#はじめに
PythonでLSTMモデルを作成し、株価予測アルゴリズムを開発しました。
それをDjangoを用いてWEBアプリ化し、Herokuにデプロイしました。
色々と省きますが、WEBアプリができるまでを順に説明したいと思います。
開発環境は以下です。
- Windows8.1 Pro
- Python 3.6.5
- Django 2.0.7
本記事の構成は以下です。
No. | 項目 |
---|---|
1 | PythonによるLSTMモデルの構築と株価予測 |
2 | DjangoによるWebアプリケーションの作成 |
3 | HerokuへWebアプリケーションをデプロイ |
#1.PythonによるLSTMモデルの構築と株価予測
ここでは、Pythonを用いて、
- 株価データのスクレイピング
- LSTMモデルの定義
- LSTMモデルの学習
- 株価予測
を行っています。
stock_predict_nikkei.py
#def LSTM(NAME,epoch,s_date,e_date,batch):
from . import brand_list
from . import read_nikkei
def LSTM(input):
############
#---LSTM---#
############
############
###1.importing Libraies and getting stock data
import pandas as pd
import datetime as dt
import numpy as np
import pandas_datareader.data as web
import matplotlib.pyplot as plt
import chainer
#start = dt.date(2011,1,1)
#end = dt.date(2018,7,1)
#start = s_date
#end = e_date
start = input[2]
end = input[3]
print(start)
print(end)
#AMZN:Amazon、AAPL:Apple、GOOGL:Google、ACN:アクセンチュア、
#AFL:アフラック、DIS:ディズニー、FB:Facebook、NVDA:NVIDIA
#df_org= web.DataReader('NVDA',"morningstar",start,end)
#df_org= web.DataReader(NAME,"morningstar",start,end)
#df_org= web.DataReader(input[0],"morningstar",start,end)
df_org = read_nikkei.get_jstock(input[0],start=pd.Timestamp(start),end=pd.Timestamp(end))
df_org = df_org.drop('Adj Close',axis=1)
#翌日のOpen値入力
df_add = df_org['Open'].shift(-1)
#最終日は当日のOpen値入力(これしないとNANになる)
df_add[len(df_org)-1] = df_add[len(df_org)-2]
#翌日のOpen値入力
df_org = pd.concat([df_org,df_add], axis=1)
#カラム更新
df_org.columns = ['Open', 'High','Low', 'Close', 'Volume','Open-1']
############
#2.setting data
from sklearn.preprocessing import MinMaxScaler
x_scaler = MinMaxScaler(feature_range=(0, 1))
x2_scaler = MinMaxScaler(feature_range=(0, 1))
x3_scaler = MinMaxScaler(feature_range=(0, 1))
t_scaler = MinMaxScaler(feature_range=(0, 1))
df_x = x_scaler.fit_transform(np.array(df_org['Open-1']).reshape(-1,1)).astype(np.float32)
df_x2 = x2_scaler.fit_transform(np.array(df_org['Close']).reshape(-1,1)).astype(np.float32)
df_x3 = x3_scaler.fit_transform(np.array(df_org['High']).reshape(-1,1)).astype(np.float32)
df_t = t_scaler.fit_transform(np.array(df_org['Close']).reshape(-1,1)).astype(np.float32)
#訓練データと教師データへの分割
x,x2,x3,t = [],[],[],[]
N = len(df_org)
M = 30
for n in range(M,N):
_x = df_x[n-M:n]
_x2 = df_x2[n-M:n]
_x3 = df_x3[n-M:n]
_t = df_t[n]
x.append(_x)
x2.append(_x2)
x3.append(_x3)
t.append(_t)
#trainデータの割合
ratio_train_test = input[5]
#testデータの個数
n_test = 1
#testデータ数を個数で決めるか割合で決めるかのSW
SW = -1
#例:x[1]は初日からM日分の(標準化された)Closeデータ、t[1]はM+1日目のCloseデータ
x = np.array(x, dtype = np.float32)
x2 = np.array(x2, dtype = np.float32)
x3 = np.array(x3, dtype = np.float32)
t = np.array(t, dtype = np.float32).reshape(len(t),1)
#x = np.c_[x,x2]
if SW == 1:
n_train = int(len(x) * ratio_train_test)
elif SW == -1:
n_train = len(x)-n_test
else:
pass
dataset = list(zip(x, t))
train, test = chainer.datasets.split_dataset(dataset,n_train)
############
#3.making models
# chainerと必要なパッケージをインポート
import chainer.links as L
import chainer.functions as F
from chainer import Chain, Variable, datasets, optimizers
from chainer import report, training
from chainer.training import extensions
import chainer.cuda
# ニューラルネットワークモデルを作成
class RNN(Chain):
def __init__(self, n_units, n_output):
super().__init__()
with self.init_scope():
self.l1 = L.LSTM(None, n_units)
self.l2 = L.Linear(None, n_output)
def reset_state(self):
self.l1.reset_state()
def __call__(self, x, t):
y = self.predict(x)
loss = F.mean_squared_error(y, t)
report({'loss':loss},self)
return loss
def predict(self, x):
#if train:
#h1 = F.dropout(self.l1(x),ratio = 0.5)
#else:
h1 = self.l1(x)
return self.l2(h1)
## LSTMUpdaterを作る。
class LSTMUpdater(training.StandardUpdater):
def __init__(self, data_iter, optimizer, device=None):
super(LSTMUpdater,self).__init__(data_iter, optimizer, device=None)
self.device = device
def update_core(self):
data_iter = self.get_iterator("main")
optimizer = self.get_optimizer("main")
batch = data_iter.__next__()
x_batch, t_batch = chainer.dataset.concat_examples(batch, self.device)
optimizer.target.reset_state() #追加
optimizer.target.cleargrads()
loss = optimizer.target(x_batch, t_batch)
loss.backward()
loss.unchain_backward() #追記
optimizer.update()
############
#4.setting hyperparameters
# 乱数のシードを固定 (再現性の確保)
np.random.seed(1)
# モデルの宣言
model = RNN(30, 1)
# GPU対応
#chainer.cuda.get_device(0).use()
#model.to_gpu()
# Optimizer
optimizer = optimizers.Adam()
optimizer.setup(model)
# Iterator
batchsize = input[4] #ミニバッチのサイズ
train_iter = chainer.iterators.SerialIterator(train, batchsize)
test_iter = chainer.iterators.SerialIterator(test, batchsize, repeat=False, shuffle=False)
# Updater <- LSTM用にカスタマイズ
updater = LSTMUpdater(train_iter, optimizer,device = -1)
# Trainerとそのextensions
#epoch = 100
epoch = input[1]
trainer = training.Trainer(updater, (epoch, 'epoch'), out='result')
# 評価データで評価
trainer.extend(extensions.Evaluator(test_iter, model,device = -1))
# 学習結果の途中を表示する
trainer.extend(extensions.LogReport(trigger=(1, 'epoch')))
# 1エポックごとに、trainデータに対するlossと、testデータに対するlossを出力させる
trainer.extend(extensions.PrintReport(['epoch', 'main/loss', 'validation/main/loss', 'elapsed_time']), trigger=(1, 'epoch'))
############
#5.training
trainer.run()
############
#6.predict stock price
x_,x2_,x3_ = [],[],[]
_x = df_x[N-M:N]
_x2 = df_x2[N-M:N]
_x3 = df_x3[N-M:N]
x_.append(_x)
x2_.append(_x2)
x3_.append(_x3)
#例:x[1]は初日からM日分の(標準化された)Closeデータ、t[1]はM+1日目のCloseデータ
x_ = np.array(x_, dtype = np.float32)
x2_ = np.array(x2_, dtype = np.float32)
x3_ = np.array(x3_, dtype = np.float32)
#x_ = np.c_[x_,x2_]
if SW == 1:
n_train = int(len(x) * ratio_train_test)
elif SW == -1:
n_train = len(x)-n_test
else:
pass
train_x, test_x = x[:n_train], x[n_train:]
train_t, test_t = t[:n_train], t[n_train:]
train_t = t_scaler.inverse_transform(train_t)
#図表示
plt.clf()
plt.plot(train_t, label = 'actual', color='blue') # 実測値
plt.legend()
plt.savefig('C:\\Users\\Owner\\Desktop\\Django\\mySite\\static\\fig.png')
# 検証データ
model.reset_state()
test_y = model.predict(Variable(x_)).data
test_y = t_scaler.inverse_transform(test_y)
test_t = t_scaler.inverse_transform(test_t)
return test_y[0][0],test_t[0][0]
#2.DjangoによるWebアプリケーションの作成
編集中
#3.HerokuへWebアプリケーションをデプロイ
編集中
詳細は、今後書いていきます!
質問・ご指摘あればぜひ。
また、株価予測アプリは情報提供を目的としており、株価予測アプリに従って投資した結果に関しましては一切責任をもちません。利用に関しては自己責任でお願いします。