競馬の予測モデルを自作した

3回目の挑戦。
前回の記事
https://datacreative.me/blog/mlr_analysis/

準備

前回同様データはnetkeiba.comの2006~2017年のデータをお借りした。 使用したツールは以下。

  • python
    • pandas
    • numpy
  • Exploratry
    • R
    • random forest
    • XGboost

pythonはデータをスクレイピングするため、Exploratryは分析・予測モデル構築のために使用。

戦略

前回は連対率を予測し、複勝転がしでやったが惨敗だった。
今回は1位になる確率を予測し、単勝で勝てるかどうかをとことん検証する。

ちなみに最終的に決まった戦略は以下。

  • 10,11レースの
  • 信頼性42%以上で1位になると予想した
  • 単勝

※今回は新馬、未勝利は予測の対象外とする。

STEP1 重要な指標を特定する

最初のステップとしてとりあえずどのデータが1位になるために重要なのかをざっくり把握する。
※一部抜粋

Variable Importance
単勝オッズ 857.28
人気 585.14
重量 347.90
複勝率 330.62
連対率 270.73
体重差 261.38
出場回数 241.54
単勝率 237.66
2位入賞率 236.11
馬番 226.01

当たり前だけど、オッズと人気度が一番重要らしい。

STEP2 ライバルを決める

今回は1番人気のみで予想した場合との比較で効果を測定してみる。
なので、1番人気かつ実際に1位だった場合の混同行列(Confusion Matrix)を出してみる。

Loading...

1番人気の馬だけに賭け続けたら30%の確率で当たるみたいだということがわかる。

STEP3 ランダムフォレストで予想する

この結果を持って、ランダムフォレストで試しに予想してみる。

Loading...

TRUE , TRUE → 買った馬券が当たった確率は25.32%だった。
人気度だけで予想した時よりも低い。
そして無駄に処理が長い。

STEP4 XGboostで予想する

同じ要領でXGboostの予測精度を確認してみる。

Loading...

23.58%で少しだけ下がった。
処理は結構早かった。

STEP5 西田式スピード指数で予想する

競馬の有名な指数らしいスピード指数というものを使って予想してみる。
http://www.rightniks.ne.jp/index.php?action=whatspidx_contents&name=sikumi

予想の仕方は、スピード指数が一番高いものを1位であると判断する。

Loading...

7%だけだった。エラーもたくさんある。
まあ前走のスピード指数を予測にしてるから新馬とかのデータがないのは当然っちゃ当然か。

STEP6 予測走破タイムで予想する

XGboostは回帰もできちゃうのでタイムを予想してみる。
上記で作成したスピード指数も使ってもう一回モデルを構築する。

Loading...

結果は的中率5%だった。
全然参考にならない。。

でも一応中身も確認してみる。

Loading...

一応それっぽく予測してるっぽいことはわかる。

Loading...

相関係数は99%を超えた。

Loading...

r_squaredは0.9861で結構良い制度で予測しているにも関わらず、結果がよくない。
レースでは0コンマの違いで順位が変わるからもっと精度をあげないといけないということなのだろうか。

STEP7 順位をそれぞれ予想する

XGboostには他クラス分類もできる機能があるので使ってみる。
上記の指標といろいろ追加したものを使って1−18くらいの順位をそれぞれ予想してみる。

Loading...

17.56%くらいでパッとしない

Loading...

ヒートマップを見ると、実際に1位であったパターンが最も多いが、はずしたパターンもたくさんあるという事実は無視できない。

Loading...

精度もよくない。

STEP8 アンサンブルする

上記で予測した結果と確率などのデータを元にXGboostの二項分類で1位になるかを予想してみる。

Loading...

だいぶ改善された。

STEP9 データを調整する

上記で作ったモデルのパラメータをいろいろいじってみた。
また論文やテレビや記事でみた良さそうな指標もいろいろ試してみた。

  • 経験は成績に影響するのか?
  • 乗換えの発生は成績に影響するのか?

などなど

検証

これまでは正答率を上げるために努力してきたが、次からは上記のSTEPで作ったモデルの特徴を把握し、馬券を買ったら儲けが出るのかをシミュレーションする。
それを持って利益が出るように改善していく。

ラウンド別正答率

8,9,10,11レース目が精度が高い。

Loading...

人気別正答率

1番人気の正答率が高い。
かなり人気に依存していることがわかる。

Loading...

信頼度別正答率

0.55を超えると正解している割合が増えていることがわかる。

Loading...

8,9,10,11レース目でpredicted probabilityが0.55以上のものが買いなのかな。
0.4くらいだと外れる割合の方が多いみたい。

結局いくら儲かったのか?

実際に馬券を買って、どのくらいの利益ができるのかを検証してみた。
30%のテスト用データで回収率500%で30万円くらい儲かるかもしれないことがわかった。
100円づつ賭けただけで結構いいスコアになった。

Loading...

予想した推移を見てみると、万馬券もいくつか出ている。

Loading...

8,9,10,11レースだけを対象に予測した馬券を買った場合

データを8,9,10,11レースだけに絞って再度モデルを構築してみた。

正答率は改善された。

Loading...

でも利益はかなり減っている。
買う件数が減ったからっぽい。

Loading...

最終的に完成したモデルの精度は?

最終的に出来上がったモデルの精度と、実際に馬券を買ってどのくらい儲けが出るのかをシミュレーションしてみる。
馬券の買い方は、信頼性(小数点切り捨て)*100
ただし、信頼性が低かったら100円だけ賭けるという戦略(?)にする。

1位だと予想した馬の実際の順位。

Loading...

70%くらいが実際に1位になってる。

信頼性が高いほど正解する割合も増えている。
信頼性が50%前後だと外れる可能性も高いことがわかる。

Loading...

正答率も70%になった。結果的に人気度だけで当てる確率の倍以上になった。

Loading...

推移を見てみると大勝ちしなくてもそこそこの勝ちが続いていることがわかる。

Loading...

回収率も1000%超えた。このままいけば家買うのも夢じゃないかも。

Loading...

まとめ

この2週間くらいで記事では書ききれないほどいろんなパラメーターや指標やモデルを触ってみて、ROCカーブやP-valueなどを確認しながら改善しまくった結果、
当初の2倍以上の精度に昇華させることができた。

施行 正答率
1番人気 29.97%
ランダムフォレスト 25.32%
XGboost_二項分類 23.58%
スピード指数 6.91%
XGboost_回帰 5.29%
XGboost_カテゴリ 17.56%
アンサンブル 45.28%
調整後 52.08%
最終 70.95%

今は実際のレースで使う時にある程度手作業をする必要があるので、次は全自動にしてslackで定期的に通知させるようにしたいな。
あと実際の利益は小さいけど今のところ回収率は100%を超えてる。

この一連の手順は、データでサイエンスするということの定義に当てはまっているのかな。
ということである程度データ分析で価値を見出したということで及第点くらいはもらってもいいのではないだろうか。

課題

スピード指数は前走のスピード指数を使用しているので欠損値がある。

走破予測タイムを元にスピード指数を計算し直せばもっとマシな結果になるのかな?

レースをかなり選んでいる

このモデルは結局10,11レース かつ 信頼性が一定以上であれば買う(それ以外は見送り)にしている。 なので1位になる確率が当該レースの中で一番高くて実際に1位だったとしても買わない。という選択をする回数が結構多い。

惜しいレースが多々ある

このモデルを実際に使ってみて、1位の信頼性が高く、2位以下の信頼性が低い場合、その順位が3連複になっていることが多々ある。
この結果の中にもっと利益を上げるヒントがあると思うのだが、それはまた今度試す。