Question

I'm doing timeseries prediction with Matlab's NN toolbox using a layer-recurrent network (layrecnet) with layerDelays = 1:2 and hiddenSize = 5 (I've used a few other sizes for the one hidden layer with similar results). I modified the network to take multiple inputs (up to 5 or 10) and the associated change to net.inputConnect, and it works (that is, I can train it with good results).

As soon as I change divideFcn from the default to divideblock it no longer works, giving me this error while running the train function:

Error in divideblock>divide_indices (line 108)
  testInd = (1:numTest)+valInd(end);

Error in divideblock (line 65)
    [out1,out2,out3] = divide_indices(in1,params);

Error in nntraining.setup (line 176)
      [trainInd,valInd,testInd] =
      feval(net.divideFcn,Q,net.divideParam);

Error in network/train (line 292)
    [net,rawData,tr,err] =
    nntraining.setup(net,net.trainFcn,X,Xi,Ai,T,EW,~isGPUArray);

Through debugging mode, I found that valInd is an empty array, which is determined by a value Q in the (built-in) nntraining.setup() function. Q is set by another function (nntraining.config), which I have no access to. Now, obviously I don't believe the error is in those functions, but I was trying to find the error by tracing back the problem. And now I'm up against a wall.

This boils down to 2 questions

  1. I want to use divideblock instead of dividerand because I want the layer delays to take advantage of the signal's temporal structure (it's highly periodic - leg joint angles during walking). Am I mistaken in thinking that dividerand will not be able to take advantage of this temporal structure?

  2. Is there some idiosyncrasy of how the train function interacts with divideblock that means I need to change something about my data format?

Thanks much!

Was it helpful?

Solution

The problem was the network's divideMode parameter. The default value for static networks is 'sample', and for dynamic networks 'time'. I haven't found a clear explanation of what the distinction between the two is, but when I initialized a layrecnet (a layer-recurrent network, supposedly a dynamic network) it would initialize to 'sample' instead of 'time'. As a result, it did not divide the data into training, validation, and test sets, but trained on the entire input. Changing that value manually during setup fixed the problem.

From the toolbox documentation:

This property defines the target data dimensions which to divide up when the data division function is called.

In terms of time series data, this seems to correlate to dividing across time versus across trials, so to speak. That is, if data were input as a set of concurrent trials ("concurrent" and "sequential" are sort of data types for NN inputs) and divideMode were set to 'sample', it would pick a subset of trials for training vs. validation vs. testing. If somebody sees this and can contribute a clearer explanation, please do.

OTHER TIPS

For dynamic networks (as layrecnet) you should use this code for block data division:

net.divideFcn = 'divideblock'; % Divide targets into three sets using blocks of indices

net.divideParam.trainRatio = 0.6; % Ratio of targets for training. Default = 0.7.

net.divideParam.valRatio = 0.2; % Ratio of targets for validation. Default = 0.15.

net.divideParam.testRatio = 0.2; % Ratio of targets for testing. Default = 0.15.

net.divideMode = 'time'; % 'time' for dynamic networks or 'sample' for static networks

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top