kerasとLSTMで未来予測を行う方法をどこよりも詳しく紹介します

kerasで未来予測を行うにはどうすれば良いの?

趣旨

LSTMを使えば未来予測が出来るよ。やり方を紹介するね。

趣旨

当記事について

kerasのLSTMを使って未来予測を行う方法を解説します。(※)
機械学習は割と手間ですが、たった3行のソースでお手軽に機械学習が出来る自作ライブラリも紹介します。
対象読者は機械学習やkerasの初心者以上を想定します。
※専門的に言うと未来予測ではなく回帰ですが、本記事では一般に伝わりやすい未来予測という表現にします。

1.LSTMとは?

LSTM(Long short-term memory)は2020年現在で時系列データの機械学習を行うのに最も適したディープニューラルネットワークです。
連続するデータの流れを学習し、データの波形を予測します。

LSTMの構造

LSTMの構造

LSTMはRNN(リカレントニューラルネットワーク)の派生のネットワークで、内部にループを持ち、情報を持続させることができる様になっています。
これにより、過去の重み付けを踏まえて未来の重み付けが行われます。
LSTMはRNNの内部にループを持つという構造に加えて、忘却ゲートを設けられています。忘却ゲートを設けることでRNNでは出来なかった、長期の連続データの学習が出来る様になっています。

LSTMで時系列データの機械学習を行う局面

  1. 文章・対話の生成
  2. 音素・音声認識
  3. 映像認識
  4. 株価予測

時系列データの機械学習の仕組みを式で表すと?

$$x_{n+1}=f(x_1, x_2, x_3, ・・・, x_n)$$

となる\(f()\)を求めるのが時系列データの機械学習の目的です。

\(f()\)を求めるために、

$$x_{t}=f(x_1, x_2, x_3,・・・)$$

$$x_{t+1}=f(x_2, x_3, x_4,・・・)$$

$$x_{t+2}=f(x_3, x_4, x_5,・・・)$$

・・・

の様に時系列データを大量に用意して、どの式にも成り立つ\(f()\)を求めます。

2.kerasでLSTMを行うサンプル(学習)

LSTMのサンプル学習データ(sin波)

sin波のデータを用意しました。

LSTMのサンプル学習データのイメージ(sin波)

sin波の学習データ

LSTMのサンプル学習データ(tran.csv)

x1,x2,x3,x4,x5,x6,x7,x8,x9,x10,x11,x12,x13,x14,x15,x16,x17,x18,x19,x20,x21,x22,x23,x24,x25,y
0.30,0.56,0.78,0.93,1.00,0.97,0.86,0.68,0.43,0.14,-0.16,-0.44,-0.69,-0.87,-0.98,-1.00,-0.93,-0.77,-0.55,-0.28,0.02,0.31,0.58,0.79,0.94,1.00
0.56,0.78,0.93,1.00,0.97,0.86,0.68,0.43,0.14,-0.16,-0.44,-0.69,-0.87,-0.98,-1.00,-0.93,-0.77,-0.55,-0.28,0.02,0.31,0.58,0.79,0.94,1.00,0.97
0.78,0.93,1.00,0.97,0.86,0.68,0.43,0.14,-0.16,-0.44,-0.69,-0.87,-0.98,-1.00,-0.93,-0.77,-0.55,-0.28,0.02,0.31,0.58,0.79,0.94,1.00,0.97,0.85
0.93,1.00,0.97,0.86,0.68,0.43,0.14,-0.16,-0.44,-0.69,-0.87,-0.98,-1.00,-0.93,-0.77,-0.55,-0.28,0.02,0.31,0.58,0.79,0.94,1.00,0.97,0.85,0.66
・・・

LSTMのサンプル学習プログラム(tran.py)

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from abc import ABCMeta, abstractmethod
from pandas import Series,DataFrame
from keras.callbacks import EarlyStopping
from keras.models import Sequential
from keras.layers.core import Dense, Activation
from keras.layers.recurrent import LSTM
from keras.optimizers import Adam
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
import logging

