LoginSignup
5
12

More than 5 years have passed since last update.

TensorFlowを投資につかうまで 衝撃のサンプル編 (4)

Last updated at Posted at 2017-08-29

前置き

衝撃のサンプルとはGoogle公式の以下です。
財務時系列データを使用した機械学習

サンプルをもとにTensorFlow1.3でN225の予測を試みます。

予測するもの

  • N225のcloseが前日のcloseより価格が上か下か予測します。
  • ダウンロードしたデータを全部つかってみます。
  • 日本の市場は開くのがはやいのですべて1~3日前のデータを使用します。

上がるか下がるかの2つのものに分類することを
バイナリ分類(binary classification)またはロジスティック回帰(logistic regression)というそうです。

予測する列の追加

予測する列を追加し正解も入力しておきます。対数差分をとっているのでN225が0以上か0以下かで判断できます。
positiveが上がったとき、negativeが下がったときです。

    closing["positive"] = 0
    #closing["N225"] >= 0の行のpositiveに1をいれる。
    closing.ix[closing["N225"] >= 0, "positive"] = 1
    closing["negative"] = 0
    #closing["N225"] < 0の行のnegativeに1をいれる。
    closing.ix[closing["N225"] < 0, "negative"] = 1

トレーニングと検証用データの作成

サンプル通りダウンロードしてきたデータの80%を学習に20%をテストに使用します。

    #1~3日前のデータを予測に使う
    days_before = range(1,4)

    columns = ["positive", "negative"]
    for i in days_before :
        columns += [index + "_" + str(i) for index in INDEIES]

    training = pd.DataFrame(
        # ['positive', 'negative', 'N225_1', 'HSI_1', 'GDAXI_1', 'DJI_1', 'GSPC_1', 'SSEC_1', 'BVSP_1', 'N225_2', 'HSI_2', 'GDAXI_2', 'DJI_2', 'GSPC_2', 'SSEC_2', 'BVSP_2', 'N225_3', 'HSI_3', 'GDAXI_3', 'DJI_3', 'GSPC_3', 'SSEC_3', 'BVSP_3']
        columns = columns
    )

    #なんで7から?
    for i in range(7, len(closing)):
        data = {}
        #予測の部分は当日のデータで
        data["positive"] = closing["positive"].ix[i]
        data["negative"] = closing["negative"].ix[i]
        #ほかの指標は1個前のデータを使用する。
        for index in INDEIES:
            for before in days_before :
                data[index + "_" + str(before)] = closing[index].ix[i - before]
        training = training.append(data, ignore_index=True)
    #一応確認
    print(training.describe())

サンプルはrangeが7からになっているのはなんでなんでしょう。
対数差分の時に最初の行がNANになってるのと3日前までのデータをみるのでrange(4, len(closing))でいいきがするんですけど。ちびっとデータが減るだけだしいっか。

以下の表がコンソールにでるはずです。長いので一部です。

positive negative N225_1 HSI_1 GDAXI_1 \
count 2441.000000 2441.000000 2441.000000 2441.000000 2441.000000
mean 0.521098 0.478902 0.000077 0.000058 0.000197
std 0.499657 0.499657 0.016424 0.016591 0.014922
min 0.000000 0.000000 -0.121110 -0.135820 -0.074335
25% 0.000000 0.000000 -0.007568 -0.006612 -0.006390
50% 1.000000 0.000000 0.000574 0.000000 0.000569
75% 1.000000 1.000000 0.008792 0.007450 0.007199
max 1.000000 1.000000 0.132346 0.134068 0.134627

あとはテスト用、学習用にわけるだけです。

    training_predictors = predictors[:training_size]
    training_classes = classes[:training_size]
    test_predictors = predictors[training_size:]
    test_classes = classes[training_size:]

やっとtensorflow

把握しきれなかったのでとりあえず今回は動かします。
以下の関数を追加python3の記述に変えた以外はほとんどサンプルそのまんまです。

def tf_confusion_metrics(model, actual_classes, session, feed_dict):
    predictions = tf.argmax(model, 1)
    actuals = tf.argmax(actual_classes, 1)

    ones_like_actuals = tf.ones_like(actuals)
    zeros_like_actuals = tf.zeros_like(actuals)
    ones_like_predictions = tf.ones_like(predictions)
    zeros_like_predictions = tf.zeros_like(predictions)

    tp_op = tf.reduce_sum(
      tf.cast(
        tf.logical_and(
          tf.equal(actuals, ones_like_actuals),
          tf.equal(predictions, ones_like_predictions)
        ),
        "float"
      )
    )

    tn_op = tf.reduce_sum(
      tf.cast(
        tf.logical_and(
          tf.equal(actuals, zeros_like_actuals),
          tf.equal(predictions, zeros_like_predictions)
        ),
        "float"
      )
    )

    fp_op = tf.reduce_sum(
      tf.cast(
        tf.logical_and(
          tf.equal(actuals, zeros_like_actuals),
          tf.equal(predictions, ones_like_predictions)
        ),
        "float"
      )
    )

    fn_op = tf.reduce_sum(
      tf.cast(
        tf.logical_and(
          tf.equal(actuals, ones_like_actuals),
          tf.equal(predictions, zeros_like_predictions)
        ),
        "float"
      )
    )

    tp, tn, fp, fn = \
      session.run(
        [tp_op, tn_op, fp_op, fn_op],
        feed_dict
      )

    tpr = float(tp)/(float(tp) + float(fn))
    fpr = float(fp)/(float(tp) + float(fn))

    accuracy = (float(tp) + float(tn))/(float(tp) + float(fp) + float(fn) + float(tn))

    recall = tpr
    precision = float(tp)/(float(tp) + float(fp))

    f1_score = (2 * (precision * recall)) / (precision + recall)

    print('Precision = ', precision)
    print('Recall = ', recall)
    print('F1 Score = ', f1_score)
    print('Accuracy = ', accuracy)

