|
1 | 1 | # Deep Echo State Networks |
2 | 2 |
|
3 | | -Deep Echo State Network architectures started to gain some traction recently. In this guide, we illustrate how it is possible to use ReservoirComputing.jl to build a deep ESN. |
4 | | - |
5 | | -The network implemented in this library is taken from [Gallicchio2017](@cite). It works by stacking reservoirs on top of each other, feeding the output from one into the next. The states are obtained by merging all the inner states of the stacked reservoirs. For a more in-depth explanation, refer to the paper linked above. |
| 3 | +In this example we showcase how to build a deep echo state network (DeepESN) |
| 4 | +following the work of [Gallicchio2017](@cite). The DeepESN stacks reservoirs |
| 5 | +on top of each other, feeding the output from one into the next. |
| 6 | +In the version implemented in ReservoirComputing.jl the final state is the state |
| 7 | +used for training. |
6 | 8 |
|
7 | 9 | ## Lorenz Example |
8 | 10 |
|
9 | | -For this example, we are going to reuse the Lorenz data used in the [Lorenz System Forecasting](@ref) example. |
| 11 | +We are going to reuse the Lorenz data used in the |
| 12 | +[Lorenz System Forecasting](@ref) example. |
10 | 13 |
|
11 | 14 | ```@example deep_lorenz |
12 | 15 | using OrdinaryDiffEq |
@@ -34,35 +37,30 @@ target_data = data[:, (shift + 1):(shift + train_len)] |
34 | 37 | test_data = data[:, (shift + train_len + 1):(shift + train_len + predict_len)] |
35 | 38 | ``` |
36 | 39 |
|
37 | | -Again, it is *important* to notice that the data needs to be formatted in a matrix, with the features as rows and time steps as columns, as in this example. This is needed even if the time series consists of single values. |
38 | | - |
39 | | -The construction of the ESN is also really similar. The only difference is that the reservoir can be fed as an array of reservoirs. |
| 40 | +The call for the DeepESN works similarly to the ESN. |
| 41 | +The only difference is that the reservoir (and corresponding kwargs) |
| 42 | +can be fed as an array. |
40 | 43 |
|
41 | 44 | ```@example deep_lorenz |
42 | 45 | using ReservoirComputing |
| 46 | +desn = DeepESN(input_size, [res_size, res_size], input_size; |
| 47 | + init_reservoir=rand_sparse(; radius=1.2, sparsity=6/300), |
| 48 | + state_modifiers=ExtendedSquare |
| 49 | +) |
43 | 50 |
|
44 | | -reservoirs = [rand_sparse(; radius=1.1, sparsity=0.1), |
45 | | - rand_sparse(; radius=1.2, sparsity=0.1), |
46 | | - rand_sparse(; radius=1.4, sparsity=0.1)] |
47 | | -
|
48 | | -esn = DeepESN(input_data, 3, 200; |
49 | | - reservoir=reservoirs, |
50 | | - reservoir_driver=RNN(), |
51 | | - nla_type=NLADefault(), |
52 | | - states_type=StandardStates()) |
53 | 51 | ``` |
54 | 52 |
|
55 | | -The input layer and bias can also be given as vectors, but of course, they have to be of the same size of the reservoirs vector. If they are not passed as a vector, the value passed will be used for all the layers in the deep ESN. |
56 | | - |
57 | | -In addition to using the provided functions for the construction of the layers, the user can also choose to build their own matrix, or array of matrices, and feed that into the `ESN` in the same way. |
58 | | - |
59 | 53 | The training and prediction follow the usual framework: |
60 | 54 |
|
61 | 55 | ```@example deep_lorenz |
62 | | -training_method = StandardRidge(0.0) |
63 | | -output_layer = train(esn, target_data, training_method) |
| 56 | +using Random |
| 57 | +Random.seed!(42) |
| 58 | +rng = MersenneTwister(17) |
| 59 | +
|
| 60 | +ps, st = setup(rng, esn) |
| 61 | +ps, st = train!(esn, input_data, target_data, ps, st) |
64 | 62 |
|
65 | | -output = esn(Generative(predict_len), output_layer) |
| 63 | +output, st = predict(esn, 1250, ps, st; initialdata=test[:, 1]) |
66 | 64 | ``` |
67 | 65 |
|
68 | 66 | Plotting the results: |
@@ -93,4 +91,4 @@ plot(p1, p2, p3; plot_title="Lorenz System Coordinates", |
93 | 91 | ```@bibliography |
94 | 92 | Pages = ["deep_esn.md"] |
95 | 93 | Canonical = false |
96 | | -``` |
| 94 | +``` |
0 commit comments