# 出力ファイルなどの定義
tran_ds_file = './tran.csv'  # 学習データファイル
tran_result = './tran_result.png' # 学習結果ファイル
hdf5_file = './param.hdf5' # 学習済パラメタファイル
batch_size = 300 # バッチサイズ
validation_split = 0.1  # 学習データの中の訓練データとテストデータの割合

# 1.学習データ読込
def loadData():
  # CSVデータ読み込み
  logging.info('dataset is [' + tran_ds_file + ']')
  csv = pd.read_csv(tran_ds_file, sep=',', header=0)

  logging.info('-- data tran_In(x) --------------------------')
  tran_In = DataFrame(csv.drop('y',axis=1))
  logging.info(tran_In)

  logging.info('-- data tran_Out(y) -------------------------')
  tran_Out = DataFrame(csv['y'])
  logging.info(tran_Out)

  # 読み込んだ学習データをLSTMで扱える様に加工
  logging.info('-- reshape data tran_In --------------------------')
  x = tran_In
  tran_In = np.array(x).reshape(len(x), x.shape[1] , 1)
  logging.info(len(tran_In))

  logging.info('-- reshape data tran_Out --------------------------')
  y = tran_Out
  tran_Out = np.array(y).reshape(len(y), 1)
  logging.info(len(tran_Out))

  return tran_In, tran_Out

# LSTMモデルの生成
def createModel(in_size, out_size, n_hidden):
  # LSTM学習モデルの生成
  model = Sequential()
  model.add(LSTM(n_hidden, batch_input_shape=(None, in_size, out_size), return_sequences=False))
  model.add(Dense(out_size))
  model.add(Activation("linear"))
  optimizer = Adam(lr=0.001)
  model.compile(loss="mean_squared_error", optimizer=optimizer)
  return model

# 学習
def tran(model, tran_In, tran_Out, epochs):
  # 学習
  early_stopping = EarlyStopping(monitor='val_loss', mode='auto', patience=20)
  model.fit(tran_In, tran_Out,
    batch_size = batch_size,
    epochs = epochs,
    validation_split = validation_split,
    callbacks=[early_stopping]
    )
  # 学習済パラメタ保存
  model.save_weights(hdf5_file)
  logging.info('hdf5_file saved to ' + hdf5_file)
  # 学習済モデル返却
  return model

# 学習結果の描画
def draw_tran_result(model, tran_In, tran_Out):
  out = model.predict(tran_In)
  plt.figure()
  plt.plot(range(0, len(out)), out, color="b", label="actual")
  plt.plot(range(0, len(tran_Out)), tran_Out, color="r", label="expected")
  plt.legend()
  plt.savefig(tran_result)
  logging.info('tran_result saved to ' + tran_result)

# メイン関数
if __name__ == "__main__":
  logging.basicConfig(level=logging.INFO)

  # 1.学習データ読込
  tran_In, tran_Out = loadData()
  # 2.LSTMモデル生成(入力データ項目数=25(x1,x2,・・・,x25)、教師データ=1(y)、隠れ層=100)
  model = createModel(25, 1, 300)
  # 3.学習(epochs = 30)
  model = tran(model, tran_In, tran_Out, 30)
  # 4.学習結果の描画
  draw_tran_result(model, tran_In, tran_Out)

LSTMのサンプルの実行結果(ログ)

