前回スクレイピングにより、KDDI(9433)の株価を取得する方法を解説した。
今回は、このデータを用いて株価を予想するAIを実装する。
概要
今回は、過去20日のデータから21日目の株価終値を予測するモデルを構築する。
構築する方法は、「回帰」を用いる。
回帰とは、連続するデータの予測を行うときなどに使う。
例えば、そのデータの特徴量の傾向をみて(座標上に線を書いて)、具体的な数字を出す(線上から割り出す)、予測するのが回帰である。
以下のフローで実装する。
- CSVデータの読み込み
- データの前処理
- 回帰モデル(LSTM)の構築
使用するライブラリをimport
import numpy as np
import pandas as pd
from pandas import Series, DataFrame
import statistics
import matplotlib.pyplot as plt
from keras.models import Sequential
from keras.layers.core import Dense, Activation
from keras.layers.recurrent import LSTM
CSVデータの読み込み
下の表の終値を用いて実装する。
データ数は、実際は、190日分ある。
日付 | 始値 | 高値 | 安値 | 終値 | 出来高 | 終値調整 | |
0 | 2020-01-06 | 3,237 | 3,243 | 3,211 | 3,243 | 4,504,000 | 3,243 |
1 | 2020-01-07 | 3,250 | 3,273 | 3,238 | 3,271 | 4,604,200 | 3,271 |
2 | 2020-01-08 | 3,270 | 3,277 | 3,213 | 3,241 | 6,703,200 | 3,241 |
3 | 2020-01-09 | 3,241 | 3,300 | 3,234 | 3,295 | 4,647,000 | 3,295 |
4 | 2020-01-10 | 3,295 | 3,298 | 3,278 | 3,288 | 4,270,000 | 3,288 |
5 | 2020-01-14 | 3,280 | 3,299 | 3,277 | 3,283 | 4,701,600 | 3,283 |
6 | 2020-01-15 | 3,289 | 3,290 | 3,266 | 3,270 | 4,198,700 | 3,270 |
7 | 2020-01-16 | 3,251 | 3,265 | 3,243 | 3,254 | 4,288,200 | 3,254 |
8 | 2020-01-17 | 3,263 | 3,277 | 3,259 | 3,265 | 4,223,500 | 3,265 |
pandasでCSVを読み込み終値のみを抽出する。
前回作成したkddi.csvを同じディレクトリに格納する。
dfにkddi.csvを読み込む。df[‘終値’]で終値のみのデータ列にする。
def read_csv(dir):
df = pd.read_csv(dir)
return df['終値'],df['日付']
データの前処理
20日間を入力データとして、ラベルを21日目のデータを使用する。
よって、1set目は、1〜20までがデータで、21日目がlabelとなる。
2set目は、2〜21までがデータで、22日目がlabelとなる。
これを繰り返すことで、AIの学習を進める。
trainとtestデータの生成
trainとtestを7:3の割合で生成する。
load_data(data, length_of_sequences = 20)のdataにdf[‘終値’]を入力する。
docXにdataを,docYにlabelを割り付ける。
def load_data(data, length_of_sequences = 20):
docX, docY = [], []
for i in range(len(data)-length_of_sequences ):
docX.append(data.iloc[i:i+length_of_sequences ].as_matrix())
docY.append(data.iloc[i+length_of_sequences ].as_matrix())
alsX = np.array(docX)
alsY = np.array(docY)
return alsX, alsY
# 学習用とテスト用データを分割
def train_test_split(df, test_size, length_of_sequences):
ntrn = round(len(df) * (1 - test_size))
ntrn = int(ntrn)
X_train, y_train = load_data(df.iloc[0:ntrn], length_of_sequences )
X_test, y_test = load_data(df.iloc[ntrn:], length_of_sequences )
return (X_train, y_train), (X_test, y_test),ntrn
データの標準化
標準化とは、元のデータの平均を0、標準偏差が1のものへと変換する正規化法です。
外れ値のあるデータに対してはそれを無視するようなデータへ変換できるため、外れ値に対して効果的な手法だと言えます。 この処理を行う前提として、元のデータの分布が正規分布になっていることです。
標準化は、以下のように求める。平均値と標準偏差は後ほど、株価に変換する際に使用するので返しておく。
def standardization(l):
l_mean = statistics.mean(l)
l_stdev = statistics.stdev(l)
print("mean",l_mean)
print("std",l_stdev)
return [(i - l_mean) / l_stdev for i in l],l_mean,l_stdev
標準化した値から元の株価に変換する式を記述する。
def kabuka(l,l_mean,l_stdev):
return [i*l_stdev+l_mean for i in l]
回帰モデル(LSTM)の構築
Long short-term memory(LSTM)とは、リカレントリニューラルネットワークの一種である。
リカレントリニューラルネットワークとは、深層学習の一部に再帰的な手続きを導入したものである。時系列データに現れるパターン認識に向きで、株価予測などに用いられる。再帰型ニューラルネットワークである。
LSTMはRNNの中間層のユニットをLSTM blockと呼ばれるメモリと3つのゲートを持つブロックに置き換えることで実現されています。
まずは、生成したモデルのtrain_lossとval_lossをグラフにプロットするため式を定義する。
def plot(train_loss,val_loss):
# Set background color to white
fig = plt.figure()
fig.patch.set_facecolor('white')
# Plot lines
plt.xlabel('epoch')
plt.plot(train_loss, label='train_loss')
plt.plot(val_loss, label='val_loss')
plt.legend()
# Visualize
plt.show()
次に、LSTMによって、予想されたデータと実際の株価を比較グラフをプロットするための式を定義する。
見やすさを向上させるため、plt.xticks(date[::4],rotation=90, size=’small’)で、x軸の値を4つおきに表示し、縦方向に小さい文字で表示する。
def plot_predict(input,predict,date):
# Set background color to white
fig = plt.figure()
fig.patch.set_facecolor('white')
# Plot lines
plt.xlabel('date')
plt.plot(date,input, label='input')
plt.plot(date,predict, label='predict')
plt.xticks(date[::4],rotation=90, size='small')
plt.legend()
# Visualize
plt.show()
以下モデル生成のための本文を記載する。
loss=”mean_squared_error”, optimizer=”adam”を用いた。
test_size = 0.3
length_of_sequences = 20
in_out_neurons = 1
hidden_neurons = 100
dir='kddi.csv'
data,date=read_csv(dir)
data,l_mean,l_stdev=standardization(data)
data=pd.DataFrame(data)
(X_train, y_train), (X_test, y_test),ntrn =train_test_split(data,test_size,length_of_sequences)
model = Sequential()
model.add(LSTM(hidden_neurons, batch_input_shape=(None, length_of_sequences, in_out_neurons), return_sequences=False))
model.add(Dense(in_out_neurons))
model.add(Activation("linear"))
model.compile(loss="mean_squared_error", optimizer="adam")
history = model.fit(X_train, y_train, batch_size=3, epochs=30, validation_split=0.2)
train_loss = history.history["loss"]
val_loss = history.history["val_loss"]
#train_loss,val_lossのプロット
plot(train_loss,val_loss)
# 予測値算出
predicted = model.predict(X_test)
# 実績と比較
dataf = pd.DataFrame(predicted)
dataf.columns = ["predict"]
dataf["input"] = y_test
dataf["predict"]=kabuka(dataf["predict"],l_mean,l_stdev)
dataf["input"]=kabuka(dataf["input"],l_mean,l_stdev)
# 実績と比較可視化
plot_predict(dataf["input"],dataf["predict"],date.iloc[ntrn+length_of_sequences:])
実行結果
過学習なく、順調に学習できた。
縦軸は、loss=”mean_squared_error”です。
作成したモデルで最近の株価を予想させたところ、現実(input)は、予想(predict)より低い結果である。
考察
現在の株価は、2800円前後であるが、AIは、3100円を予想している。
これは、直近のアメリカ大統領選挙やコロナウイルスの第三波により、市場が悲観傾向であると推察できる。
結論|KDDIの株価は3100円
過去の傾向から今後の株価の見通しとしては、3100円までの上昇が見込める。
コメント
[…] 【KDDIの株価をAIで予想】AI実装編KDDIの株価が暴落したが、今後の見通しをA… […]