Help us understand the problem. What is going on with this article?

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

More than 3 years have passed since last update.

なぜかあまりやっている人を見ない、ディープラーニングを使用した株価の予想をしてみます。
ディープラーニング、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 でポケモンの名前から種族値とタイプを予測させる遊び
深層学習 (機械学習プロフェッショナルシリーズ)

yai
機械学習などを勉強中。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away