$ python tran.py
Using TensorFlow backend.
2020-02-09 09:46:04.085050: W tensorflow/stream_executor/platform/default/dso_loader.cc:55] Could not load dynamic library 'libnvinfer.so.6'; dlerror: libnvinfer.so.6: cannot open shared object file: No such file or directory
2020-02-09 09:46:04.085180: W tensorflow/stream_executor/platform/default/dso_loader.cc:55] Could not load dynamic library 'libnvinfer_plugin.so.6'; dlerror: libnvinfer_plugin.so.6: cannot open shared object file: No such file or directory
2020-02-09 09:46:04.085196: W tensorflow/compiler/tf2tensorrt/utils/py_utils.cc:30] Cannot dlopen some TensorRT libraries. If you would like to use Nvidia GPU with TensorRT, please make sure the missing libraries mentioned above are installed properly.
INFO:user1:dataset is [./tran.csv]
INFO:user1:-- data tran_In(x) --------------------------
INFO:user1:       x1    x2    x3    x4    x5    x6    x7    x8    x9  ...   x17   x18   x19   x20   x21   x22   x23   x24   x25
0    0.30  0.56  0.78  0.93  1.00  0.97  0.86  0.68  0.43  ... -0.93 -0.77 -0.55 -0.28  0.02  0.31  0.58  0.79  0.94
1    0.56  0.78  0.93  1.00  0.97  0.86  0.68  0.43  0.14  ... -0.77 -0.55 -0.28  0.02  0.31  0.58  0.79  0.94  1.00
2    0.78  0.93  1.00  0.97  0.86  0.68  0.43  0.14 -0.16  ... -0.55 -0.28  0.02  0.31  0.58  0.79  0.94  1.00  0.97
3    0.93  1.00  0.97  0.86  0.68  0.43  0.14 -0.16 -0.44  ... -0.28  0.02  0.31  0.58  0.79  0.94  1.00  0.97  0.85
4    1.00  0.97  0.86  0.68  0.43  0.14 -0.16 -0.44 -0.69  ...  0.02  0.31  0.58  0.79  0.94  1.00  0.97  0.85  0.66
..    ...   ...   ...   ...   ...   ...   ...   ...   ...  ...   ...   ...   ...   ...   ...   ...   ...   ...   ...
195  0.78  0.56  0.29 -0.01 -0.30 -0.57 -0.79 -0.94 -1.00  ...  0.69  0.88  0.98  1.00  0.92  0.77  0.54  0.27 -0.03
196  0.56  0.29 -0.01 -0.30 -0.57 -0.79 -0.94 -1.00 -0.97  ...  0.88  0.98  1.00  0.92  0.77  0.54  0.27 -0.03 -0.32
197  0.29 -0.01 -0.30 -0.57 -0.79 -0.94 -1.00 -0.97 -0.86  ...  0.98  1.00  0.92  0.77  0.54  0.27 -0.03 -0.32 -0.59
198 -0.01 -0.30 -0.57 -0.79 -0.94 -1.00 -0.97 -0.86 -0.67  ...  1.00  0.92  0.77  0.54  0.27 -0.03 -0.32 -0.59 -0.80
199 -0.30 -0.57 -0.79 -0.94 -1.00 -0.97 -0.86 -0.67 -0.42  ...  0.92  0.77  0.54  0.27 -0.03 -0.32 -0.59 -0.80 -0.94

[200 rows x 25 columns]
INFO:user1:-- data tran_Out(y) -------------------------
INFO:user1:        y
0    1.00
1    0.97
2    0.85
3    0.66
4    0.41
..    ...
195 -0.32
196 -0.59
197 -0.80
198 -0.94
199 -1.00

