競馬AI作ってみた話

題名の通り最近競馬AIを作って遊んでます。 機械学習を触ってみたかった + 機械学習の対象にできそうで詳しい対象が競馬だった、といった感じです。

備忘としてどんな感じで進めているのかを書いておこうと思います。

データソース

学習のためのデータを取得するところから始めないといけないですが、便利なコードが公開されていたので使ってみることにしました。

github.com

netkeibaをスクレイピングしてデータを集めてくれます。 Scalaで書かれています。Scalaは触ったことがなかったので学習としてもいい感じでした。 ソースは古いみたいでそのままでは使えないのである程度改造する必要があります。(レースの区分けが500万下とかで古いので最新のデータ取得がうまくいかない。) また並列処理にしたほうが早いかな~とか色々いじれる箇所アリ。 Scalaは並列処理めっちゃ書きやすかったです。もうちょっと勉強するのもアリだなー...

あとDBにSQLite使っていますが、これも手軽に扱えてよかったです。DBは現場で使っているのしか触らないがちなのでこういうところで経験値積むのもいいかも。 一方でデータ量が多いのでDynamoDBとかに変えたほうが早いかも?などと...この辺も余裕があればいじりたいところ。

機械学習フレームワーク

LightGBMを使いました。競馬AIとかで検索するとこれ使っているのが多かったです。 使ってて思いますが処理早いです。欠損値の扱いもしやすくてとても楽。

パラメータチューニングのところは要勉強...

データ整形

ラベルエンコーディングしたくらい。 特徴量はとりあえず持っているデータ全部突っ込みました。LightGBM側で重要度とか出してくれるのでそれもいい点ですよねえ。

上がり3Fタイムを使おうとしても、レースのペースによって結構変わってくる数値なので"上がり3F / レース上がり"みたいに処理してあげたりはしています。

この辺の整形はまだまだやりようがありそう。

目的変数

二項分類で学習させるのか、回帰分析で連続数値を予測させるのかの二パターンやってみました。 参考: http://www.tani.cs.chs.nihon-u.ac.jp/g-2018/ML_HR/ML_HR_final.pdf

二項分類では3着以内かどうかで分類させましたが、これはオッズが加味されないので欠点ですね。。。 データの重要度を出しても騎手のスコアが高く出てくるのでそりゃあそうって感じでした。 儲けようと思うと二項分類での学習は限界があるかも?

回帰分析では複勝期待値を予測させました。 これで購買シミュレーションしてみたので乗っけてみます。

購買シミュレーション

学習データは2013-2020年、検証データは2021,2022年、購買シミュレーションに使うデータは2023年のデータとしました。

(予測時点では未来の成績はわからないので時系列で分けてますがこれはどうなんでしょう?このあたり勉強不足です。)

収支シミュレーション

複勝期待値の予測をさせて、期待値がX円を超えた馬を複勝で100円買うといった感じで馬券を購入したシミュレーションをさせてみます。

収支シミュレーション 縦軸:収支 横軸:複勝期待値

横軸は複勝期待値です。モデルに複勝期待値を予測させ、複勝期待値が横軸の値を超えたら複勝で100円買うようにしています。

横軸のスケールがバグっているんですが、10000のところが予想複勝期待値100円に対応します。

縦軸は馬券を購入していった場合の最終収支になります。

複勝期待値100円付近で0に近づいていますが、そこを超えるとガクっと落ちています。期待値が100円超えているところで購買していったら儲けがでるようにしていきたいので予想モデルはまだまだですね...

回収率シミュレーション

次に回収率も見てみたいと思います。

回収率シミュレーション 縦軸:回収率 横軸:複勝期待値

横軸は所持金シミュレーションと同じく複勝期待値です。モデルに複勝期待値を予測させ、複勝期待値が横軸の値を超えたら複勝で100円買うようにしています。 同じく10000のところが予想複勝期待値100円に対応します。

縦軸は馬券を購入していった場合の最終回収率です。

青の補助線は回収率100%、赤は90%のラインです。

複勝期待値100円付近で回収率100%近いのは収支所持金シミュレーションと同じくですね。

横軸が14000(つまり複勝期待値140円)あたりから回収率が100%を超えてきています。

これはいい感じでは!?と思ったんですが、データを見てみると購入馬券数が6点(!)ほどしかなく、サンプル少なすぎて運がいいだけだろうな...になりました。悲しみ。(15500以降は購入馬券が0です。2023年の半年くらいのデータでやっているので半年で6点の購入とかだとあまりにしょっぱい...)

ただ穴馬を探す手伝いくらいにはなるかもしれません。

今後やりたいこと

データ整形のところはまだまだやれることがありそうです。 また、持っているデータから新しく特徴量を作っていくこともやっていきたいところ。 (例えば前走からのレース間隔とかのデータが今のところないです。)

最終確定オッズがレース前にはわからないので特徴量として使うのはいまいちだと思う一方で、馬券購入時はオッズを考えて馬券を買うと思うのでこのあたりどうしようか悩み中です。

あと馬券の自動購入プログラムも作っていきたいですが時間がない...

(手伝ってくれる人を緩く募集しています。知り合い限定になりますが...)