概要
Kerasによるニューラルネットワークモデルの構築方法素のメモです。用語
・Anaconda:データサイエンスおよび機械学習関連アプリケーション(大規模データ処理、予測分析、科学計算)のためのPythonおよびRプログラミング言語のフリーでオープンソースのディストリビューション・Python:機械学習プログラミングに人気のプログラミング言語。
・Keras:Pythonで書かれたオープンソースニューラルネットワークライブラリ。tensorflowをラッピングして作られている。
・ニューラルネットワーク:脳機能を模して考案された機械学習のアルゴリズムの1つ。
・xlrd:pythonでxlsxファイルを読み書きするためのライブラリ
事前準備(前提とする環境)
・Windows10 Professional・Anaconda
・Python3(バージョン3.7.2)
・Keras2.1.5
手順
学習させるデータ
学習の題材には日経平均株価を扱いたいと思います。そこで、日経平均株価の情報をエクセル形式で準備します。 説明変数は、「日付」「終値」「始値」「高値」「安値」「前日比」「5日移動平均」「25日移動平均」「75日移動平均」「14日RSI」です。予測値は、「翌日の日経平均株価」です。用意するデータ
ファイル論理名 | ファイル物理名 | 概要 |
日経平均株価学習データ | nikkei225.xlsx | ニューラルネットワークモデルに学習させるデータセット |
日経平均データファイル定義 | nikkei225_def.xlsx | データセットのファイル定義 |
日経平均株価学習結果テストデータ | nikkei225_test.xlsx | 学習結果のテスト用データ |
xlrdのインストール
xlrdをインストールします。xlrdを用いて、エクセル形式の日経平均株価を読み込みます。$ pip install xlrd
エクセルデータ読み込みプログラム作成(importXLSX.py)
まずはxlsファイルを読み込み、0~1の値に正規化するプログラムを作成します。著者のプログラム能力不足により若干残念ですが、例えば以下みたいな感じで。
import pandas as pd import keras from keras.preprocessing.text import one_hot # dateFlg:0の場合->日付データをそのまま学習、1の場合->日付データは無視して学習 # stringFlg:0の場合->文字列データをそのまま学習、1の場合->文字列データは無視して学習 def getData(fileDefinition, filename, dateFlg, stringFlg, superviser): # xlsxファイルの定義ファイルの読み込みを行う csv_def = pd.read_excel(fileDefinition, encoding='utf-8') # xlsxファイルの読み込みを行う csv_data = pd.read_excel(filename, encoding='utf-8') # 正規化処理(型毎に0~1の値になるように正規化) for raw in csv_def: array = [] # Date型の場合 if(csv_def[raw][0] == 'Date'): max = 0 min = 9999999 for value in csv_data[raw]: if dateFlg == 0: if pd.isnull(value): tmpValue = -1 else: tmpValue = one_hot(value, len(csv_data[raw]) + 1)[0] # 正規化するための最大値取得 if max < tmpValue: max = tmpValue # 正規化するための最小値取得 if min > tmpValue: min = tmpValue else: tmpValue = 0 array.append(tmpValue) # float型の場合 elif(csv_def[raw][0] == 'float'): max = 0.0 min = 9999999.999 for value in csv_data[raw]: if pd.isnull(value): tmpValue = 0.0 else: tmpValue = value # 正規化するための最大値取得 if max < tmpValue: max = tmpValue # 正規化するための最小値取得 if min > tmpValue: min = tmpValue array.append(tmpValue) # long型の場合 elif(csv_def[raw][0] == 'long'): max = 0 min = 9999999 for value in csv_data[raw]: if pd.isnull(value): tmpValue = 0.0 else: tmpValue = value # 正規化するための最大値取得 if max < tmpValue: max = tmpValue # 正規化するための最小値取得 if min > tmpValue: min = tmpValue array.append(tmpValue) # String型の場合 if(csv_def[raw][0] == 'String'): max = 0 min = 9999999 for value in csv_data[raw]: if stringFlg == 0: if pd.isnull(value): tmpValue = -1 else: tmpValue = one_hot(value, len(csv_data[raw]) + 1)[0] # 正規化するための最大値取得 if max < tmpValue: max = tmpValue # 正規化するための最小値取得 if min > tmpValue: min = tmpValue else: tmpValue = 0 array.append(tmpValue) # 学習データの場合は0~1の値に正規化を行う result = [] if max != 0 and raw != superviser: if max == min: min = 0 for value in array: result.append((value - min) / (max - min)) else: result = array csv_data[raw] = result print(csv_data) return csv_data def setSupData(superviser, data): svData = pd.DataFrame() lnData = pd.DataFrame() for raw in data: if raw == superviser: # 指定されたカラムの場合は教師データとして扱う svData[raw] = data[raw] else: # 指定されたカラム以外の場合は学習データとして扱う lnData[raw] = data[raw] return lnData, svData # このプログラム単体でも実行可能です if __name__ == '__main__': data = getData('nikkei225_def.xlsx', 'nikkei225.xlsx', 1, 1, '翌日日経平均')
モデル作成プログラム作成(createModel.py)
続いて、ニューラルネットワークモデルをプログラムを作成します。著者のプログラム能力不(ry
実行が完了すると、「nikkei225.h5」というファイルが生成されます(これがニューラルネットワークモデルになります)。
import sys import datetime import importXLSX as ic from keras.models import Sequential from keras.layers import Dense, Dropout, BatchNormalization def getData(fileDefinition, trainFilename, testFileName, superviser): # 入力データの作成 ------------------------------------------------------------------------- # 入力データの全件取得 print(datetime.datetime.today(), ' トレーニング用データの取得を開始します') trainData = ic.getData(fileDefinition, trainFilename, 1, 1, superviser) # 学習データと教師データの作成(Pandas) print(datetime.datetime.today(), ' トレーニング用データから学習データと教師データを作成します') x_train, y_train = ic.setSupData(superviser, trainData) # テストデータの作成 ----------------------------------------------------------------------- # テスト用データの全件取得 print(datetime.datetime.today(), ' テスト用データを作成します') testData = ic.getData(fileDefinition, testFileName, 1, 1, superviser) # テストデータと正解データの作成(Pandas) print(datetime.datetime.today(), ' テスト用データからテストデータと正解データを作成します') x_test, y_test = ic.setSupData(superviser, testData) return x_train, y_train, x_test, y_test def createModel(x_train, y_train, x_test, y_test): ''' モデルの作成 ''' print(datetime.datetime.today(), ' モデルを作成します') model = Sequential() model.add(Dense(x_train.shape[1], activation='sigmoid')) model.add(BatchNormalization()) model.add(Dropout(0.8)) model.add(Dense(179, activation='sigmoid')) model.add(BatchNormalization()) model.add(Dropout(0.8)) model.add(Dense(179, activation='sigmoid')) model.add(BatchNormalization()) model.add(Dropout(0.8)) model.add(Dense(1)) model.compile(loss='mean_squared_error', optimizer='adam') model.fit(x_train.values, y_train.values, epochs=500, batch_size=32, verbose=1, validation_split=0.1) score = model.evaluate(x_test.values, y_test.values, verbose=0) print('Test MSE : ', score) return model def main(fileDefinition, trainFilename, testFileName, modelName, superviser): # パラメータの表示 print(datetime.datetime.today(), ' fileDefinition(データ定義) : ', fileDefinition) print(datetime.datetime.today(), ' trainFilename(トレーニングデータ) : ', trainFilename) print(datetime.datetime.today(), ' testFileName(テストデータ) : ', testFileName) print(datetime.datetime.today(), ' modelName(作成するモデル名称) : ', modelName) print(datetime.datetime.today(), ' superviser(予測対象項目) : ', superviser) # 入力データとテストデータの作成 x_train, y_train, x_test, y_test = getData(fileDefinition, trainFilename, testFileName, superviser) # モデルの作成 model = createModel(x_train, y_train, x_test, y_test) # モデルの保存 print(datetime.datetime.today(), ' モデルを保存します') model.save(modelName) # 動かす際は、下記コメントアウト内の文字列をコマンドライン引数として与えてください # python createModel.py nikkei225_def.xlsx nikkei225.xlsx nikkei225_test.xlsx nikkei225.h5 翌日日経平均 if __name__ == '__main__': args = sys.argv main(args[1], args[2], args[3], args[4], args[5])
計算実行プログラム(run.py)
最後に、作成したニューラルネットワークモデルを用いて予測を実行します。import sys import datetime import importXLSX as ic import keras from keras.models import load_model def main(modelName, fileDefinition, preFileName, superviser): ''' パラメータの表示 ''' print(datetime.datetime.today(), ' modelName(用いるモデル名称) : ', modelName) print(datetime.datetime.today(), ' fileDefinition(データ定義) : ', fileDefinition) print(datetime.datetime.today(), ' preFileName(検証データ) : ', preFileName) print(datetime.datetime.today(), ' superviser(予測対象項目) : ', superviser) ''' 予測データの取得 ''' # 予測データの取得 preData = ic.getData(fileDefinition, preFileName, 1, 1, superviser) x_pre, dummy = ic.setSupData(superviser, preData) ''' モデルの作成 ''' # モデル生成 model = load_model(modelName) ''' 予測の実行 ''' predicted = model.predict(x_pre) print(predicted) # python rarun.py nikkei225.h5 nikkei225_def.xlsx nikkei225_test.xlsx 翌日日経平均 if __name__ == '__main__': args = sys.argv main(args[1], args[2], args[3], args[4])結果は以下のコマンドラインの値になります。日経平均予測に必要なデータ項目も全然足りていないし、ニューラルネットワークのハイパーパラメーターのチューニングも全然していないため、予測値がマイナスになるものもあり全然です。が、Kerasの使い方はこんな感じです。
> $ python rarun.py nikkei225.h5 nikkei225_def.xlsx nikkei225_test.xlsx 翌日日経平均 Using TensorFlow backend. 2019-05-24 17:44:41.663010 modelName(用いるモデル名称) : nikkei225.h5 2019-05-24 17:44:41.665976 fileDefinition(データ定義) : nikkei225_def.xlsx 2019-05-24 17:44:41.665976 preFileName(検証データ) : nikkei225_test.xlsx 2019-05-24 17:44:41.666974 superviser(予測対象項目) : 翌日日経平均 2019-05-24 17:44:42.156586: I tensorflow/core/platform/cpu_feature_guard.cc:140] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX AVX2 [[ 10371.795 ] [-50451.01 ] [ 17245.732 ] [ 523.5143] [ 16382.622 ] [ 15044.639 ] [ -6003.2383] [-17564.129 ] [ -4260.0283] [ 17274.5 ] [ 17795.049 ] [ 18401.918 ] [ 19743.291 ] [ 4336.625 ] [ 22392.877 ] [ 22660.785 ] [ 23163.428 ] [ 22441.758 ]]