[200 rows x 1 columns]
INFO:user1:-- reshape data tran_In --------------------------
INFO:user1:200
INFO:user1:-- reshape data tran_Out --------------------------
INFO:user1:200
2020-02-09 09:46:05.570519: W tensorflow/stream_executor/platform/default/dso_loader.cc:55] Could not load dynamic library 'libcuda.so.1'; dlerror: libcuda.so.1: cannot open shared object file: No such file or directory
2020-02-09 09:46:05.570581: E tensorflow/stream_executor/cuda/cuda_driver.cc:351] failed call to cuInit: UNKNOWN ERROR (303)
2020-02-09 09:46:05.570648: I tensorflow/stream_executor/cuda/cuda_diagnostics.cc:156] kernel driver does not appear to be running on this host (v133-18-208-186.vir.kagoya.net): /proc/driver/nvidia/version does not exist
2020-02-09 09:46:05.571059: I tensorflow/core/platform/cpu_feature_guard.cc:142] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2 FMA
2020-02-09 09:46:05.582694: I tensorflow/core/platform/profile_utils/cpu_utils.cc:94] CPU Frequency: 2596990000 Hz
2020-02-09 09:46:05.583002: I tensorflow/compiler/xla/service/service.cc:168] XLA service 0x55d27eec9060 initialized for platform Host (this does not guarantee that XLA will be used). Devices:
2020-02-09 09:46:05.583044: I tensorflow/compiler/xla/service/service.cc:176]   StreamExecutor device (0): Host, Default Version
Train on 180 samples, validate on 20 samples
Epoch 1/30
180/180 [==============================] - 1s 5ms/step - loss: 0.5397 - val_loss: 0.4508
Epoch 2/30
180/180 [==============================] - 0s 2ms/step - loss: 0.4760 - val_loss: 0.3858
Epoch 3/30
180/180 [==============================] - 0s 2ms/step - loss: 0.4081 - val_loss: 0.3095
・・・
Epoch 30/30
180/180 [==============================] - 0s 1ms/step - loss: 0.0103 - val_loss: 0.0083
INFO:user1:hdf5_file saved to ./param.hdf5
INFO:user1:tran_result saved to ./tran_result.png

LSTMのサンプルの学習結果(tran_result.png)

Epochs(思考回数)が30の場合の学習結果

sin波の機械学習結果

うーん、Epochs(思考回数)が30だとちょっと外していますね・・・。

Epochs(思考回数)が100の場合の学習結果

sin波の機械学習結果

Epochs(思考回数)を100にしたら、正しく学習されました。

これで、学習に使ったデータであれば、正しい結果を算出できる機械学習モデル(AI)が出来上がりました。
次節では、これを使って未来を予想してみます。

3.kerasでLSTMを行うサンプル(予測)

LSTMによるAI未来予測の方法

LSTMで学習したモデルは1つ先の未来を予測できるので、その結果を元に次の未来を予測することで、先の先の未来を予測することが出来ます。

LSTMの未来予測方法

LSTMによるAI未来予測プログラム(predict.py)

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from abc import ABCMeta, abstractmethod
from pandas import Series,DataFrame
from keras.callbacks import EarlyStopping
from keras.models import Sequential
from keras.layers.core import Dense, Activation
from keras.layers.recurrent import LSTM
from keras.optimizers import Adam
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
import logging

tran_ds_file = './tran.csv'  # 学習データファイル
predict_result = './predict_result.png' # 予想結果ファイル
hdf5_file = './param.hdf5' # 学習済パラメタファイル

# 1.学習データ読込
def loadData():
  # CSVデータ読み込み
  logging.info('dataset is [' + tran_ds_file + ']')
  csv = pd.read_csv(tran_ds_file, sep=',', header=0)

  logging.info('-- data tran_In(x) --------------------------')
  tran_In = DataFrame(csv.drop('y',axis=1))
  logging.info(tran_In)

  logging.info('-- data tran_Out(y) -------------------------')
  tran_Out = DataFrame(csv['y'])
  logging.info(tran_Out)

  # 読み込んだ学習データをLSTMで扱える様に加工
  logging.info('-- reshape data tran_In --------------------------')
  x = tran_In
  tran_In = np.array(x).reshape(len(x), x.shape[1] , 1)
  logging.info(len(tran_In))

  logging.info('-- reshape data tran_Out --------------------------')
  y = tran_Out
  tran_Out = np.array(y).reshape(len(y), 1)
  logging.info(len(tran_Out))

  return tran_In, tran_Out

# LSTMモデルを学習済パラメタから復元
def createModel(in_size, out_size, n_hidden):
  # LSTM学習モデルの生成
  model = Sequential()
  model.add(LSTM(n_hidden, batch_input_shape=(None, in_size, out_size), return_sequences=False))
  model.add(Dense(out_size))
  model.add(Activation("linear"))
  optimizer = Adam(lr=0.001)
  model.compile(loss="mean_squared_error", optimizer=optimizer)

  # 学習済パラメタの読み込み
  model.load_weights(hdf5_file)
  return model

