🏇予想のモデルを考える

この記事は Speee Advent Calendar の2日目になります。

昨日は id:nisshiee の 『AWS Batchを本番導入するにあたって考えたことアレコレ』 でした。


弊社で年に2回ほどある Speee Kaigi というイベントで『競馬×機械学習』というテーマで発表しました。

発表時点では予想モデルといえるようなものはできておらず、トークの勢いで押し切っただけでした。

なのでしっかり要素として切り出せるものを色々と盛り込んで見ようと思い立ちました。

結論

この記事で予想モデルが完結しているものではなく、机上の空論な状態です。

こんな風にして組み立てていくのかなという思考ログに相当するようなものです。

前提

  • できる限り容易に取得できる情報を利用する

具体的には、 netkeibayahoo競馬 とかで見ることのできる出馬表などのアクセスしやすい情報で予想しようというものです。

なので、競馬新聞に掲載されている調教師や厩務員コメント、調教タイムといった要素は省いています。

出馬表の見方

まずは、出馬表の読み方からです。

先日行われたのジャパンカップ(G1)に出走した キタサンブラック 号の netkeiba ページを例に取り上げます。

f:id:kawakubox:20171202020701p:plain

左から

  • 枠番
    • 1 ~ 8
  • 馬番
    • 1 ~ 18
  • 予想欄×4

次のセルからは情報量が多いので切り出して説明します。

f:id:kawakubox:20171202021842p:plain

上から

  • 馬名
  • 父馬
  • 母馬
  • 母父馬
  • 調教師所属, 調教師名
  • 脚質(逃げ、先行、差し、追い込み)
  • 馬体重(前走との差)

f:id:kawakubox:20171202023302p:plain

上から

  • 性別, 年齢, 毛の色
  • 斤量*1
  • 騎手名

f:id:kawakubox:20171202023327p:plain

f:id:kawakubox:20171202023128p:plain

  • 過去の出走レース ※左から1走前、2走前 ... 5走前
    • 開催日, 競馬場名, 着順
    • レース名, クラス(=グレード)
    • コース, 距離, タイム, 馬場状態
    • 出走頭数, 馬番, 人気, 騎手名, 斤量
    • コーナー通過順, 上がり3Fタイム*2, 馬体重, 馬体重の増減
    • 勝ち馬or2着馬, 勝ち馬とのタイム差

拾える情報はこのくらいでしょうか。

予想式

競馬には『馬七人三』という格言があります。 これは競馬の勝敗は馬の能力だけではなく、人も関係しており、その比率は7:3であるという意味です。

この具体的な比率が適切かはさておき、以下のような関係式が起こせそうです。

{ \displaystyle
y = H + Px
}

※Hは馬(horse)、Pは人(person)

人については、さらに騎手と調教師に要素分解して考える事もできそうです。

{ \displaystyle
y = H + Jx_1 + Tx_2
}

※Jは騎手(jockey)、Tは調教師(trainer)

騎手

騎手は勝率、連対率*3複勝*4のような数値がweb上で取得できるので、この辺の値がこのまま使えそうです。

突き詰めるとコース、距離の傾向も取れますが入手しやすい情報かと言われると 🤔 となります。

調教師

調教師も騎手と同様にwebから取得できます。

馬は過去の出走成績が手がかりになります。

netkeiba ですと、無料で5走前、有料で9走前までページ内に表示されます。

直近n走前までの結果の平均とみなすと以下のようになりそうです。

{ \displaystyle
H = \frac{1}{n} \sum _{i=1} ^n R_i
}

もしくは、最近のレースをより評価するのであれば

{ \displaystyle
H = \frac{1}{n} \sum _{i=1} ^n (R_i w_i)
}

※Rはレース結果(Result)

とも置けそうです。

レース結果

ここの数値化が一番キモですが、騎手や調教師のデータとは異なり一筋縄にはいかない部分になります。

