Python
機械学習
ディープラーニング
人工知能
TensorFlow
More than 1 year has passed since last update.

はじめに

特にFujitsu Advent Calendar 2016にちなんだ内容でなく、自分の趣味(継続中の開発の続き)を書きます。
※ 当記事は会社を代表するものではなく、個人の意見です。
(本業は新規事業立ち上げなどで開発職ではありません)

継続中の開発

[開発しているSIVAについて]
[facebook]
https://www.facebook.com/AIkeiba/
[Twitter]
https://twitter.com/Siva_keiba
随時実況していきますので、いいね!フォローお願いします。

今回のやること

前回の続き。
ディープラーニング(深層学習)による予測についてのサンプルコードを書きます。

始めるにあたり必要なスキルはこちらを参考してください。

今回のライブラリ

TensorFlow:https://www.tensorflow.org/
前回のデータを使います。
インストール方法は以下の記事などを参考にしてもらえばと思います。

Pythonの環境構築からTensorFlowインストール

予測モデル作成と実験(前と同じです)

以下のプログラムを準備してモデルの作成

用意したデータは以下のCSV(JRA-VANより)

ラベル名 説明
開催日 yyyy-mm-dd
競馬場
レース番号
レース名
コース ダート
周回 ダートか芝の場合、右回りなら「右」、左回りなら「左」
距離 [m]
馬場状態 良(りょう)
賞金 [万円]
頭数
着順
枠番
馬番
馬名
性別
年齢
騎手
タイム [s]
着差 前着の馬との差のこと,クビ,
通過順
上り3F ラスト600mのタイム[s]
斥量 [kg]
馬体重 [kg]
増減 前レースからの馬体重変化[kg]
人気 oddsの降順の番号
オッズ
ブリンカー ブリンカー(目隠し)ありの場合、「B」
調教師
調教コメント
調教評価

※ブリンカー、調教師、調教コメント以外をパラメータにしてます。

予測プログラム(trainNN.py)

データと合わせてGitにあげときました。

# -*- coding: utf-8 -*-
import csv
import random
import numpy as np
import pandas as pd
import tensorflow as tf
from sklearn.cross_validation import train_test_split
from sklearn.feature_extraction import DictVectorizer
from sklearn import preprocessing