# 予測
def predict(model, tran_In, predict_term):
  # 学習データの最後のデータを取得
  curIn = tran_In[len(tran_In) - 1]
  logging.info('-- data start curIn(x) --------------------------')
  logging.info(curIn)

  # 指定された期間まで順番に予測する
  # 0 = 学習データの最後
  # 1~ = 未来の予測
  outSum = np.empty((0))
  term = 0
  while term <= predict_term:
    # 1つ先の未来を予測
    curOut = model.predict(np.reshape(curIn, (1, len(curIn), 1)))
    # 予測結果をcurInの最後に追加。一番古いcurInの値は削除
    curIn = np.delete(curIn, 0)
    curIn = np.append(curIn, curOut)
    # 予測結果を予測結果集計に追加
    outSum = np.append(outSum, curOut)
    if (term != 0) and (term % 10 == 0):
      logging.info('term ' + str(term) + ' finished.')
    term += 1
  return outSum

# 予測結果の描画
def draw_predict_result(out):
  plt.figure()
  plt.plot(range(0, len(out)), out, color="b", label="out")
  plt.savefig(predict_result)
  logging.info('predict_result saved to ' + predict_result)

# メイン関数
if __name__ == "__main__":
  logging.basicConfig(level=logging.INFO)

  # 1.学習データ読込(未来予測の初期データとして使用)
  tran_In, tran_Out = loadData()
  # 2.LSTMモデルを学習済パラメタから復元
  model = createModel(25, 1, 300)
  # 3.予測(予測期間100)
  out = predict(model, tran_In, 100)
  # 4.予測結果の描画
  draw_predict_result(out)

実行結果(ログ)

$ python predict.py
Using TensorFlow backend.
2020-02-09 10:40:42.776335: W tensorflow/stream_executor/platform/default/dso_loader.cc:55] Could not load dynamic library 'libnvinfer.so.6'; dlerror: libnvinfer.so.6: cannot open shared object file: No such file or directory
2020-02-09 10:40:42.776515: W tensorflow/stream_executor/platform/default/dso_loader.cc:55] Could not load dynamic library 'libnvinfer_plugin.so.6'; dlerror: libnvinfer_plugin.so.6: cannot open shared object file: No such file or directory
2020-02-09 10:40:42.776533: W tensorflow/compiler/tf2tensorrt/utils/py_utils.cc:30] Cannot dlopen some TensorRT libraries. If you would like to use Nvidia GPU with TensorRT, please make sure the missing libraries mentioned above are installed properly.
INFO:user1:dataset is [./tran.csv]
INFO:user1:-- data tran_In(x) --------------------------
INFO:user1:       x1    x2    x3    x4    x5    x6    x7    x8    x9  ...   x17   x18   x19   x20   x21   x22   x23   x24   x25
0    0.30  0.56  0.78  0.93  1.00  0.97  0.86  0.68  0.43  ... -0.93 -0.77 -0.55 -0.28  0.02  0.31  0.58  0.79  0.94
1    0.56  0.78  0.93  1.00  0.97  0.86  0.68  0.43  0.14  ... -0.77 -0.55 -0.28  0.02  0.31  0.58  0.79  0.94  1.00
2    0.78  0.93  1.00  0.97  0.86  0.68  0.43  0.14 -0.16  ... -0.55 -0.28  0.02  0.31  0.58  0.79  0.94  1.00  0.97
3    0.93  1.00  0.97  0.86  0.68  0.43  0.14 -0.16 -0.44  ... -0.28  0.02  0.31  0.58  0.79  0.94  1.00  0.97  0.85
4    1.00  0.97  0.86  0.68  0.43  0.14 -0.16 -0.44 -0.69  ...  0.02  0.31  0.58  0.79  0.94  1.00  0.97  0.85  0.66
..    ...   ...   ...   ...   ...   ...   ...   ...   ...  ...   ...   ...   ...   ...   ...   ...   ...   ...   ...
195  0.78  0.56  0.29 -0.01 -0.30 -0.57 -0.79 -0.94 -1.00  ...  0.69  0.88  0.98  1.00  0.92  0.77  0.54  0.27 -0.03
196  0.56  0.29 -0.01 -0.30 -0.57 -0.79 -0.94 -1.00 -0.97  ...  0.88  0.98  1.00  0.92  0.77  0.54  0.27 -0.03 -0.32
197  0.29 -0.01 -0.30 -0.57 -0.79 -0.94 -1.00 -0.97 -0.86  ...  0.98  1.00  0.92  0.77  0.54  0.27 -0.03 -0.32 -0.59
198 -0.01 -0.30 -0.57 -0.79 -0.94 -1.00 -0.97 -0.86 -0.67  ...  1.00  0.92  0.77  0.54  0.27 -0.03 -0.32 -0.59 -0.80
199 -0.30 -0.57 -0.79 -0.94 -1.00 -0.97 -0.86 -0.67 -0.42  ...  0.92  0.77  0.54  0.27 -0.03 -0.32 -0.59 -0.80 -0.94

