今日も窓辺でプログラム

外資系企業勤めのエンジニアが勉強した内容をまとめておくブログ

隠れ層の数を調整してみる ~株価予測(4)~

今回やること

前回 はTensorBoardでグラフや損失関数、精度の変化を可視化する環境を整えました。
今回は隠れ層の層数や、各層のノードの個数を変えてみて、精度がどのように変化するのかを可視化したグラフを見ながら確認してみたいと思います。

前回記事:
TensorBoardで学習の過程を可視化する ~株価予測(3)~ - 今日も窓辺でプログラム

隠れ層の個数が変えられる実装

隠れ層の数をいろいろ変えてみるにあたって、前回のコードのinference()の部分を少し改良して、自由に隠れ層の層数や、各層のノード数を指定できるように変更します。

def inference(feature_data, layers):
    if len(layers) < 2:
        raise Exception("'layers' should have more than one elements")

    previous_layer = feature_data
    for i in range(len(layers) - 2):
        with tf.name_scope("Hidden" + str(i + 1)):
            weights = tf.Variable(tf.truncated_normal([layers[i], layers[i + 1]], stddev=0.0001))
            biases = tf.Variable(tf.ones([layers[i + 1]]))
            previous_layer = tf.nn.relu(tf.matmul(previous_layer, weights) + biases)

    with tf.name_scope("Output"):
        weights = tf.Variable(tf.truncated_normal([layers[-2], layers[-1]], stddev=0.0001))
        biases = tf.Variable(tf.ones([layers[-1]]))
        model = tf.nn.softmax(tf.matmul(previous_layer, weights) + biases)
        return model

引数のlayersに、各層のノード数のリストを与えます。
例えば、入力層ノード10個、中間層が2層でそれぞれノード50個と25個、出力層がノード2個の場合は[10, 50, 25, 2]というリストを渡します。

今回の実装全体はこちらにおいてあります。
https://github.com/kanoh-k/pred225/blob/9bd2f31b583a2c60248a680d04e3a3dfe3c3808d/eval.py

隠れ層の総数を変えてみる

最適な隠れ層の数を探すセオリーがよくわからなかった(あるんですかね?)ので、とりあえず以下のパターンを試してみることにしました。
各行のリストが隠れ層のノード数になります。コメント部分に、入力層と出力層も含めたノード数を書いてあります。

experiments = [
    [],           # 隠れ層なし  ノード数:9-2
    [25],         # 1層の隠れ層 ノード数:9-25-2
    [50],         # 1層の隠れ層 ノード数:9-50-2
    [100],        # 1層の隠れ層 ノード数:9-100-2
    [50, 25],     # 2層の隠れ層 ノード数:9-50-25-2
    [100, 50],    # 2層の隠れ層 ノード数:9-100-25-2
    [100, 50, 25] # 3層の隠れ層 ノード数:9-100-50-25-2
]

テストデータでの精度はこのようになりました。
f:id:kanohk:20160817210350p:plain

損失関数の変化や訓練データでの精度はこのようになりました。

損失関数の変化
f:id:kanohk:20160817210738p:plain

訓練データでの精度
f:id:kanohk:20160817210701p:plain

簡単な考察

まずテストデータでの精度を見てみると、隠れ層が3層のモデルが一番良い精度を出しています。(3万イテレーション時点で、71.36%)
続いて隠れ層が1層のモデル3つが同じ精度で次点に着けています。
(上のグラフだと分からないですが、3本の線が重なっています)
f:id:kanohk:20160817211130p:plain

そして精度がダントツで一番悪いのは、隠れ層のないモデル。悪いといっても、65.8%ほどの精度を出しています。

次に損失関数の変化を見てみます。すると、損失関数が一番小さくなっているのは隠れ層が2層の場合です。9-50-25-2の構成の時に一番小さくなり、9-100-50-2の時が2番目に小さくなっています。
テストデータで精度の良かった隠れ層3層のモデルは、下から3番目の紫色の線で、隠れ層2層のモデルよりは少し大きめの値となっています。

訓練データでの精度のほうを見ると、隠れ層2層のモデルが高い精度を出していることがわかります。損失関数を小さくできて、訓練データにはうまく適合しているけれどテストデータでの精度はあまりよくない、これがよく聞く過学習を起こしている状態なのでしょうか。

(2016/08/31追記:プログラムのデータを作成する部分にバグがあり、この数値は正しくないものであることが判明しました。手法や記事で直接言及した部分の実装は問題ないはずです。)
(2016/9/20追記:正しい数値での記事を投稿しました(クリックで記事へ移動)

まとめ

途中で貼ったグラフ以外の層数・ノード数を試してみましたが、結局9-100-50-25-2の構成が一番良い精度でした。
良い隠れ層の数を見つける方法に定石があるのかはわからないのですが、今後は問題ごとに、このような方法で最適な隠れ層を見つけていくことにします。

次回予告

今までは、日経平均の終値が、前日の終値と比べて上がるか下がるかを予測してきました。
しかし最初から分かっていた通り、この予測をしたところで実際にお金が儲かるかというと、そうではありません。
日経平均に連動したETFを買ってみるにしても、実際にETFを買えるのは当日の始値かそれ以降についた値段です。
そこで次回は、「前日の終値と比べて」ではなく、「当日の始値と比べて、終値は上がるか下がるか」の予測に挑戦してみたいと思います。



次回記事:
日経平均の終値が始値より上がるか下がるかを予測する ~株価予測(5)~ - 今日も窓辺でプログラム