Go to list of users who liked
Share on X(Twitter)
Share on Facebook
More than 5 years have passed since last update.
ディープラーニング(TensorFlow)を使用した株価予想 ~その2~
前回の続き。
ディープラーニングのフレームワークであるTensorFlowを使用して株価を予想するぞ~、というお話です。ちなみに前回は完全に失敗でした。
前回のコメントで、tawagoさんから「Googleが同じようなことしている」という情報をいただいたので、そちらをコピ・・・インスパイアしてみました。
前回との相違点
前回は、「数日分の日経平均を使用して、次の日の日経平均が上がるか、下がるか、変わらないか(3択)を予想する」ものでした。
Googleのデモでは、「数日分の世界中の株価指数(ダウ、日経平均、FTSE100、DAXなど)を使用して、次の日のS&Pが上がるか下がるか(2択)を予想する」という内容でした。
ということで、下記が前回からの主な変更点となります。
- 「上がるか」「下がるか」の2択
- 日経平均だけでなく、他国の株価指数も使用
- 隠れ層x2、ユニット数は50,25
予想するのは前回と同じく、次の日の日経平均です。
Googleのデモの詳細はこちらの動画から。(英語)
環境
TensorFlow 0.7
Ubuntu 14.04
Python 2.7
AWS EC2 micro instance
実装
準備
Quandlというサイトから、データがダウンロードできるようです。
しかし、掲載されているデータが膨大過ぎて、どれをダウンロードしたら良いのか分からないという問題が発生したため、今回は日経、ダウ、香港ハンセン、ドイツの4つのみ利用することにします。Googleのデモでは8つくらい使用していました。
落としてきたデータは一つの表にまとめてCSVで保存します。特にスクリプトとかありません。ExcelのVLOOKUP関数とか使った手作業でやりました。出来る人ならDBに入れて上手く扱うのでしょうが・・・
ラベル
今回は「上がる」か「下がる」かの2択なので、正解のフラグは下記のような感じ。
if array_base[idx][3] > array_base[idx+1][3]: y_flg_array.append([1., 0.]) up += 1else: y_flg_array.append([0., 1.]) down += 1サンプル全体としては、
上がる:50.6%
下がる:49.4%
となりました。
グラフ作成
グラフはほぼGoogleのコードを真似ています。
隠れ層の数やユニット数もGoogleのコードのままです。
ドロップアウトは無かったかもしれないですが。
NUM_HIDDEN1 = 50NUM_HIDDEN2 = 25def inference(x_ph, keep_prob): with tf.name_scope('hidden1'): weights = tf.Variable(tf.truncated_normal([data_num * price_num, NUM_HIDDEN1], stddev=stddev), name='weights') biases = tf.Variable(tf.zeros([NUM_HIDDEN1]), name='biases') hidden1 = tf.nn.relu(tf.matmul(x_ph, weights) + biases) with tf.name_scope('hidden2'): weights = tf.Variable(tf.truncated_normal([NUM_HIDDEN1, NUM_HIDDEN2], stddev=stddev), name='weights') biases = tf.Variable(tf.zeros([NUM_HIDDEN2]), name='biases') hidden2 = tf.nn.relu(tf.matmul(hidden1, weights) + biases) #DropOut dropout = tf.nn.dropout(hidden2, keep_prob) with tf.name_scope('softmax'): weights = tf.Variable(tf.truncated_normal([NUM_HIDDEN2, 2], stddev=stddev), name='weights') biases = tf.Variable(tf.zeros([2]), name='biases') y = tf.nn.softmax(tf.matmul(dropout, weights) + biases) return y損失
前回書き忘れた損失は下記のように定義。
前回と変わっていませんが、こちらもGoogleさんと同じです。
def loss(y, target): return -tf.reduce_sum(target * tf.log(y))最適化
最適化は前回と変わらず。
def optimize(loss): optimizer = tf.train.AdamOptimizer(learning_rate) train_step = optimizer.minimize(loss) return train_step訓練
訓練も何一つ前回と変わらず。
def training(sess, train_step, loss, x_train_array, y_flg_train_array): summary_op = tf.merge_all_summaries() init = tf.initialize_all_variables() sess.run(init) summary_writer = tf.train.SummaryWriter(LOG_DIR, graph_def=sess.graph_def) for i in range(int(len(x_train_array) / bach_size)): batch_xs = getBachArray(x_train_array, i * bach_size, bach_size) batch_ys = getBachArray(y_flg_train_array, i * bach_size, bach_size) sess.run(train_step, feed_dict={x_ph: batch_xs, y_ph: batch_ys, keep_prob: 0.8}) ce = sess.run(loss, feed_dict={x_ph: batch_xs, y_ph: batch_ys, keep_prob: 1.0}) summary_str = sess.run(summary_op, feed_dict={x_ph: batch_xs, y_ph: batch_ys, keep_prob: 1.0}) summary_writer.add_summary(summary_str, i)評価
評価も前回と変わらず。
correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_ph, 1))accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))print(sess.run(accuracy, feed_dict={x_ph: x_test_array, y_ph: y_flg_test_array, keep_prob: 1.0}))結果~その1~
上記の結果、精度は
0.50295・・・ダメやん。
修正
入力として、各国の株価指数をそのままぶっこんでましたが、ここを少し修正。入力は「その株価指数が前日と比べてどれくらい上下したか」をいれることにしました。(定かではないが、ビデオ内でGoogleもそうやっているように見えた)
コードにすると、こんな感じ。(分かりにくいかもしれませんが)
tmp_array = []for j in xrange(idx+1, idx + data_num + 1): for row, sprice in enumerate(array_base[j]): tmp_array.append(sprice)x_array.append(tmp_array)上記を、下のように変更。
tmp_array = []for j in xrange(idx+1, idx + data_num + 1): for k in range(price_num): tmp_array.append(((array_base[j][k]) - (array_base[j+1][k])) / array_base[j][k] * 100)x_array.append(tmp_array)結果~その2~
0.63185なんとか意味のある数字になったもよう。63%で「上がるか」「下がるか」を予想できているので、当てずっぽうよりかは良い結果が出せていると言えます。
というわけで、一応成功とします(^_^;)
Googleのデモだと72%程度の精度になっていたと思いますが、まぁこっちは使用している株価指数の数も少ないし、こんなものだと思います。
考察
- 入力は「独立した数字群」より、「全体として意味がある数字群」とした方が良い結果が出るのかもしれない。
- 前回どうでもいいのかと思っていたtf.truncated_normal()のstddev指定が割と大事。デフォルトのままだと発散しやすいので0.001とかを指定しています。発散しているようなら調整した方が良いパラメータのようです。
- Googleの指定している隠れ層のユニット数とか結構適当に見える。今回、50と25だけど、最初のユニット数は入力の2倍くらい見ておけばいいのか?(よく分からない)
- Googleのデモ同様にもっと多くの株価指数を入れたり、為替などのデータを入れるともっと精度が上がるかも。
所感
- とりあえずそれっぽくなって良かった!
- TensorFlowはデータが多少変わっても、訓練部分など変えなくて良い部分が多いので、一回テンプレートのようなものを作ってしまえばコーディングが楽。どっちかというと入力データの加工の方が面倒。
- 上記理由で、数字はなるべく定数化しておいた方が後々楽。
ところで・・・
どなたか、為替の5, 15, 30分足データとかダウンロードできるサイトをご存知の方いましたら教えてください。m(__)m
Register as a new user and use Qiita more conveniently
- You get articles that match your needs
- You can efficiently read back useful information
- You can use dark theme