[200 rows x 25 columns]
INFO:user1:-- data tran_Out(y) -------------------------
INFO:user1:        y
0    1.00
1    0.97
2    0.85
3    0.66
4    0.41
..    ...
195 -0.32
196 -0.59
197 -0.80
198 -0.94
199 -1.00

[200 rows x 1 columns]
INFO:user1:-- reshape data tran_In --------------------------
INFO:user1:200
INFO:user1:-- reshape data tran_Out --------------------------
INFO:user1:200
2020-02-09 10:40:43.998191: W tensorflow/stream_executor/platform/default/dso_loader.cc:55] Could not load dynamic library 'libcuda.so.1'; dlerror: libcuda.so.1: cannot open shared object file: No such file or directory
2020-02-09 10:40:43.998243: E tensorflow/stream_executor/cuda/cuda_driver.cc:351] failed call to cuInit: UNKNOWN ERROR (303)
2020-02-09 10:40:43.998309: I tensorflow/stream_executor/cuda/cuda_diagnostics.cc:156] kernel driver does not appear to be running on this host (v133-18-208-186.vir.kagoya.net): /proc/driver/nvidia/version does not exist
2020-02-09 10:40:43.998620: I tensorflow/core/platform/cpu_feature_guard.cc:142] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2 FMA
2020-02-09 10:40:44.008282: I tensorflow/core/platform/profile_utils/cpu_utils.cc:94] CPU Frequency: 2596990000 Hz
2020-02-09 10:40:44.008577: I tensorflow/compiler/xla/service/service.cc:168] XLA service 0x5609e0320f70 initialized for platform Host (this does not guarantee that XLA will be used). Devices:
2020-02-09 10:40:44.008601: I tensorflow/compiler/xla/service/service.cc:176]   StreamExecutor device (0): Host, Default Version
INFO:user1:-- data start curIn(x) --------------------------
INFO:user1:[[-0.3 ]
 [-0.57]
 [-0.79]
 [-0.94]
 [-1.  ]
・・・
 [-0.94]]
INFO:user1:term 10 finished.
INFO:user1:term 20 finished.
INFO:user1:term 30 finished.
INFO:user1:term 40 finished.
INFO:user1:term 50 finished.
INFO:user1:term 60 finished.
INFO:user1:term 70 finished.
INFO:user1:term 80 finished.
INFO:user1:term 90 finished.
INFO:user1:term 100 finished.
INFO:user1:predict_result saved to ./predict_result.png

AIによる未来予測結果(predict_result.png)

Epochs(思考回数)が30の場合の未来予測結果

LSTM機械学習予測

うーん、Epochs(思考回数)が30だとちょっと外していますね・・・。

Epochs(思考回数)が100の場合の未来予測結果

