RNN(LSTM)で株価予測をやってみた(失敗)
最近音沙汰ないですが、地味にディープラーニングネタは進行中です。
今回は、ディープラーニングでも”RNN”(リカレント ニューラル ネットワーク)というやつにトライしてみました。
そもそもこのRNNってやつは何ぞや?ですが、誤解を承知で簡単にいうと”未来の時系列データを予測する手法”とでもいうんでしょうか。
CNNがある時間における画像認識をするための手法なら、RNNは時間で変化するデータを予測するという手法、ということです。
で、LSTMとは何ぞや?ですが。
”Long Short-Term Memory (Networks)”の略だそうです。
ロングでショート?というずいぶん矛盾した名前の手法ですが、これが時系列予測に革命をもたらした(大げさ)手法のようです。
詳しい説明は一つ目のリンクあたりを参照願いますが、すごく簡単に言うと「長い時系列データから特徴を取り出すために、どうでもいい特徴は忘れる」手法なんだそうです。
考えてみれば、人間もそうですね。
今までの人生で、すごく印象に残った出来事やトラウマ的なものはしっかり残ってるけど、どうでもいい出来事って本当にまったく覚えていないものです。
そうでなければ人間、いろいろなことを覚えていられないんでしょうね。
それにしても人間は、いいことばかりというより、悪いことの方がよく覚えているものですよね。私も思い出したくない黒歴史やトラブルほどよく覚えていてですね・・・
脱線しましたが、LSTMってのは、そういうものです。とりあえず、そういうことにしておきましょう。
さて、時系列データの予測なんて話を聞くと「株価が予測できるんじゃねぇ?」と思うのは人の業というもの。
そんな不純な動機で、RNNというのを体感してみました。
参考にしたのは、こちらのサイト。
RNNで来月の航空会社の乗客数を予測する:TFLearnでLSTMからGRUまで実装しよう - DeepAge
大元はこちら。
コードは2つ目のリンクから入手しました。
さて、まずやらなきゃいけないのは”Keras”ってやつを導入すること。
TensorFlow(+Keras)がWindowsで簡単にインストールできた件 - Qiita
この辺のサイトを読むと
> pip install keras
で行けると書かれてますが、どっこいそうは簡単にはいきませんで。
scipyだかscikit-learnだがを入れろといわれます。
でこれがどちらかが”pip”コマンドでは入らなかったため、
> conda install scikit-learn
という感じに”conda”コマンドを使ったら行けました(自宅ではscikit-learnのみconda使いましたが、会社ではscipyあたりもcondaコマンド使わないと入りませんでした。理由は不明)。
あとは、matplotlibあたりも入れておきます。
> pip install matplotlib
あとは
> pip install keras
(”conda”の方がいい場合があります)
これで準備完了。
続いて、2つ目のリンク先にあるコードをテキストエディタで保存します。
◆「lstm.py」
# LSTM for international airline passengers problem with regression framing
import numpy
import matplotlib.pyplot as plt
from pandas import read_csv
import math
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import LSTM
from sklearn.preprocessing import MinMaxScaler
from sklearn.metrics import mean_squared_error
# convert an array of values into a dataset matrix
def create_dataset(dataset, look_back=1):
dataX, dataY = [], []
for i in range(len(dataset)-look_back-1):
a = dataset[i:(i+look_back), 0]
dataX.append(a)
dataY.append(dataset[i + look_back, 0])
return numpy.array(dataX), numpy.array(dataY)
# fix random seed for reproducibility
numpy.random.seed(7)
# load the dataset
dataframe = read_csv('international-airline-passengers.csv', usecols=[1], engine='python', skipfooter=3)
dataset = dataframe.values
dataset = dataset.astype('float32')
# normalize the dataset
scaler = MinMaxScaler(feature_range=(0, 1))
dataset = scaler.fit_transform(dataset)
# split into train and test sets
train_size = int(len(dataset) * 0.8)
test_size = len(dataset) - train_size
train, test = dataset[0:train_size,:], dataset[train_size:len(dataset),:]
# reshape into X=t and Y=t+1
look_back = 1
trainX, trainY = create_dataset(train, look_back)
testX, testY = create_dataset(test, look_back)
# reshape input to be [samples, time steps, features]
trainX = numpy.reshape(trainX, (trainX.shape[0], trainX.shape[1] ,1))
testX = numpy.reshape(testX, (testX.shape[0], testX.shape[1] ,1))
print(testX , testY)
# create and fit the LSTM network
model = Sequential()
model.add(LSTM(4, input_shape=(1, look_back)))
model.add(Dense(1))
model.compile(loss='mean_squared_error', optimizer='adam')
model.fit(trainX, trainY, epochs=50, batch_size=1, verbose=2)
# make predictions
trainPredict = model.predict(trainX)
testPredict = model.predict(testX)
# invert predictions
trainPredict = scaler.inverse_transform(trainPredict)
trainY = scaler.inverse_transform([trainY])
testPredict = scaler.inverse_transform(testPredict)
testY = scaler.inverse_transform([testY])
# calculate root mean squared error
trainScore = math.sqrt(mean_squared_error(trainY[0], trainPredict[:,0]))
print('Train Score: %.2f RMSE' % (trainScore))
testScore = math.sqrt(mean_squared_error(testY[0], testPredict[:,0]))
print('Test Score: %.2f RMSE' % (testScore))
# shift train predictions for plotting
trainPredictPlot = numpy.empty_like(dataset)
trainPredictPlot[:, :] = numpy.nan
trainPredictPlot[look_back:len(trainPredict)+look_back, :] = trainPredict
# shift test predictions for plotting
testPredictPlot = numpy.empty_like(dataset)
testPredictPlot[:, :] = numpy.nan
testPredictPlot[len(trainPredict)+(look_back*2)+1:len(dataset)-1, :] = testPredict
# plot baseline and predictions
plt.plot(scaler.inverse_transform(dataset))
plt.plot(trainPredictPlot)
plt.plot(testPredictPlot)
plt.show()
このとき使うデータ”international-airline-passengers.csv”は、以下のサイトから入手。
ここで”Export”タブから”CSV(,)”をクリックするとダウンロードできます。
あとは、以下のように打ち込んで実行。
> python lstm.py
さて、これを実行した結果はこちら。
6割くらいのデータを使って、残り4割を予測しています。
実際のデータが青、予測が赤。
ちょっとずれがありますが、おおむねいい予測ですね。
これはとある国際線の利用者数のデータのようです。実際は緑までのパターンより、需要が伸びたんでしょう。これが赤と青のずれの原因と思われます。
さて、上のコードの”international-airline-passengers.csv”てのを株価データに変えてしまえば、予測できるんじゃないか?
やってみました。
最近、妻が株を保有してて、その中の一つで吉野家HDの株を持ってるので、”吉野家HD”の株価のデータで予測させてみました。
ちなみに、株価データは以下から入手。
ここから吉野家HDの株価250日分(概ね1年分)を入手。
ただし、ここから入手したデータは、そのままだと下に行くほど過去になるCSVが得られるため、上下ひっくり返さないとおかしなデータになります。
やり方は、こちらを参照。
表の上下を入れ替える -エクセルで作成した表を、あとから見たら、「上- Excel(エクセル) | 教えて!goo
データは必ず2つ(2行)にします。
こんな感じで保存。私は”終値”を使いました。
これを”yoshinoya.csv”とでも付けて保存。
先のコード中の”international-airline-passengers.csv”を”yoshinoya.csv”に変えて実行。
結果はこちら。
おお!すごい!ぴったり予測できてるじゃん!!
ということはなくて、これは失敗事例です。。。
一体どこが失敗なのか?
LSTMのこのコードは「一つ手前のデータと、これまでのパターンから次の値を予測する」ことをやってます。
実はこの株価の場合、ただ単に一つ手前のデータをコピーして返しているだけ。よーく見ると、一つだけずれたデータになってます。
この先を予測するためには、最後の予測値を含んだ時系列データを使ってその次のステップを予測して、またこれを含んだデータを使って・・・というのを繰り返せばいいんですが、こういうパターンの時は”最後の値がずーっとフラットに吐き出されるだけのデータ”になってしまうようです。
要するに、彼は0~150までの学習データからパターンを見いだせなかったんですね・・・
考えてみれば、株価というのは外的要因が大きくて、決して基準となるパターンがあるわけではありません。
決算の傾向や企業買収の噂だけでなく日経○聞の飛ばし記事、マ○ゴミどもの印象操作報道、北朝鮮・トランプ氏のチャーハン合戦・・・などで株価って結構変動してます。
あまりに不確定要素が多すぎて、そのたびに妻が一喜一憂しておりますね。ほんと。見てて面白い・・・いや、なんでもありません。
そんなもののパターン予測をやろうなんて、どだい無理だったんでしょうかね・・・
sinカーブを予測させるというのは得意なようです。
さて、ここで痛感したRNN(LSTM)の活用法は以下。
・ 例えば生産機械などの異常検知
生産機械というのは、一定の間隔、決まったパターンで動作しているものが多いため、正常パターンを学習させれば、異常が起きた時には予測と実データのずれが発生。そこから”異常検知”をするらしいです。
・ 季節や時間周期で起こる現象の予測
先の国際線の利用客じゃないですが、ああいうある程度パターン化された現象というのはこのRNN(LSTM)手法で予測できるようです。
近似式を作って予測すればいいかもしれませんが、なかなかすべてのデータが定式化できるというわけでもないですし、右肩上がりな成長をしているものの場合はRNNの出番なのかもしれません。
他にも、CNNと組み合わせて画像の変化を予測するということもやられてるようです。具体的なプログラムコードを知りませんが。
・ 文書自動作成
これが今一番ホットな使い方の一つのようです。
単語の前後のつながりを学習して、決まった単語や画像認識結果から文書作り出すという者が作れます。
もっとも、そのためには相当な学習データが必要ですが・・・参考サイトを紹介しておきます。
もうちょっと教師データがあって、もうふた工夫くらいすれば文章が作れるかもしれません。
自動翻訳にも、最近このLSTMが注目されてるっぽいですね。
ということを思い知らされたところで、一旦RNNの試行は停止状態。
株価予測がとりあえずダメだってことがわかったからモチベーションが落ちたというのは、多分気のせいです。
どのみち、私の周りに(私的、職場的に)ちょうどいい題材がありません。最後の文書作成が一番やってみたいですが、多分これが一番難易度が高いです。
いい活用術が見つかったら、もう少しコードをいじっていろいろやってみたいですよね。
・・・などと偉そうに記事書いてますけど、プロの方が見たら多分突っ込みどころ満載のはず。やり方や解釈等ご指摘あれば、ぜひコメント欄にお願いします。
« 米保険大手がApple Watchを2300万人に提供か!? | トップページ | 3分の1サイズのミニチュアX1turbo »
「数値解析系」カテゴリの記事
- Tanuki-8Bの4ビット量子化ggufモデルでRAGをやってみました(2024.09.14)
- 純日本産なローカルLLM「Tanuki-8B」を試してみた(2024.09.02)
- 東京のセールスフォースに行ってきました(2024.07.24)
- ローカルLLM「Llama-3-ELYZA-JP-8B」にいろいろ聞いてみた(2024.07.01)
- ElyzaのLlama3ベースの言語モデル「Llama-3-ELYZA-JP-8B」のRAGが予想以上に賢かった件(2024.06.27)
コメント
« 米保険大手がApple Watchを2300万人に提供か!? | トップページ | 3分の1サイズのミニチュアX1turbo »
吉野家のくだりは一瞬驚きましたが、世の中甘くはないようですね^^;
投稿: yoja | 2017年8月27日 (日) 15時32分
こんにちは、yojaさん。
私も一瞬びっくりしましたが、単に一つ前をトレースしているだけと知ってがっかりでした。そんなに楽に未来が予測できたら、みんな使いますよね。そんなに甘くはないです。
投稿: arkouji | 2017年8月28日 (月) 06時37分