馬券に人生フルベット ← 戻る

競馬AIの回収率100%は、なぜ再現しないのか

・ 書き手 馬券に人生フルベット
競馬の予測モデルを作った、回収率が100%を超えた——という記事はたくさんあります。私も作りました。AUCは0.839、1着的中率は30%まで来ました。それでも機械的に買うと回収率は0.6〜0.95で、一度もプラスに定着しませんでした。さらに一度は「エッジを見つけた」と判断して、あとから全部撤回しています。原因はモデルではなく、検証に使ったデータの方にありました。この記事は成功談ではなく、その一部始終の記録です。
30秒でわかる
  • AUC 0.839・1着的中率30%まで来ても、機械的に買えば回収率は0.6〜0.95で止まった
  • 一度は「エッジを見つけた」と判断し、撤回した。正体はデータの欠け
  • 疑う順番はモデルより先にデータ。同じ期間・対象の参照結果と、出走馬・着順・払戻を照合する

精度が上がることと、増えることは別物だった

まず数字から。過去10年ぶんのJRAデータで学習させたモデルは、6か月ぶんを学習に使わずに残して評価して、AUC 0.839・1着的中率30%・3着内67%まで来ました。数字だけ見れば十分に機能しています。

ところが同じモデルの予測で機械的に買うと、本命の単勝・複勝、3連複ボックス、期待値でしぼる買い方——どれも回収率0.6〜0.95に収まりました。控除率を超えられません。

順位を当てる能力と、オッズに対して割に合う馬を見つける能力は、別々のものです。前者が高いだけでは後者にはなりません。ここを混同したまま「精度が出たので回収率も出るはず」と進むと、あとの検証がすべて甘くなります。

リークは3層ある。3層目はあまり語られていない

予測に未来の情報が混ざることをデータリークと呼びます。競馬AIの解説記事でよく挙がるのは最初の2層です。

1層目は分かりやすい未来情報。着順、走破タイム、上がり、通過順、確定オッズ、確定人気。レースが終わらないと確定しない値を特徴量に入れてしまう形です。

2層目は集計の作り方によるもの。騎手の勝率のような「過去の平均」を作るとき、集計対象にそのレース自身が入っていると、答えの一部を特徴量に埋め込んだことになります。過去だけを見るようにずらす処理が要ります。

評価データが欠けるという3層目

3層目が、私が実際につまずいたところです。特徴量は正しく作れていても、評価に使うデータの方が欠けていると、リークと同じように成績が水増しされます。この層はあまり書かれていません。

層どこで混ざるか本文で挙がった中身
1層目分かりやすい未来情報着順、走破タイム、上がり、通過順、確定オッズ、確定人気
2層目集計の作り方騎手の勝率などの集計対象にそのレース自身が入っている
3層目評価に使うデータ特徴量は正しくてもデータが欠けて成績が水増しされる

「エッジを見つけた」を撤回した話

オッズを使わないモデルを作ったとき、市場より優れた判断ができているように見える結果が出ました。検定にもかけて、統計的にも支持されたと判断しました。

数え直して分かったこと

おかしいと思って評価データを数え直したところ、レースの66%で出走馬が欠けていました。18頭立てのはずが3頭しか入っていないレースがあり、37%のレースでは勝ち馬すら含まれていませんでした。

何が起きていたか。欠けていたのは主に人気薄です。よく走る馬ほど過去データが揃っているので、集計に残りやすい。結果、評価データは「堅い馬だけの世界」になっていました。その世界では市場1番人気の単勝回収率が1.13になります。回収率が高いことだけで欠損とは断定できませんが、この評価では出走馬の欠落も確認できました。

つまり見つけたのはエッジではなく、データの欠けでした。検定の数字は正しく計算されていましたが、入力が現実と違っていました。結論は撤回しています。

評価データの66%で、出走馬が欠けていた
馬が欠けた66%
勝ち馬不在37%
棒の目盛り: 0〜100%
オッズを使わないモデルの評価データを数え直した結果。欠けていたのは主に人気薄で、その世界では市場1番人気の単勝回収率が1.13になっていた(この値だけでは欠損を断定できませんが、出走馬の欠落も確認済み)。 馬が欠けた=18頭立てで3頭の例も。

公開前に確認したい3つの点

この経験を踏まえ、公開前には次の3点を確かめる必要があります。

1つめ。市場1番人気の単勝回収率を、同じ期間・レース範囲・計算法の参照データと照合します。控除率だけから正常値の範囲は決まりません。参照値からずれたら、まず抽出条件や欠損を調べます。

2つめ。公式の確定結果と照合し、同着を含む勝ち馬が欠けていないかを確認します。3つめ。出走馬IDの集合・頭数を参照結果と比べ、重複・欠損を調べます。取消・除外・競走中止も区別し、行数と着順の最大値が合うだけで完全とは判定しません。

閾値を200%に置くと見逃す

「ROIが異常に高かったらデータを疑う」という目安だけでは十分ではありません。閾値を200%のように置くと、今回の1.13の水増しは素通りします。同じ条件の参照結果と、馬ごとの記録を照合することが必要です。

図解|予想を確定する時点で、情報を区切る
  1. 過去で準備する学習や条件選びは過去のデータで行う
  2. 予想を確定するその時点で取得できた情報だけを使う
  3. 未使用の期間で評価確定した予想と、その後の結果を照合
  4. 改善は次の評価へ結果を見た変更を、元の評価に混ぜない

時間の向きは一方向。あとから分かった情報を、過去の予想時点へ戻さない。

評価の基本形を示す概念図です。予想確定後の最終オッズ・結果や、評価期間の成績を見た条件変更を、その評価の入力へ戻しません。これだけで再現性が保証されるわけではありません。

オッズを入れると、モデルは市場の写しになる

オッズや人気を特徴量に入れると精度は明確に上がります。私のモデルでも、重要度の上位4つを市場系の特徴が独占し、合計で83%を占めました。

ただし中身を見ると、モデルの本命は市場の1番人気と91%一致していました。ほぼ同じことを言っているだけです。

さらに、意見が割れた61レースだけを取り出すと、モデルの的中14.8%に対し市場は29.5%でした。食い違ったときは市場のほうが当たっていたわけです。オッズ入りモデルの高い精度は、市場をうまく再現できているという意味であって、市場に勝てるという意味ではありませんでした。

意見が割れたレースでは、市場のほうが当たっていた
市場1番人気29.5%
モデル本命14.8%
棒の目盛り: 0〜100%
オッズ・人気を特徴量に入れたモデルの本命と、市場1番人気が食い違った61レースのみを取り出した1着的中率。両者は全体では91%一致している。

オッズを抜くと、何が見えたか

そこで市場の情報を完全に外したモデルも作りました。精度は当然落ちます。AUCは0.839から0.788へ、1着的中率は30%から24%へ。

代わりに独立性が手に入りました。オッズを±20%動かしても、欠損させても、予測はまったく変わりません。参照していないので当然です。市場との本命一致率も91%から58%に下がりました。別の意見を言うモデルになったということです。

この独立したモデルでは、いくつかの買い方で学習期間・検証期間の両方で回収率が1.0を超えました。ただし該当したのは50〜100件程度で、この件数では誤差の範囲を出ません。有望な兆しではありますが、確かめられたとは言えない段階です。

指標オッズ入りオッズを抜く
AUC0.8390.788
1着的中率30%24%
市場との本命一致率91%58%

それでも壁は越えられていない

ここまでやって、私はまだ持続的なプラス収支を確認できていません。控除率という構造が、思っていたより厚いというのが現時点の結論です。

誤解のないように書いておくと、モデルを作ること自体は無駄ではありませんでした。どの条件が3着内と着外を分けているかは実際に見えるようになりましたし、このサイトの重賞メタ読みはその副産物です。ただ、それは「見え方が整理される」ことであって、「増える」ことではありません。

回収率100%超えを掲げた記事を読むときは、検証期間の長さ、買った件数、そして評価データが欠けていないかを見てみてください。私の場合、そこに原因がありました。

この記事の持ち帰り
  • 回収率100%超えの記事で先に見るのは、検証期間の長さと買った件数
  • オッズを特徴量に入れたモデルは、本命が市場1番人気と何%一致するかを数える
  • 自分で集計するときは、同着・取消・除外・中止を区別し、出走馬IDの重複と欠損を確かめる
🏇 重賞メタ読みを見る → 重賞カレンダーで日程を確認 →
馬券に人生フルベット
馬券に人生フルベット
データで楽しむ競馬 / 重賞の参考スコアを無料公開
むずかしい数字を見やすく整理してお届け。過去データから効く指標と効かない通説を数値で可視化。「予想の断定」ではなくデータに基づく参考スコアを無料公開しています。