Last active
May 19, 2021 18:26
-
-
Save sdwfrost/d87bda9e0df9f022fdffcabb584cfec9 to your computer and use it in GitHub Desktop.
Fitting a sine curve using an echo state network in ReservoirComputing.jl
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Sine regression using echo state networks in ReservoirComputing.jl | |
## Loading libraries | |
```julia | |
using Random | |
using Distributions | |
using Plots | |
using StatsPlots | |
using ParameterizedFunctions | |
using ReservoirComputing | |
``` | |
Fix the random number seed for reproducibility. | |
```julia | |
Random.seed!(1234) | |
``` | |
## Generating data | |
Generate 401 data points scattered around a sine curve. | |
```julia | |
x = collect(0.0:0.01:4.0) | |
z = 4 .* sin.(2*π*x .- π/2) | |
plot(x, z, legend=:bottomright, label="observed") | |
``` | |
## Generate train and test datasets | |
```julia | |
shift = 1 | |
train_len = 201 | |
predict_len = 200 | |
data = reshape(z,1,length(z)) | |
xtrain = x[shift:shift+train_len-1] | |
xtest = x[shift+train_len:shift+train_len+predict_len-1] | |
train = data[:,shift:shift+train_len-1] | |
test = data[:,shift+train_len:shift+train_len+predict_len-1] | |
``` | |
## Define and train echo state network | |
```julia | |
approx_res_size = 20 #size of the reservoir | |
radius = 1.1 #desired spectral radius | |
activation = tanh #neuron activation function | |
degree = 6 #degree of connectivity of the reservoir | |
sigma = 0.1 # input weight scaling | |
beta = 0.0 #ridge | |
alpha = 1.0 #leaky coefficient | |
nla_type = NLADefault() #non linear algorithm for the states | |
extended_states = false # if true extends the states with the input | |
``` | |
```julia | |
esn = ESN(approx_res_size, | |
train, | |
degree, | |
radius, | |
activation = activation, | |
sigma = sigma, | |
alpha = alpha, | |
nla_type = nla_type, | |
extended_states = extended_states) | |
``` | |
```julia | |
W_out = ESNtrain(esn, beta) | |
output = ESNpredict(esn, predict_len, W_out) #applies standard ridge regression for the training | |
``` | |
```julia | |
fitted = ESNfitted(esn,W_out) | |
fitted_aut = ESNfitted(esn,W_out;autonomous=true) | |
``` | |
## Plotting | |
### Input states | |
```julia | |
plot(xtrain, vec(fitted), label="fitted") | |
plot!(xtrain, vec(fitted_aut), label="fitted autonomous") | |
plot!(xtrain, vec(train), label="observed") | |
``` | |
### Predicted states | |
```julia | |
plot(xtest, vec(output), label="predicted") | |
plot!(xtest, vec(test), label="actual") | |
``` | |
```julia | |
scatter(vec(test),vec(output)) | |
``` | |
## Generating Poisson data | |
Generate 401 data points scattered around a sine curve. | |
```julia | |
ez = exp.(z) | |
yp = rand.(Poisson.(ez)) | |
``` | |
```julia | |
plot(x,ez,legend=false) | |
scatter!(x,yp) | |
``` | |
How to adapt the ESNs to predict `yp`? | |
## Generating binary data | |
Now for binary data. | |
```julia | |
invlogit(x) = exp(x)/(1+exp(x)) | |
lz = invlogit.(z) | |
yb = rand.(Bernoulli.(lz)) | |
``` | |
```julia | |
plot(x,lz,legend=false) | |
scatter!(x,yb) | |
``` | |
## Multiple sequences (same length) | |
```julia | |
w=50 | |
s=19 | |
zn = [] | |
xn = [] | |
for e in ((@view z[i:i+w-1]) for i in 1:s:length(z)-w+1) | |
push!(zn,e) | |
end | |
for e in ((@view x[i:i+w-1]) for i in 1:s:length(x)-w+1) | |
push!(xn,e) | |
end | |
``` | |
```julia | |
plot(zn,legend=false) | |
``` | |
## Multiple sequences (unequal length) | |
```julia | |
l = rand(2:w,size(zn)[1]) | |
zu = [zn[i][1:l[i]] for i in 1:(size(zn)[1])] | |
xu = [xn[i][1:l[i]] for i in 1:(size(xn)[1])] | |
``` | |
```julia | |
plot(zu,legend=false) | |
``` |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment