ディープラーニング(TensorFlow)を使用した株価予想

  • 350
    いいね
  • 7
    コメント
この記事は最終更新日から1年以上が経過しています。

なぜかあまりやっている人を見ない、ディープラーニングを使用した株価の予想をしてみます。
ディープラーニング、Pythonともに初心者です。ライブラリ、実装方法、理論等は殆ど分かっておりません。ツッコミ等お待ちしています。

目標

  • 数日分の株価データを使用して、翌日の日経平均株価が「上がる」か「下がる」か「変わらず」かを予想します。(分類)

概要

  • 「上がった」か「下がった」か「変わらず」だったかの判断には翌日の終値をベースに判断。
  • 入力データは数日前から前日までの「始値」「高値」「安値」「終値」を使用。
  • 隠れ層は4つ。
  • 入力として上記過去数日分の株価をぶっこんでトレーニングするだけです。

環境

TensorFlow 0.7
Ubuntu 14.04
Python 2.7
AWS EC2 micro instance

内容

準備

可能な限りの日経平均のデータを用意します。今回はYahooファイナンスのデータを使用しました。

実装

日経平均はテキストにしておきます。(毎回取りに行くと面倒なので)
今回は10日分のデータを見て、翌日の株価を予想することにします。
また、翌日の終値が、前日の終値より0.5%以上ならば「上がった」、0.5%以下ならば「下がった」、それ以外ならば「変わらず」としました。この数字の理由は、ちょうどこの3つが33%程度になるためです。

if array_base[idx][3] > (array_base[idx+1][3] * (1.0+flg_range)):
  y_flg_array.append([1., 0., 0.])
  up += 1
elif array_base[idx][3] < (array_base[idx+1][3] * (1.0-flg_range)):
  y_flg_array.append([0., 0., 1.])
  down += 1
else:
  y_flg_array.append([0., 1., 0.])
  keep += 1

データ全体としての割合は下記の通り。
上がった:33.9%
下がった:32.7%
変わらず:33.4%

グラフ作成

コードはこんな感じ。コピペで若干スパゲッティですが、まぁ見やすいのではないでしょうか。(という言い訳)

def inference(x_ph, keep_prob):

  with tf.name_scope('hidden1'):
    weights = tf.Variable(tf.truncated_normal([data_num * 4, NUM_HIDDEN1]), name='weights')
    biases = tf.Variable(tf.zeros([NUM_HIDDEN1]), name='biases')
    hidden1 = tf.nn.sigmoid(tf.matmul(x_ph, weights) + biases)

  with tf.name_scope('hidden2'):
    weights = tf.Variable(tf.truncated_normal([NUM_HIDDEN1, NUM_HIDDEN2]), name='weights')
    biases = tf.Variable(tf.zeros([NUM_HIDDEN2]), name='biases')
    hidden2 = tf.nn.sigmoid(tf.matmul(hidden1, weights) + biases)

  with tf.name_scope('hidden3'):
    weights = tf.Variable(tf.truncated_normal([NUM_HIDDEN2, NUM_HIDDEN3]), name='weights')
    biases = tf.Variable(tf.zeros([NUM_HIDDEN3]), name='biases')
    hidden3 = tf.nn.sigmoid(tf.matmul(hidden2, weights) + biases)

  with tf.name_scope('hidden4'):
    weights = tf.Variable(tf.truncated_normal([NUM_HIDDEN3, NUM_HIDDEN4]), name='weights')
    biases = tf.Variable(tf.zeros([NUM_HIDDEN4]), name='biases')
    hidden4 = tf.nn.sigmoid(tf.matmul(hidden3, weights) + biases)

  #DropOut
  dropout = tf.nn.dropout(hidden4, keep_prob)

  with tf.name_scope('softmax'):
    weights = tf.Variable(tf.truncated_normal([NUM_HIDDEN4, 3]), name='weights')
    biases = tf.Variable(tf.zeros([3]), name='biases')
    y = tf.nn.softmax(tf.matmul(dropout, weights) + biases)

  return y

x_phが前日までの株価データが入ったプレースホルダ。[1日前の終値, 1日前の始値, 1日前の高値, 1日前の安値, 2日前の終値, ...]と言った具合にデータが入っています。
なお、隠れ層のユニット数は100, 50, 30, 10です。つまり、下記で定義しています。

# DEFINITION
NUM_HIDDEN1 = 100
NUM_HIDDEN2 = 50
NUM_HIDDEN3 = 30
NUM_HIDDEN4 = 10

ちなみにこのユニット数と層数は適当です。多い方がいいんじゃね?くらいのつもりで決めました。
これらの数を決める指針等あるなら教えていただけると幸いですm(__)m

最適化

最適化はADAMを使用しています。詳しくは知りませんが、経験上、勾配降下法(GradientDescentOptimizer)より発散し辛いイメージ。

def optimize(loss):
  optimizer = tf.train.AdamOptimizer(learning_rate)
  train_step = optimizer.minimize(loss)
  return train_step

訓練

訓練は下記のような感じ。バッチサイズは100にしました。大きすぎるとコケます。(メモリ不足で。ケチらなければ大丈夫です)

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})

    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}))

結果

TensorBoardで見てみると、下記のように収束しているように見える。
nikkei.jpg

が、正答率を見てみると、

0.3375

惨敗。 :scream:
前述したとおり、各カテゴリ(上がった、下がった、変わらず)の確率が概ね33%なので、当てずっぽうと同じという結果になりました。(笑)

考察

今回の失敗の原因について、原因と考えられるのは下記の通り。
- モデルの構築が不十分?(アドバイスあればお願いします)
- そもそも前日までの株価は翌日の株価に影響を与えない?
- 日経平均は株価の平均なので、そもそもテクニカル的な要素は関係しない?

なお、入力に使う日数、隠れ層の数、ユニット数、活性化関数等を変更して色々試してみましたが、特に結果に変化はありませんでした。 :sob:

所感

行列計算とかディープラーニングとかあまり詳しくありませんが、概要がなんとなく分かってれば、TensorFlowを使ってなんとなくそれらしいことが出来るっぽい! :laughing:

参考にしたサイト、ページ、文献

公式チュートリアル
TensorFlow でポケモンの名前から種族値とタイプを予測させる遊び
深層学習 (機械学習プロフェッショナルシリーズ)