【LSTM】カオスなDuffing振動子をシミュレートして未来予測♬

前回の話の当然の延長として、カオスなDuffing振動子の解をシミュレートして未来予測できるのかどうかはすごく興味がわく。
ということで、今回はそこをやってみました。

###やったこと
（１）LSTMは過学習；単純な減衰振動の未来予測
（２）LSTMでシミュレート；5つのDuffing振動子の振る舞い
（３）未来予測；面倒な振る舞いを予測する
###（１）LSTMは過学習；単純な減衰振動の未来予測
コードは以下に置きました。
[LSTM/keras_lstm_sin.py ](https://github.com/MuAuan/LSTM/blob/master/keras_lstm_sin.py) 
ここでコードの主要な部分は以下のとおり

```py
tsteps = 1
batch_size = 25
epochs = 301
lahead = 2000

def gen_cosine_amp(amp=80, period=200, x0=0, xn=5000, step=1, k=0.0001):
    cos = np.zeros(((xn - x0) * step, 1, 1))
    for i in range(len(cos)):
        idx = x0 + i * step
        cos[i, 0, 0] = amp * (np.cos(2 * np.pi * idx / period))
        cos[i, 0, 0] = cos[i, 0, 0]* np.exp(-k * idx)
    return cos

cos = gen_cosine_amp()

expected_output = np.zeros((len(cos), 1))
output = np.zeros((len(cos), 1))
for i in range(len(cos) - lahead):
    expected_output[i, 0] = cos[i]
    expected_output1 = np.zeros((len(cos), 1))
output1 = np.zeros((len(cos), 1))
for i in range(len(cos)):
    expected_output1[i, 0] = cos[i]

model = Sequential()
model.add(LSTM(100,
               input_shape=(tsteps, 1),
               batch_size=batch_size,
               return_sequences=False,
               stateful=True,
              dropout=0.0))
model.add(Dense(1))
opt=Adam(lr=0.0001, beta_1=0.5, beta_2=0.999, epsilon=1e-08, decay=0.)
model.compile(loss='mse', optimizer=opt)   #'rmsprop')
model.summary()
```
そして結果は以下のとおりとなった。この図を見ると、どうも過学習になっているようだ。
![pend0hidden100lahead2000.gif](https://qiita-image-store.s3.amazonaws.com/0/233744/08d1773f-aae2-206f-9826-995694ae9690.gif)
そこでモデルのdropout=0.75, batch_size=50で以下の結果が得られた。最下段の規格化した形状はかなり再現できた。しかし、絶対値は全く再現せず、小さい。
![pend075hidden100batch50lahead2000.gif](https://qiita-image-store.s3.amazonaws.com/0/233744/cef863a3-8047-ec17-e896-13f68415d53b.gif)
###（２）LSTMでシミュレート；5つのDuffing振動子の振る舞い
コードは以下に置きました。
[LSTM/keras_lstm_duffing.py  ](https://github.com/MuAuan/LSTM/blob/master/keras_lstm_duffing.py) 
Duffing振動子の振る舞いはパラメータや初期値によっていろいろ変わるが、今回は参考で紹介されているパラメータの組み合わせで得られる５つの領域を調べた。
結果を見ると、dropoutの値を変化させてみたが、フィッティング精度は向上せず悪い。振動の周期やアップダウンの様子はある程度再現しているようだが、絶対値含め全体に未来予測の思惑ははずれたようだ。
Duffing0
![plot_x-p_duffing.png](https://qiita-image-store.s3.amazonaws.com/0/233744/a390ca72-426c-3cdc-d8f9-5310c9e1f19f.png)
![plot_duffing_300_lstm.png](https://qiita-image-store.s3.amazonaws.com/0/233744/57c4c53b-fe3b-690e-0924-72892f074d23.png)
Duffing1
![plot_x-p_duffing.png](https://qiita-image-store.s3.amazonaws.com/0/233744/33fa56d9-79be-b010-7b7e-51bcb2c25724.png)
![plot_duffing_300_lstm.png](https://qiita-image-store.s3.amazonaws.com/0/233744/bfb0abfe-7112-6358-f790-efd2c53ba59c.png)
Duffing2
![plot_x-p_duffing.png](https://qiita-image-store.s3.amazonaws.com/0/233744/b3b10fc4-fcbb-13e8-c570-93e851905db0.png)
![plot_duffing_300_lstm.png](https://qiita-image-store.s3.amazonaws.com/0/233744/aadb58db-923d-fb15-651a-16c7ebfbdb9a.png)
Duffing3
![plot_x-p_duffing.png](https://qiita-image-store.s3.amazonaws.com/0/233744/ed950ee1-66b0-772b-aa51-38486c25a738.png)
![plot_duffing_300_lstm.png](https://qiita-image-store.s3.amazonaws.com/0/233744/6a7c01bd-0546-05d0-b3f5-478564849a33.png)
Duffing4
![plot_x-p_duffing.png](https://qiita-image-store.s3.amazonaws.com/0/233744/79e2250d-348d-a59e-86b5-37e80aebe615.png)
![plot_duffing_300_lstm.png](https://qiita-image-store.s3.amazonaws.com/0/233744/1c5ff275-6420-1d73-8514-120856466cb8.png)
###（３）未来予測；面倒な振る舞いを予測する
とはいえ、単純な減衰振動のシミュレーションのときを考えると、dropout=0でlahead=1の場合の結果では絶対値含め予測できていた。
ということで、Duffing振動子の場合も同じようにやってみた。
Duffing0と類似の振る舞いは以下のとおり、絶対値含め再現できた。ということで、少なくとも１個先の未来は予測できたことになる。
![plot_x-p_duffing.png](https://qiita-image-store.s3.amazonaws.com/0/233744/90b5fcf0-a5c2-7cdd-6913-472a27aaa25f.png)
![plot_duffing_600_lstm.png](https://qiita-image-store.s3.amazonaws.com/0/233744/1c461c95-5c77-fe1d-eb83-e84f590d096a.png)
しかし、この状態は上の５つの状態の中でも一番再現性がよかった部分なので、ある意味つまらない。そこで、上で一番壊滅的な結果であるDuffing4と類似の場合についてどこまでの未来を予測可能なのかをやってみた。
Duffing4  lahead=1 [0,200]
つまりこの領域でも１個未来は予測できた。
![plot_x-p_duffing.png](https://qiita-image-store.s3.amazonaws.com/0/233744/62f36d00-382f-87dc-9d97-4c50a46076ad.png)
![Duffing4Drop0lahead1.gif](https://qiita-image-store.s3.amazonaws.com/0/233744/b8f5ee76-7ff8-9531-0573-167f99350113.gif)
以下は100個未来予測できたことを示す。
Duffing4  lahead=100 [0,200]
![Duffing4Drop0lahead100.gif](https://qiita-image-store.s3.amazonaws.com/0/233744/6b3cd28f-8f0e-abef-5390-c4a4664032ce.gif)
なんとなく上記の領域は安定的な振動にも見えるのでもう少し不安定そうな部分の予測をやってみた。
結果は以下の通り、最初は予測しているが、フィッティングが進むにつれて、過学習が発生して、予測精度が落ちていることが分かる。とはいえ、カオス的な振動の未来予測ができるということでとても驚いた。
Duffing4　lahead=100 t=[0,168]
![Duffing4Drop0lahead100[0,168].gif](https://qiita-image-store.s3.amazonaws.com/0/233744/c56fb889-3638-11d8-8ece-edb799e1f7ce.gif)
lahead=200にすると、最初は予測できているが、過学習が始まるとほんの一ピーク程度を除いて予測はほとんどできていない。
Duffing4　lahead=200 t=[0,168]
![Duffing4Drop0lahead200[0,168].gif](https://qiita-image-store.s3.amazonaws.com/0/233744/f9d26c1e-b27c-ad1c-991e-a9e78ade6182.gif)
###まとめ
・カオスなDuffing振動子の未来予測ができた！
・LSTMは過学習を起こし、Dropoutすると絶対値予測が失われるようである

・Duffing振動子の領域の相図的な網羅性ができていないので、振る舞いのすべてを表現できていない（今回の領域も今一つ統一性が取れていない）
・位相空間の振る舞いは運動の指紋的なものであり、これで分類する手法を確立したい
・今回の手法は一般的なので幾つかの実際の系（株価、太陽活動、地震、天気など）に適用してみようと思う

・相図の参考
[Duffing oscillator ](http://www.scholarpedia.org/article/Duffing_oscillator)