Pythonのニューラルネットワークライブラリkerasを用いて,RNNの1つであるLSTM(Long Short-Term Memory)による時系列データの学習をさせてみました.
これまでPythonを利用する際はPandasを主に使用していたため,今回はnumpyのndarrayの取り扱いやkerasの学習データのフォーマットを調べながら参考記事と同様のモデル作成と学習・予測をしています.
本記事のコード全体は以下に置いてあります.
github.com
環境
開発環境の用意
Anacondaをインストールし,Anaconda Promptから以下2つのコマンドを実行します.
conda install keras
conda install tensorflow
今回GPUは使用しませんでした.
入力データの作成
学習させる入力データとして,ノイズを含むsin波とcos波を作成します.
import numpy as np import matplotlib.pyplot as plt #sinとcosの波形を作る cycle = 2 # 周期の数 period = 100 # 1周期の時間 x = np.arange(0, cycle*period) sin = np.sin(2.0 * np.pi * x / period) cos = np.cos(2.0 * np.pi * x / period) # numpy のndarrayを横に連結 y = np.vstack((sin, cos)) # ノイズを乗せる noise = np.random.uniform(-0.05, 0.05, size=y.shape) y = y + noise # 波形の確認 plt.plot(x, y[0]) plt.plot(x, y[1])
入力データの形式変更
生成したnumpy配列をkerasに入力するデータの形式となるように変更します.
input_length = 10 # 1入力データの長さを10個とする X = np.zeros([len(x)-input_length, input_length-1, 2]) #(190, 9, 2) Y = np.zeros([len(x)-input_length, 2]) #(190, 2) for i in range(0, len(X)): X[i, :, :] = y[:,i:i+input_length-1].T Y[i, :] = y[:,i+input_length-1].T
LSTMモデルの作成
LSTMモデルを作成します.sinとcosの2つの波形を予測するので入力ユニットと出力ユニットはそれぞれ2ずつ,隠れLSTM層のユニットは100としました.
from keras.layers.recurrent import LSTM from keras.models import Sequential from keras.layers import Dense, Activation from keras.optimizers import Adam # モデルの作成 model = Sequential() # LSTM層の追加,隠れユニット100,入力は10×2サイズ num_in_units = 2 num_hidden_units = 100 model.add( LSTM(units=num_hidden_units, input_shape=(input_length-1, num_in_units), kernel_initializer="random_normal", stateful=False, return_sequences=False ) ) # 全結合出力層の追加,出力は2ユニット num_out_units = 2 model.add(Dense(units=num_out_units, kernel_initializer="random_normal")) # 活性化関数は線形関数 model.add(Activation('linear')) # MSEを誤差とし,Adamで最適化する model.compile(loss="mean_squared_error", optimizer=Adam(lr=0.01, beta_1=0.9, beta_2=0.999))
学習の実行
fit()で学習を実行します.今回はepochを20,バッチサイズを32としました.
model.fit(X, Y, epochs=20, batch_size=32, validation_split=0.1)
学習中は以下のようなメッセージが出力されます.
Train on 171 samples, validate on 19 samples Epoch 1/20 171/171 [==============================] - 4s 23ms/step - loss: 0.2567 - val_loss: 0.0184 Epoch 2/20 171/171 [==============================] - 0s 316us/step - loss: 0.0496 - val_loss: 0.0168 (中略) Epoch 20/20 171/171 [==============================] - 0s 292us/step - loss: 0.0012 - val_loss: 0.0011
最終的に1割の検証データで誤差(MSE)の値が0.0011まで低減できています.
データ予測の実行
学習データをそのまま使った予測を実行してみます.
Y_predict = model.predict(X) plt.figure() plt.plot(Y[:, 0]) plt.plot(Y_predict[:, 0], ".") plt.figure() plt.plot(Y[:, 1]) plt.plot(Y_predict[:, 1], ".")
元の波形がノイズを含んでいても,良い精度で元のsin, cos波形を推測できていることがわかります.
LSTMは時系列のデータ予測モデルであり,予測した時刻の出力データを入力としてさらにその先の時刻のデータを繰り返し予測して出力ことができます. 予測は以下のように出力値を含んだデータを入力としてpredict()を繰り返し実行すればできます.
Y_future = np.zeros([300, 2]) # 予測値を格納する配列を用意 Y_future[:input_length-1, :] = X[-1, :, :] # Xの最終のinput_lengthのデータを入力とする for i in range(input_length-1,len(Y_future)): x_temp = Y_future[i-input_length+1:i, :].reshape(1, input_length-1, -1) y_temp = model.predict(x_temp) Y_future[i, :] = y_temp plt.plot(Y_future[input_length:])
参考文献
WindowsでKerasを用いたDeep Learning開発環境を整備する
Keras Documentation
kerasでlstmを学習する手順を整理してみた
入門 Keras (7) 最終回:リカレントニューラルネットワークを体験する
深層学習ライブラリKerasでRNNを使ってsin波予測