Edited at
FujitsuDay 17

機械学習で競馬予想(その4)

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

随時実況していきますので、いいね!フォローお願いします。