class TrainNN:

  def __init__(self) : 
    # Parameters
    self.learning_rate = 0.01     # 学習率 高いとcostの収束が早まる
    self.training_epochs = 50     # 学習全体をこのエポック数で区切り、区切りごとにcostを表示する

    self.batch_choice = 500
    self.batch_size = 0           # 学習1回ごと( sess.run()ごと )に訓練データをいくつ利用するか
    self.display_step = 1         # 1なら毎エポックごとにcostを表示
    self.train_size = 500         # 全データの中でいくつ訓練データに回すか
    self.step_size =  500         # 何ステップ学習するか

    # Network Parameters
    self.n_hidden_1 = 64      # 隠れ層1のユニットの数
    self.n_hidden_2 = 64      # 隠れ層2のユニットの数

    self.n_input = 27          # 与える変数の数
    self.n_classes = 0        # 分類するクラスの数

  def load_csv(self):
    file_name = "data/jra_race_resultNN.csv"
    df = pd.read_csv(file_name)
    ## 文字列の数値化
    labelEncoder = preprocessing.LabelEncoder()
    df['area_name'] = labelEncoder.fit_transform(df['area_name'])
    df['race_name'] = labelEncoder.fit_transform(df['race_name'])
    df['track'] = labelEncoder.fit_transform(df['track'])
    df['run_direction'] = labelEncoder.fit_transform(df['run_direction'])
    df['track_condition'] = labelEncoder.fit_transform(df['track_condition'])
    df['horse_name'] = labelEncoder.fit_transform(df['horse_name'])
    df['horse_sex'] = labelEncoder.fit_transform(df['horse_sex'])
    df['jockey_name'] = labelEncoder.fit_transform(df['jockey_name'])
    df['margin'] = labelEncoder.fit_transform(df['margin'])
    df['is_blinkers'] = labelEncoder.fit_transform(df['is_blinkers'])
    df['trainer_name'] = labelEncoder.fit_transform(df['trainer_name'])
    df['comments_by_trainer'] = labelEncoder.fit_transform(df['comments_by_trainer'])
    df['evaluation_by_trainer'] = labelEncoder.fit_transform(df['evaluation_by_trainer'])
    df['dhorse_weight'] = labelEncoder.fit_transform(df['dhorse_weight'])
    x_np = np.array(df[['area_name', 'race_number', 'race_name', 'track', 'run_direction',
                       'distance', 'track_condition', 'purse', 'heads_count', 
                       'post_position', 'horse_number', 'horse_name', 'horse_sex', 'horse_age', 
                       'jockey_name', 'time', 'margin', 'time3F', 
                       'load_weight', 'horse_weight', 'dhorse_weight', 'odds_order', 
                       'odds', 'is_blinkers', 'trainer_name', 'comments_by_trainer', 
                        'evaluation_by_trainer'
    ]].fillna(0))
    # 結果
    d = df[['finish_order']].to_dict('record')

    self.vectorizer = DictVectorizer(sparse=False)
    y_np = self.vectorizer.fit_transform(d)
    self.n_classes = len(self.vectorizer.get_feature_names())

    # データを訓練データとテストデータに分ける
    [self.x_train, self.x_test] = np.vsplit(x_np, [self.train_size]) 
    [self.y_train, self.y_test] = np.vsplit(y_np, [self.train_size])
    self.batch_size = self.train_size

  # Create model
  def multilayer_perceptron(self, x, weights, biases):
    # Hidden layer with RELU activation
    layer_1 = tf.add(tf.matmul(x, weights['h1']), biases['b1'])
    layer_1 = tf.nn.relu(layer_1)
    # Hidden layer with RELU activation
    layer_2 = tf.add(tf.matmul(layer_1, weights['h2']), biases['b2'])
    layer_2 = tf.nn.relu(layer_2)
    # Output layer with linear activation
    out_layer = tf.matmul(layer_2, weights['out']) + biases['out']
    return out_layer

  def train(self) :
    # tf Graph input
    x = tf.placeholder("float", [None, self.n_input])
    y = tf.placeholder("float", [None, self.n_classes])

    # Store layers weight & bias
    weights = {
      'h1': tf.Variable(tf.random_normal([self.n_input, self.n_hidden_1]), name="h1"),
      'h2': tf.Variable(tf.random_normal([self.n_hidden_1, self.n_hidden_2]), name="h2"),
      'out': tf.Variable(tf.random_normal([self.n_hidden_2, self.n_classes]), name="wout")
    }
    # バイアスの設定
    biases = {
      'b1': tf.Variable(tf.random_normal([self.n_hidden_1]), name="b1"),
      'b2': tf.Variable(tf.random_normal([self.n_hidden_2]), name="b2"),
      'out': tf.Variable(tf.random_normal([self.n_classes]), name="bout")
    }

    # Construct model
    pred = self.multilayer_perceptron(x, weights, biases)

    # Define loss and optimizer
    cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(pred, y))

    correct_prediction = tf.equal(tf.argmax(pred, 1), tf.argmax(y, 1))
    accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))

    # Logistic Regression  AdamOptimizer GradientDescentOptimizer
    optimizer = tf.train.AdamOptimizer(learning_rate=self.learning_rate).minimize(cost)

    # Initializing the variables
    init = tf.initialize_all_variables()
    saver = tf.train.Saver()
    # Launch the graph

    with tf.Session() as sess:
      tf.scalar_summary("cost", cost)
      tf.scalar_summary("accuracy", accuracy)
      merged = tf.merge_all_summaries()
      writer = tf.train.SummaryWriter("logs/tensorflow_log", sess.graph_def)    

      sess.run(init)
      # Training cycle
      for epoch in range(self.training_epochs):
        avg_cost = 0.
        # Loop over step_size
        for i in range(self.step_size):
          # 訓練データから batch_size で指定した数をランダムに取得
          ind = np.random.choice(self.batch_size, self.batch_choice)
          x_train_batch = self.x_train[ind]
          y_train_batch = self.y_train[ind]
          # Run optimization op (backprop) and loss op (to get loss value)
          _, c = sess.run([optimizer, cost], feed_dict={x: x_train_batch, y: y_train_batch})
          avg_cost += c / self.step_size

        # Display logs per epoch step
        if epoch % self.display_step == 0:
          print "Epoch:", '%04d' % (epoch+1), "cost=", "{:.9f}".format(avg_cost)
          # Compute average loss
          summary_str, acc = sess.run([merged, accuracy], feed_dict={x: x_train_batch, y: y_train_batch})
          writer.add_summary(summary_str, epoch)
          print "Accuracy:", acc
          ## modelの保存
          # name_model_file = 'model_epoch_' + str(epoch+1) + '.ckpt'
          # save_path = saver.save(sess, 'model/tensorflow/' + name_model_file)

      # Test model
      correct_prediction = tf.equal(tf.argmax(pred, 1), tf.argmax(y, 1))
      # Calculate accuracy
      accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))
      print "Accuracy:", accuracy.eval(session=sess, feed_dict={x: self.x_test, y: self.y_test})

if __name__ == "__main__":
  trainNN = TrainNN()
  trainNN.load_csv()
  trainNN.train()

※ pythonおよびデTensorFlowについては勉強中ですのでプログラムに誤りがあるかもです。