出馬表で得られる数値情報はいくつかありますが、どれも単項目では評価しづらいです。

  • レースタイムは、クラス、コース、距離、馬場状態、展開といった要素に大きく左右される

    • 東京コースはホームストレッチが長い
    • 京都コースはホームストレッチに坂がない
    • 馬場状態が良と不良ではレースタイムに5〜10秒近くの影響が出ることもある
  • 馬体重(増減含む)は、良い状態をベースに±αを考慮しないと意味がない

  • 上がり3Fタイムも脚質、展開によって変わる

    • 前半がゆったり流れると当然タイム速くなる、逆も然り

要はレース単体での数値を取り上げたところで意味はなく、他のレースと比較できる状態にあることが求められるわけです。

レースの比較をする

取っ掛かりして、クラス、コース、距離、馬場状態といったセグメント毎の平均レースタイム(基準タイム)を知っていると仮定します。

この基準タイムと実際のタイムとの偏差を求めることで、同一セグメント内での優劣が取れそうです。

{ \displaystyle
\sigma = B - A
}

※ Bは基準タイム(Base TIme), Aは実際のタイム(Actual Time)

この偏差にはいくつかの係数を掛ける必要があると思われます。

なぜならば、今予想してるレースと偏差求めたレースのセグメントが同じとは限らないからです。

  • 今回予想するレースと同じ条件であればより評価したい
  • 勝ち上がってクラスが上がったことで過去レースの偏差からは割り引いて評価したい

といったことが考えられられます。

{ \displaystyle
\sigma = (B - A)k
}

まとめてみる

これを先の馬個体の式に代入して

{ \displaystyle
H = \frac{1}{n} \sum _{i=1} ^n ((B - A)k w_i)
}

馬、騎手、調教師の式に代入して

{ \displaystyle
y = \frac{1}{n} \sum _{i=1} ^n ((B - A)k w_i) + Jx_1 + Tx_2
}

こんな感じまで持ってこれました。

実際のレースには最大18頭まで出走することができるので、

{ \displaystyle
m \times n
} 行列として書き起こせるような気もしてます。

※mは最大18、nは過去レース結果を5レースとすると7

教師データ

教師データをどう用意するかですが、中央競馬1年間で3,000を超えるレース数があるので、数年間分集めればそこそこの数を用意できそうです。

ただ、レース条件のバラつきがあるので、どういった切り口で用意するかは TRY & ERROR でやる必要がありそうです。

今考えているものは以下のようなものです。

レースの配当別に教師データを用意する

馬連の配当に着目し、

  • 順当(払戻金 〜1,999円)
  • 小波乱(払戻金 2,000円〜9,999円)
  • 大波乱(払戻金 10,000円〜)

といった分類で集めて学習を行い。

順当ケース、小波乱ケース、大波乱ケースのそれぞれの予想モデルを作ろうというものです。

順当で決まるレースが最も多いので、これらを分けず学習してしまうと、学習結果のモデルは順当な結果を返すものになってしまうのではないかと危惧しております。

ほかの案

  • 距離別に切り出す
  • クラス別に切り出す
  • コース×距離別に切り出す

など他にもたくさん考えられそうですね。

最後に

ここまでとりとめもなく書いてきましたが、なんらかの機械学習フレームワークに突っ込んだわけでもないので、机上の空論ではあります。

高校レベルの数学がやっとな中で機械学習なぞに手を出してしまい、手探りで進めている感じではあります。

もともと興味のあった競馬という題材は僕の中で身近なものだったので、そういったものを軸に徐々に理解を深めていけばいいのかなと思っております。


明日は yukihisamatsu より『bandit周りのまとめ、もしくは趣味でやってる懸賞でやってみたデータ分析のまとめ』になります。

お楽しみにっ

*1:騎手の重量

*2:*ラスト600mにかかった秒数

*3:2着までに入る確率

*4:3着までに入る確率