概要
今流行りの深層学習で日経平均株価を予想してみました。 結論から言えば、全く予想できず、惨敗でした。
LSTMとは
LSTMとはリカレントニューラルネットワーク(RNN)と呼ばれる機械学習手法の一つです。
RNNを用いることで、現在と過去一定時間の時系列データから、未来のデータを予測することができます。
また、RNNを改良したLSTMでは、長期のトレンドが反映されやすいとされています。
詳しくはこちらのサイトをご覧ください。
学習データとかモデルとか
こちらのサイトから、過去4ヶ月の1時間足のデータをダウンロードし、学習データとして用いました。 モデルの隠れ層のユニット数は100、過去20時間の株価から1時間先の株価を予測するモデルを用いました。学習方法はAdamを用いました。
実装
Keras(TensorFlow)を用いて実装しました。初めて使ったんですが、短く書けて便利ですね。以下、ソースコードを載せておきます。
# coding: utf-8
import numpy as np
from keras.models import Sequential
from keras.layers import Dense, Activation
from keras.layers.recurrent import LSTM
from keras.optimizers import Adam
from keras.initializers import TruncatedNormal
from keras.callbacks import EarlyStopping
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt
import seaborn
import pandas as pd
df = pd.read_csv('~/deep_learning/csv/nikkei4_7.csv')
x = df['始値'] / df['始値'].max()
f = list(x)
length_of_sequences = len(f)
maxlen = 20
data = []
target = []
for i in range(0, length_of_sequences - maxlen):
data.append(f[i:i+maxlen])
target.append(f[i+maxlen])
X = np.array(data).reshape(len(data), maxlen, 1)
Y = np.array(target).reshape(len(data), 1)
N_train = int(len(data)*0.9)
N_validation = len(data) - N_train
X_train, X_validation, Y_train, Y_validation = \
train_test_split(X, Y, test_size=N_validation)
n_in = len(X[0][0])
n_hidden = 100
n_out = len(Y[0])
weight_hidden = TruncatedNormal(stddev=np.sqrt(1/n_hidden))
weight_out = TruncatedNormal(stddev=np.sqrt(1/n_out))
model = Sequential()
model.add(LSTM(n_hidden,
init=weight_hidden,
input_shape=(maxlen, n_out)))
model.add(Dense(n_out, init=weight_out))
model.add(Activation('linear'))
optimizer = Adam(lr=0.001, beta_1=0.9, beta_2=0.999)
model.compile(loss='mean_squared_error',
optimizer=optimizer)
epochs = 500
batch_size = 10
early_stopping = \
EarlyStopping(monitor='val_loss', patience=10, verbose=1)
hist = model.fit(X_train, Y_train,
epochs=epochs,
batch_size=batch_size,
validation_data=(X_validation, Y_validation),
callbacks=[early_stopping])
## predict 1 step future
original = [f[i] for i in range(length_of_sequences)]
predicted = [None for i in range(maxlen)]
for i in range(1, length_of_sequences - maxlen):
Z = X[:i]
z_ = Z[-1:]
y = model.predict(z_)
predicted.append(y[0][0])
plt.figure()
plt.plot(original, label="original")
plt.plot(predicted, label="predicted")
plt.legend()
plt.xlabel("step")
plt.ylabel("price")
plt.show()
結果
上のスクリプトを走らせた結果、つぎの結果が得られました。 一見予測できているように見えます。 しかしながら、ズームしてみると、 このように、実際の動きから遅れていることがわかります。 これでは全く意味がありません。 世の中そんなに甘い話はありませんね。
書籍
ソースコードの作成に当たって、以下の書籍を参考にしました。数学やPythonの基礎に始まり、LSTMやGRUなど現在注目されている時系列データの機械学習方法の理論と実装が述べられています。全体として簡潔かつコンパクトにまとまっており、初学者でも楽しく読むことができました。深層学習初心者の方には特にオススメします。