以下を最後に追加

    # 予測する列の数
    num_predictors = len(training_predictors.columns)
    # 予測するべき列の数
    num_classes = len(training_classes.columns)

    session = tf.Session()
    feature = tf.placeholder(tf.float32, shape=(None, num_predictors))
    actual_classes = tf.placeholder(tf.float32,  shape=(None, num_classes))
    weights = tf.Variable(tf.truncated_normal([num_predictors, num_classes], stddev=0.0001))
    biases = tf.Variable(tf.ones([num_classes]))
    model = tf.nn.softmax(tf.matmul(feature, weights) + biases)
    cost = -tf.reduce_sum(actual_classes*tf.log(model))
    training_step = tf.train.AdamOptimizer(learning_rate=0.0001).minimize(cost)
    init = tf.global_variables_initializer()
    session.run(init)
    correct_prediction = tf.equal(tf.argmax(model, 1), tf.argmax(actual_classes, 1))
    accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
    actual_classes_param = training_classes.values.reshape(len(training_classes.values), 2)

    for i in range(1, 30001):
        session.run(
          training_step,
          feed_dict={
            feature: training_predictors.values,
            actual_classes: actual_classes_param
          }
        )
        if i%5000 == 0:
            print( i, session.run(
             accuracy,
             feed_dict={
               feature: training_predictors.values,
               actual_classes: actual_classes_param
             }
           ))
    feed_dict= {
      feature: test_predictors.values,
      actual_classes: test_classes.values.reshape(len(test_classes.values), 2)
    }

    tf_confusion_metrics(model, actual_classes, session, feed_dict)

隠れ層なしで30000回学習させています。

5000 0.56916
10000 0.61834
15000 0.647541
20000 0.653688
25000 0.65625
30000 0.660861
Precision =  0.6015037593984962
Recall =  0.3389830508474576
F1 Score =  0.4336043360433604
Accuracy =  0.5725971370143149

Accuracyがテストデータでの正解率で57%だそうです。まあダメダメですね。
こんどは隠れ層2個いれて学習させます。

    session2 = tf.Session()

    feature = tf.placeholder(tf.float32, shape=(None, num_predictors))
    actual_classes = tf.placeholder(tf.float32,  shape=(None, num_classes))

    weights1 = tf.Variable(tf.truncated_normal([num_predictors, 50], stddev=0.0001))
    biases1 = tf.Variable(tf.ones([50]))

    weights2 = tf.Variable(tf.truncated_normal([50, 25], stddev=0.0001))
    biases2 = tf.Variable(tf.ones([25]))

    weights3 = tf.Variable(tf.truncated_normal([25, 2], stddev=0.0001))
    biases3 = tf.Variable(tf.ones([2]))

    hidden_layer_1 = tf.nn.relu(tf.matmul(feature, weights1) + biases1)
    hidden_layer_2 = tf.nn.relu(tf.matmul(hidden_layer_1, weights2) + biases2)
    model = tf.nn.softmax(tf.matmul(hidden_layer_2, weights3) + biases3)

    cost = -tf.reduce_sum(actual_classes*tf.log(model))

    train_op1 = tf.train.AdamOptimizer(learning_rate=0.0001).minimize(cost)

    init = tf.global_variables_initializer()
    session2.run(init)

    correct_prediction = tf.equal(tf.argmax(model, 1), tf.argmax(actual_classes, 1))
    accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

    for i in range(1, 30001):
        session2.run(
            train_op1,
            feed_dict={
              feature: training_predictors.values,
              actual_classes: actual_classes_param
            }
          )
        if i%5000 == 0:
            print( i, session2.run(
              accuracy,
              feed_dict={
                feature: training_predictors.values,
                actual_classes: actual_classes_param
              }
            ))

    tf_confusion_metrics(model, actual_classes, session2, feed_dict)

結果

5000 0.67418
10000 0.678279
15000 0.679815
20000 0.679303
25000 0.68084
30000 0.68084
Precision =  0.6363636363636364
Recall =  0.5338983050847458
F1 Score =  0.5806451612903226
Accuracy =  0.6278118609406953

正解率が62%まであがりました。明らかに精度があがっています。ちょこっとは参考になりそう。
次回より一気に追加した部分をまたちびっとずつ把握して行こうと思います。

この後我慢できなくてヒストリカルデータを3個増やし、30万回学習させたら隠れ層なしで正解率65%,隠れ層ありで正解率66%になりました。
アカン興奮してきた。

TensorFlowを投資につかうまで 衝撃のサンプル編 (3)
TensorFlowを投資につかうまで 衝撃のサンプル編 (5)

5
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
12