LSTM機械学習予測

Epochs(思考回数)を100にし場合は綺麗に予測出来ていました。

4.LSTMを簡単に行う自作ライブラリ

kerasでLSTMを行うのは大変

よーやく出来ました。
御覧の通り、機械学習を数十行のコードで書けるのでkerasはとても便利ですが、それでもコード量が多いですね?
なので、たった3行でLSTMが出来るライブラリMLLibを作りました。
GitHUBに公開したので良ければ利用して下さい。

MLLibのGitHub

https://github.com/shibayu2002/MLLib.git

MLLibを使ったsin波の機械学習プログラム

メイン所処理:sinML.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from MLLib import LstmML as LstmML
import logging
import sys

if __name__ == "__main__":
  logging.basicConfig(level=logging.INFO)
  ml = LstmML(25, 1, 300)
  ml.epochs = 30

  if len(sys.argv) >1 :
    ml.run(sys.argv[1])
  else:
    ml.run()

ライブラリ:BaseML.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from abc import ABCMeta, abstractmethod
from pandas import Series,DataFrame
from keras.callbacks import EarlyStopping
from keras import models
import pandas as pd
import numpy as np
import logging

# ML基底クラス
class BaseML(metaclass=ABCMeta):
  tran_ds_file = './tran.csv'  # 学習データファイル
  tran_result = './tran_result.png' # 学習結果ファイル
  predict_result = './predict_result.png' # 予想結果ファイル
  hdf5_file = './param.hdf5' # 学習済パラメタファイル
  batch_size = 300 # バッチサイズ
  epochs = 100 # Epochs
  validation_split = 0.1  # 学習データの中の訓練データとテストデータの割合

  # コンストラクタ
  def __init__(self):
    self._tran_In = None    # 入力データ
    self._tran_Out = None   # 出力データ(教師データ)
    self.model = None       # 学習モデル

  # メイン処理
  def run(self, t='all'):
    logging.info('this target is [' + t + ']')

    # 学習と予測を実施
    if t == 'all':
      self.init()
      self.tran()
      self.predict()
    # 学習のみ実施
    elif t == 'tran':
      self.init()
      self.tran()
    # 予測のみ実施
    elif t == 'pre':
      self.init()
      self.predict()
    # パラメタエラー
    else:
      print("run('all' | 'tran' | 'pre')")

  # 準備処理(学習データの読み込み)
  def init(self):
    logging.info('dataset is [' + self.tran_ds_file + ']')
    csv = pd.read_csv(self.tran_ds_file, sep=',', header=0)

    logging.info('-- data tran_In(x) --------------------------')
    self._tran_In = DataFrame(csv.drop('y',axis=1))
    logging.info(self._tran_In)

    logging.info('-- data tran_Out(y) -------------------------')
    self._tran_Out = DataFrame(csv['y'])
    logging.info(self._tran_Out)

  # 学習
  def tran(self):
    # 学習
    early_stopping = EarlyStopping(monitor='val_loss', mode='auto', patience=20)
    self.model.fit(self._tran_In, self._tran_Out,
      batch_size = self.batch_size,
      epochs = self.epochs,
      validation_split = self.validation_split,
      callbacks=[early_stopping]
      )
    # 学習済パラメタ保存
    self.model.save_weights(self.hdf5_file)
    logging.info('hdf5_file saved to ' + self.hdf5_file)
    # 学習結果を描画
    out = self.model.predict(self._tran_In)
    self.draw_tran_result(self._tran_Out, out)
    logging.info('tran_result saved to ' + self.tran_result)

  # 学習結果の描画(派生クラスで実装する)
  @abstractmethod
  def draw_tran_result(self, expected, actual):
    pass

  # 予測
  def predict(self):
    # 学習済パラメタの読み込み
    self.model.load_weights(self.hdf5_file)
    # 予測処理
    actual = self.predict_impl()
    # 予測結果を描画
    self.draw_predict_result(actual)
    logging.info('predict_result saved to ' + self.predict_result)

  # 予測処理の実態(派生クラスで実装する)
  @abstractmethod
  def predict_impl(self):
    pass

  # 予測結果の描画(派生クラスで実装する)
  @abstractmethod
  def draw_predict_result(self, actual):
    pass

