Python
機械学習
Kaggle
Keras
競馬

金儲けしたい一心で競馬ドシロウトが競馬の予想を機械学習でチャレンジした

概要

機械学習を最近勉強はじめたのですが、やはり「何かに役立てたい!」と思いました。まあはっきり言ってしまえば、お財布に貢献するようなことがしたいと。

family_syunyu.png

そこで、いろいろ検討してみたのですが、分析しやすそうな競馬の順位予想をやってみようと思いました!ちなみに僕は競馬を一切やったことがありません。どういうルールかさえよく分かってないです。スティール・ボール・ランで得た知識しかないです。

予想方針

予想は、一般的な方法ではなくて違うアプローチをとりました。

一般的には、体重勝率騎手オッズ などなど馬の情報やレースに関する情報をもとに順位を予想することが多いのですが、僕が利用した方法は予想屋(tipster)の予想をもとに順位を当てるというものです。

僕は競馬ドシロウトなのでよくわからないのですが、競馬には予想屋という人たちがいて、レースごとにどの馬が勝つか、どの馬が負けるかなどを予想しているようです。変な世界です。

今回のアプローチですが、実は僕が考えた方法ではなくて、Kaggle で公開されているものです。

Screen Shot 2018-02-06 at 20.15.03.png

https://www.kaggle.com/gunner38/horseracing

今回の記事は Kaggle にアップロードされているデータとコードを元に自分なりに分析した内容を紹介していきます。

コードはすべて以下で公開しています
hourse_racing - cohki0305

データセット

Kaggle に用意されているデータ(csv ファイル)のカラムには、Tipster(予想屋), Date(日付), Track(レース場), Horse(馬名), Bet Type(予想), Odds(掛け率), Result(結果), Tipster Active(予想屋が現役か否か)があります。レース場に York とあるのでおそらくイギリスのデータですね。

Screen Shot 2018-02-06 at 20.19.39.png

約 39,000 のデータがあり、31 人の予想屋を元にデータが集められています。まあこれくらいあれば十分な気がします。

ライブラリを読み込む

はじめに今回必要なライブラリを読み込んでおきます

import numpy as np
import pandas as pd
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import train_test_split
from keras.models import Sequential
from keras.layers import Dense

前処理

はじめに前処理を行っていきます!文字列のままでは分析できないので、以下のようにしてカテゴリー分けします。sklearn の LabelEncoder を使うと簡単にできます。

cat_var = df.dtypes.loc[df.dtypes=='object'].index

le = LabelEncoder()
for var in cat_var:
    df[var] = le.fit_transform(df[var])

DataFrame を確認すると以下のようにいい感じに前処理できていることが確認できます。

Screen Shot 2018-02-06 at 20.35.23.png

学習用のデータとテスト用のデータを用意する

前処理したデータを学習用のデータテスト用のデータに分けておきます。学習用のデータは文字通りモデルを学習させる際に使います。そして、テスト用のデータは学習させたモデルがどれくらい正しい精度が出るのかを確かめるためのデータです。

X = df[['Tipster', 'Track', 'Horse', 'Bet Type', 'Odds']].values
y = df.Result.values

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.20)

Keras を使い学習を行う

Keras というフレームワークを使い学習させていきます。Google のエンジニアが開発した tensorflow のフレームワークです。

keras-logo-2018-large-1200.png

Keras を使うには、input の次元を調べる必要があるので、まず X の shape を確認します。

print(X_train.shape)
=> (30598, 5)

5 つのカラムがあって、列が約 3 万あることが確認できました。

Keras を使うと非常に簡単にニューラルネットワークの層を構築することが可能になりますよ。以下のように model に Dense を add していくだけです。

model = Sequential()
model.add(Dense(10, input_dim=5, kernel_initializer='normal', activation='relu'))

以下は、出力するニューロンを 10 個、input が 5 の 活性化関数が relu の layer という意味です。

Dense(10, input_dim=5, kernel_initializer='normal', activation='relu')

今回は予想屋が正解しているか否かを調べる Binary Classification なので、output 層は以下のようにしておきます。

model.add(Dense(1, kernel_initializer='normal', activation='sigmoid'))

そして最後に以下のように、loss function, optimizer, metrics を指定して、学習させます。学習は fit メソッドを使うだけなのでめっちゃ簡単です。

model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])

model.fit(X_train, y_train)

tipstars_keras.png

loss がめっちゃ大きいですが...accuracy が 0.8 つまり正答率が 80 % くらいになりました!
80 % の確率で予想屋の予想を当てられるということです。結構良さそうですよね。

モデルの精度を確認する

最後にこのモデルが未知のデータに対しても有効なものか確認していきます。今のところは学習用のデータでいい結果が出ただけなので、こいつが知らないデータを与えてもちゃんと正解できるのかを確かめていきます。

Keras では evaluate を使います。

score = model.evaluate(X_test, y_test)
score[1]
=> 0.80143790849673202

こちらも 0.8 くらいなので過学習が起こらず、未知のデータに対してもちゃんとした結果を出せることがわかりました!80 % なら全然金儲けできるよねw

課題

80% と結構いい結果でしたが、とはいえ、まだまだ課題があります....

  1. 日本の予想屋のデータでチャレンジする
  2. パラメータのチューニング
  3. モデルの比較

などなどがあるかなーと思っています。今回は Kaggle で楽しましたが、日本の競馬情報と予想屋の予想データを集めてくるのが結構大変そうだなという印象です。

(あとは僕が機械学習にそんなに詳しくないので、他にも課題があってもよくわからないという課題もありますね)

余談

今回は競馬の予想でしたが、予想屋の予想を行うアプローチは他の分野においても利用できそうだなと思いました。たとえば、株や FX など。本来これらの予想は変数が多くて分析するのが大変ですが、予想屋の予想であれば、今回のように数カラムで信用できる結果を得られるので、有効的なアプローチだと思う。

またこういう手法が一般的になれば、正しい予想を行う人なのかどうか機械学習によって厳しく評価される日が来るでしょうね。