結果

$ python trainNN.py 
Epoch: 0001 cost= 28999.539070313
Accuracy: 0.183333
Epoch: 0002 cost= 10636.817809570
Accuracy: 0.146667
Epoch: 0003 cost= 8187.893877930
Accuracy: 0.216667
Epoch: 0004 cost= 6673.761091797
Accuracy: 0.183333
Epoch: 0005 cost= 5364.944535645
Accuracy: 0.196667
Epoch: 0006 cost= 4300.876705078
Accuracy: 0.176667
Epoch: 0007 cost= 3560.373814697
Accuracy: 0.27
Epoch: 0008 cost= 2843.689293701
Accuracy: 0.203333
Epoch: 0009 cost= 1605.616168819
Accuracy: 0.1
Epoch: 0010 cost= 21.059406254
Accuracy: 0.0666667
Epoch: 0011 cost= 9.320877672
Accuracy: 0.0566667
Epoch: 0012 cost= 5.621849694
Accuracy: 0.0866667
Epoch: 0013 cost= 4.749191205
Accuracy: 0.07
Epoch: 0014 cost= 4.069611630
Accuracy: 0.0733333
Epoch: 0015 cost= 3.946254434
Accuracy: 0.0566667
Epoch: 0016 cost= 3.253856863
Accuracy: 0.0433333
Epoch: 0017 cost= 3.309734127
Accuracy: 0.07
Epoch: 0018 cost= 2.978426178
Accuracy: 0.0566667
Epoch: 0019 cost= 2.970437231
Accuracy: 0.0533333
Epoch: 0020 cost= 2.999267270
Accuracy: 0.0566667
Epoch: 0021 cost= 3.828851234
Accuracy: 0.0766667
Epoch: 0022 cost= 2.859027134
Accuracy: 0.0666667
Epoch: 0023 cost= 2.799751988
Accuracy: 0.08
Epoch: 0024 cost= 2.799972694
Accuracy: 0.06
Epoch: 0025 cost= 2.799448245
Accuracy: 0.0633333
Epoch: 0026 cost= 2.799542419
Accuracy: 0.06
Epoch: 0027 cost= 2.798464981
Accuracy: 0.0933333
Epoch: 0028 cost= 2.799431955
Accuracy: 0.07
Epoch: 0029 cost= 2.798901843
Accuracy: 0.05
Epoch: 0030 cost= 2.797275106
Accuracy: 0.0366667
Epoch: 0031 cost= 2.799933175
Accuracy: 0.0566667
Epoch: 0032 cost= 2.799303545
Accuracy: 0.07
Epoch: 0033 cost= 2.799922926
Accuracy: 0.0533333
Epoch: 0034 cost= 2.799450584
Accuracy: 0.0833333
Epoch: 0035 cost= 2.800814153
Accuracy: 0.08
Epoch: 0036 cost= 2.799030569
Accuracy: 0.0733333
Epoch: 0037 cost= 2.799764482
Accuracy: 0.0566667
Epoch: 0038 cost= 2.799920460
Accuracy: 0.0833333
Epoch: 0039 cost= 2.799320694
Accuracy: 0.09
Epoch: 0040 cost= 2.800959777
Accuracy: 0.0766667
Epoch: 0041 cost= 2.799612596
Accuracy: 0.09
Epoch: 0042 cost= 2.800021134
Accuracy: 0.0666667
Epoch: 0043 cost= 2.799918224
Accuracy: 0.0666667
Epoch: 0044 cost= 2.799846961
Accuracy: 0.06
Epoch: 0045 cost= 2.799782973
Accuracy: 0.06
Epoch: 0046 cost= 2.798343555
Accuracy: 0.0633333
Epoch: 0047 cost= 2.800401002
Accuracy: 0.0633333
Epoch: 0048 cost= 2.799323093
Accuracy: 0.06
Epoch: 0049 cost= 2.799231728
Accuracy: 0.0733333
Epoch: 0050 cost= 2.800211056
Accuracy: 0.0633333
Accuracy: 0.0697074

$ tensorboard --logdir=logs/

tensorboard

Screen Shot 0028-12-17 at 23.12.08.png

Screen Shot 0028-12-17 at 23.13.23.png

0.6%。。。全くあたりませんね(笑)
※ もちろんですがSIVAで開発しているアルゴリズムは全く違います。
もう少し勉強してまた書きます!

さいごに(ご参考)

SIVAについては的中率は約40%で回収率は安定して100%前後です。

CzMZW9OUkAAab_1.jpg

[開発しているSIVAについて]
[facebook]
https://www.facebook.com/AIkeiba/
[Twitter]
https://twitter.com/Siva_keiba
随時実況していきますので、いいね!フォローお願いします。