ライブラリ:LstmML.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from keras.models import Sequential
from keras.layers.core import Dense, Activation
from keras.layers.recurrent import LSTM
from keras.optimizers import Adam
from .BaseML import BaseML as BaseML
import numpy as np
import matplotlib.pyplot as plt
import logging

class LstmML(BaseML):
  predict_term = 100 # 予測期間

  # コンストラクタ
  def __init__(self, in_size, out_size, n_hidden):
    super().__init__()

    # LSTM学習モデルの生成
    self.model = Sequential()
    self.model.add(LSTM(n_hidden, batch_input_shape=(None, in_size, out_size), return_sequences=False))
    self.model.add(Dense(out_size))
    self.model.add(Activation("linear"))
    optimizer = Adam(lr=0.001)
    self.model.compile(loss="mean_squared_error", optimizer=optimizer)

  # 準備処理(学習データの読み込みと加工)
  def init(self):
    super().init()

    # 親クラスで読み込んだ学習データをLSTMで扱える様に加工
    logging.info('-- reshape data tran_In --------------------------')
    x = self._tran_In
    self._tran_In = np.array(x).reshape(len(x), x.shape[1] , 1)
    logging.info(len(self._tran_In))

    logging.info('-- reshape data tran_Out --------------------------')
    y = self._tran_Out
    self._tran_Out = np.array(y).reshape(len(y), 1)
    logging.info(len(self._tran_Out))

  # 学習結果の描画
  def draw_tran_result(self, expected, actual):
    plt.figure()
    plt.plot(range(0, len(actual)), actual, color="b", label="actual")
    plt.plot(range(0, len(expected)), expected, color="r", label="expected")
    plt.legend()
    plt.savefig(self.tran_result)

  # 予測処理の実態(LSTM未来予測)
  def predict_impl(self):
    # 学習データの最後のデータを取得
    curIn = self._tran_In[len(self._tran_In) - 1]
    logging.info('-- data start curIn(x) --------------------------')
    logging.info(curIn)

    # 指定された期間まで順番に予測する
    # 0 = 学習データの最後
    # 1~ = 未来の予測
    outSum = np.empty((0))
    term = 0
    while term <= self.predict_term:
      # 1つ先の未来を予測
      curOut = self.model.predict(np.reshape(curIn, (1, len(curIn), 1)))
      # 予測結果をcurInの最後に追加。一番古いcurInの値は削除
      curIn = np.delete(curIn, 0)
      curIn = np.append(curIn, curOut)
      # 予測結果を予測結果集計に追加
      outSum = np.append(outSum, curOut)
      if (term != 0) and (term % 10 == 0):
        logging.info('term ' + str(term) + ' finished.')
      term += 1
    return outSum

  # 予測結果の描画
  def draw_predict_result(self, actual):
    plt.figure()
    plt.plot(range(0, len(actual)), actual, color="b", label="actual")
    plt.savefig(self.predict_result)

__init__.py

from .BaseML import BaseML as BaseML
from .LstmML import LstmML as LstmML

5.kerasでLSTMをした感想

ものの見事に予想が出来てビックリしました。
次は、FXとか実用的なので試してみます。

あと、機械学習は、何か算数や数学を知らない子供に、波の波形を何個も見せて、これって次はどう動くと思う?
と聞いたら、数式は分からないけど、何となく次の波形を予想出来ちゃったみたいな感じを受けました。

法則を考えるのが難しい事象で何となく予想するには適してそうです。

本日は以上です。少しでも記事がお役に立てば幸いです。

がんばろー

広告




スポンサーリンク
広告




広告




シェアする

  • このエントリーをはてなブックマークに追加

フォローする

スポンサーリンク
広告