A 30th order Non-linear AutoRegressive Moving Average (NARMA) task with a standard reservoir
This code is available as examples/narma30_demo.py.
We first create the dataset, with a sample length of 1000 timesteps, and ten examples (this is the default value, so it is not explicitly passed) in total.
[x, y] = Oger.datasets.narma30(sample_len=1000)
Both x and y are lists of 2D numpy arrays. Oger inherets the dimensionality convention from MDP, so the rows represent timesteps and the columns represent different signals.
We then construct the reservoir node:
reservoir = Oger.nodes.ReservoirNode(input_dim=1, output_dim=100, input_scaling=0.05)
As you can see, we specify a number of parameters of the reservoir by passing keyword arguments, such as the input-dimensionality, output dimensionality and the scaling of the input weights. You can find a full list of the ReservoirNode arguments and their default values in the documentation (TODO: link).
Next, we construct the readout node which is a linear node trained using ridge regression.
readout = Oger.nodes.RidgeRegressionNode()
We use the two nodes to construct a flow and turn on verbosity:
flow = mdp.Flow([reservoir, readout], verbose=1)
We take the first nine samples of x and y, and put them in a list as follows:
data = [x[0:-1], zip(x[0:-1], y[0:-1])]
This is because flows expect their data in a certain format (taken from the MDP documentation):
'data_iterables' is a list of iterables, one for each node in the flow.The iterators returned by the iterables must return data arrays that are then used for the node training (so the data arrays are the 'x' for the nodes). Note that the data arrays are processed by the nodes which are in front of the node that gets trained, so the data dimension must match the input dimension of the first node.
Instead of a data array 'x' the iterators can also return a list or tuple, where the first entry is 'x' and the following are args for the training of the node (e.g. for supervised training).
So, in our case, the first element of the list (the x[0:-1]) is used as input for the reservoir node, and the second element of the list (the zip(x[0:-1], y[0:-1])) is used to train the linear readout, by feeding the first argument of the zip() as input to the first node, and using the second argument of the zip() to as target for training.
Our flow can then be trained on the training data:
flow.train(data)
Applying the trained flow to test-data (the tenth example in the dataset, remember that Python uses zero-based indexing!) is then as simple as:
testout = flow(x[9])
We can then compute and print the NRMSE as follows:
print "NRMSE: " + str(Oger.utils.nrmse(y[9], testout))