機械学習で競馬の回収率140%超を達成：開発までの話

競馬の単勝回収率140%を達成した機械学習モデルの開発プロセスについて書きたいと思います。
この記事では、データ収集から実際の予測までの一通りの流れを説明します。このモデルによる実際の予測はNoteで公開しています。

Note：https://note.com/umaro_ai/

## 0. はじめに
競馬は運の要素が強いと思われがちですが、実際には馬の能力、血統、調教師の技術、レース適性など、多くの要因が結果に影響を与えます。これらの数百にも及ぶ複雑な要因を人間が考慮するのは難しいため、機械学習は有効なツールとなります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3852948/a63ce2ae-e9e1-52a1-2d83-ddde438296d8.png)


機械学習の大まかな流れは以下の通りです。これは競馬予測に限らず、ほかの予測でも使う基本的な工程です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3852948/8d34a8cb-ed18-a3d0-c2bb-5d1331868da2.png)



## 1. モデル設計

始めに作成するモデルの方針を決定します。競馬は投票方法により払戻率が異なります。つまり人気馬やなんとなく予想して買い続けた場合は以下の払戻率に収束していきます。長期的に買う場合は投票法の選択も大きく回収率に影響します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3852948/ecb95435-e6e7-6d50-8d90-bade6b3e098a.png)


今回は長期的に回収率を高めることが目的のため、払戻率が高く かつ 試行回数が多く収束しやすい単勝を予測するモデルを作成します。
なぜ複勝ではないのかという点については今後のNoteで詳細を説明しますが、シンプルに単勝の方が回収率が高くなるためです。


## 2. データ収集

まず最初に必要なのは、モデルに学習させるためのデータです。競馬に関するデータはインターネット上に多数存在しますが、取得方法は大きく分けて　①JRAデータベース　②ネットスクレイピング　のどちらかになります。今回は様々な項目のデータを扱う①JRAデータベースを選びます。

データベースには多くのデータがありますが、大まかには以下のようなデータが取得できます。

　- **レース結果データ**: 過去数年間の全てのレースの結果データ。
　- **馬データ**: 各馬の血統、年齢、性別、過去の成績など。
　- **騎手のデータ**: 騎手の過去の成績や特徴。
　- **コース・天候データ**: レースが行われるコースの情報や、その日の天候、馬場状態など。


## 3. データの前処理

収集したデータはそのまま使うことができません。次に行うのは、データの前処理です。これは、データをクリーニングして扱いやすい状態にするプロセスです。

欠損値が存在する場合、それを補完するか除外するかを決定します。例えば、落馬等で出走したのにレース結果がない場合などは除外する必要があります。


## 4. 特徴量作成

特徴量とは予測にするために必要な情報であり、この特徴量を抽出・生成するプロセスです。個人的にはここが最も他者のモデルと差別化できるポイントだと思っており、最重要工程と考えます。

収集したデータをそのまま学習しても、オッズなどと相関が高くなり人気順に近い予測結果が出力され回収率≒払戻率（単勝なら80%）になります。なので、回収率を高められるような特徴量を作成していきます。

本モデルは前提として人気やオッズの情報は特徴量に使わないでいきます。これらは最終締め切り時間まで変動する値なので予測時点では正確な値ではないことと、人気順にひきづられた結果となります。そのため、これらを排除して、人気やオッズを関係なく単純に一番強い馬を予測できるようにします。

本モデルでは、数百以上の要素を作成して検証した中から、回収率に影響のある特徴量のみを学習させていきます。具体的な特徴量の一部は以下となります。

[学習させる特徴量]
馬能力指数、レース適性、血統、馬場適性、過去レースの結果(タイム指数、上り結果、不利状況、etc)、ジョッキー、ジョッキー×馬の相性、馬番の優位性、馬性別による成長差、調教師、輸送距離、PCI　etc


## 5. データの分割

ここではデータセットを学習用・テスト用・予測用に分割します。
分割の仕方はいくつか種類がありますが、今回は直感でわかりやすいように年数ごとにわけていきます。2年以上前までのデータで学習して、その結果を去年1年間のデータで実際に評価してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3852948/d1c1f39c-70dc-b31c-2bd9-614fdaf58143.png)


## 6. 学習

次に、モデルの学習を行います。
機械学習モデルはLightGBMを選定しました。
LightGBMは、勾配ブースティングアルゴリズムの一種であり、高速処理・正確な予測・大規模データに向いています。

今回は、予測結果として"1着指数",  "2着以内指数",  "3着以内指数" の3つの値を出力します。単勝なら1着指数だけでも良いですが、馬連や3連系を買うときの参考情報に使えるため合わせて予測します。


## 7. テスト予測・評価

モデルを学習した後に行うのは性能評価です。評価には、以下の指標を使用しました。

　- **的中率**: 1位と予測して的中した数 / 1位と予測した数
　- **回収率**: 1年間購入し続けた場合の回収率（払戻金額/購入金額)

これらの評価指標を用いて、モデルのパラメータチューニングや特徴量の修正・追加・削除などを繰り返して的中率・回収率をあげていきます。

その結果がこちらです。1位予測の馬を1年間買い続けた場合の回収結果です。
　「回収率＝116% 　的中率＝26%」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3852948/7c5897fa-852d-6ad5-2fe5-2bef3b321f7a.png)


これでも十分良い結果ですが、1位予測の馬を全部買っているため的中率が若干低いのが気になります。
そこで、微妙なレースは買わずに圧倒的に1位が取れそうなレースだけを買いたいと思います。これは予測した指数に対して閾値を設けて、クリアした馬のみに本命馬フラグをつけます。

本命馬のみを購入した結果がこちらです。
　「回収率＝141% 　的中率＝41%」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3852948/78ebd802-4ca0-0a4e-8020-bae79a5c7131.png)


本命馬のみ絞ることで、敵襲率が大幅に改善しました26%→41%。それに伴い、負け額が減らせるため回収率も向上しました。


## 8. 本番予測

モデルが完成した後は、実際にレースの予測をします。 レース当日の最新データを取得してきてモデルに入力します。ここはテスト予測と同じ工程です。
　

## 9. まとめ

今回、機械学習を用いて競馬の単勝回収率140%を達成したモデルを開発しました。現在も更なる回収率向上を目指してアップデート中です。
このツールで予測した結果はNoteで公開していますので、よかったら参考にしてみてください。また、各工程の詳細については今後別のNoteで説明していく予定です。

Note：https://note.com/umaro_ai/