競馬AI予測

【競馬AI #32】累計91件・的中0。原因は「偶然」ではなく「訓練時のデータリーク」だった

---

前置き:22件、すべて着外

前回(#31)は累計69件・的中0だった。その後の週末(10月17日・18日)は、推奨が一気に増えた。

10月17日(京都・新潟・東京):12件推奨 的中0

10月18日(京都・新潟・東京):10件推奨 的中0

22件とも着外。最高着順は4着だった。

全期間累計:91件 的中0 回収率0%

  札幌除外前(8/8〜8/30):43件 的中0

  札幌除外後(9/5〜10/18):48件 的中0

全ハズレ確率(バックテスト的中率9.6%想定)

  91件すべて   :約0.01%

  札幌除外後48件 :約0.8%

札幌除外後30件というチェックポイントは、この週末でとっくに超えた。事前に決めたルールでは、ここで「条件を変える前に、まず原因の特定を優先する」ことになっていた。今回は、その原因を突き止められた。

手がかり:シャドー記録が、初めて全体像を見せてくれた

#31で導入した「全出走馬の予測確率の記録(シャドー記録)」が、10月10日から動いていた。1,895頭・144レース分が溜まったので、初回の評価をした。

レース単位の対数損失(小さいほど良い)

  市場(単勝オッズ):2.016

  現行モデル    :2.490 (市場との差 +0.474、95%区間 +0.348〜+0.600)

現行モデルは、市場より**有意に悪かった**。市場に少しでもモデルを混ぜると、混ぜた分だけ悪化した。

さらに、買い条件に近い領域で、はっきりしたずれがあった。

オッズ20倍以上かつモデル確率8%以上の206頭

  モデルが期待した勝ち馬:約19頭

  実際の勝ち馬     :2頭

モデルは、人気薄の馬の勝率を約10倍に見積もっていた。

原因:訓練スクリプトに「答えの混入」があった

訓練スクリプトを読み直して、原因を見つけた。

馬・騎手・調教師・コース別などの「過去成績」の特徴量を、**そのレース自身の結果を含む全期間のデータで集計**して、同じ行に付けていた。

例:デビュー戦で勝った馬

  → その行の「過去の勝率」が 100% になる

  → モデルは「過去の勝率が高い = 勝つ」を、答えを含んだ状態で学習する

運用時は、当然ながら未来の結果は含まれない。同じ特徴量が弱くなり、モデルは人気薄の馬の勝率を過大に見積もる。

この問題は、訓練スクリプトのコメントに「既存仕様を踏襲」として書かれていた。リークとして認識はしていたが、運用への影響を過小評価していた。

しかも、ランダム分割のホールドアウト検証では、検証用データにも同じリークが含まれるので、検出できない。ここが盲点だった。

検証:時間で分けて、現行方式を再現する

「リークが原因なら、訓練に使っていない期間でも、同じ失敗が再現するはず」と考えた。訓練を過去、検証を未来に時間で分けて、現行方式を再現した。

現行方式の再現:EV3.5〜5.0帯を買った場合(訓練に未使用の期間)

  2025年:2,551件 32勝 回収率47.9%

  2026年:1,487件 21勝 回収率57.8%

実運用の69件・的中0(今回の更新で91件)と、整合する結果だった。

つまり、連敗は不運というより、**構造的に勝てない買い方をしていた可能性が高い**。以前のバックテストで出ていた回収率122.2%は、再現しなかった。理由は完全には説明できていないが、同じデータの中でEVの帯を何度も選び直した影響が大きいと見ている。

作り直し:Phase 4

リークを取り除いた新しいモデル(Phase 4)を作った。

✓ 特徴量は「その日より前」のレースだけで集計する

✓ 訓練と運用で、同じ関数で特徴量を作る(自己検査:不一致0件)

✓ 運用の出馬表に無い情報(馬体重・馬場状態)は使わない

✓ 市場情報(オッズ・人気)を特徴量に加える

2026年(訓練に未使用)での評価結果は次の通り。

レース単位の対数損失

  市場    :1.9404

  Phase 4   :1.9401 (差 -0.0003、95%区間 -0.0055〜+0.0049)

確率の校正は良好だった(予測平均と実際の勝率が、全ての帯でほぼ一致)。人気薄の過大評価も解消した。

ただし、**市場との差は0を跨いでいる。市場と同等で、上回るという証拠は出ていない。**

Phase 4 のEV帯ごとの単勝回収率(2026年、全レース)

  EV 1.0〜1.2 :1,679件 回収率 62.3%

  EV 1.2〜1.5 :  280件 回収率 80.1%

  → 100%を超える帯は無い

正直な結論

今回わかったことは、二つある。

1. 的中率が低かったのは、偶然ではなく構造的な問題だった可能性が高い

   (訓練時のデータリークによる、人気薄の過大評価)

2. リークを直しても、このデータ・この特徴量では、市場に勝てる証拠は得られていない

   (Phase 4は市場と同等)

「直せば回収率100%超になる」とは言えない。パリミュチュエル方式の控除率(約20〜25%)を超える優位性は、市場に含まれていない情報を新たに見つけない限り、出てこない。

これまでの記事で「100%を超える設計」を目指してきたが、**その前提となる評価自体に問題があった**というのが、現時点での結論だ。

訂正と、これまでの記事について

この発見によって、過去の記事のうち、次の点は見直しが必要になる。

#25(札幌の除外)

  → 札幌の偏りは一因だったかもしれないが、除外後も48件で的中0。

    主因はモデル側にあった可能性が高い。

#19〜#22(回収率100%超の設計)

  → EV3.50〜5.00という条件は、同じデータ内で選んだものだった。

    訓練外の期間では再現しなかった。

記事の過去分は消さずに残す。間違いを含めて記録することが、このブログの方針だからだ。

事前に決めたルールとの関係

札幌除外後30件を超えたため、「条件変更の前に、原因の特定を優先する」というルールに従った。原因は特定できた。

一方で、「シャドー記録が約3,000頭溜まるまでは、条件変更の判断材料にしない」というルールには、まだ届いていない(現在1,895頭)。ただ、時間で分けた検証では、約2,500件・約1,500件という、十分な件数で同じ結果が出ている。

現行ルールでの購入をどうするかは、この記事の時点では決めていない。次回までに決めて、報告する。

Data Scientistとしての振り返り

今回の教訓は、これまでで一番重い。

**「ホールドアウト検証で良かった」という事実は、リークがあれば何の保証にもならない。**

ランダムに分けた検証は、訓練と同じ「答えの混入」を共有している。時間で分けて、「過去だけで学習し、未来で評価する」という、運用と同じ条件で測らない限り、見えない問題がある。

そして、91件・的中0という痛い結果が、その問題を見つけるきっかけになった。結果が悪かったから、評価の仕組みそのものを疑えた。皮肉だが、これは収穫だと思う。

## 技術ノート

### 実運用累計成績(2026年10月19日時点)

```

全期間累計:91件 的中0 回収率0%

  札幌除外前(8/8〜8/30):43件 的中0

  札幌除外後(9/5〜10/18):48件 的中0

```

### 統計的評価(的中率9.6%想定)

```

91件すべてハズレ        :約0.01%

札幌除外後48件すべてハズレ:約0.8%

```

### 時間分割検証(訓練に未使用の期間)

```

現行方式の再現(EV3.5〜5.0):2025年 回収率47.9%(2,551件)/ 2026年 回収率57.8%(1,487件)

市場との対数損失の差    :現行 +0.47(実運用)、Phase 4 -0.0003(区間は0を跨ぐ)

```

---

## 次回の予定

Phase 4 の確率を、毎週のシャドー記録に並べて記録していく。訓練の最終日(10月18日)より後の日だけが、Phase 4 の本当の評価になる。数週間分が溜まったら、市場との比較を報告する。

---

**【競馬AI開発記】次回予定:**

- Day 33:現行ルールの購入方針の決定と、Phase 4 の初期データ

-競馬AI予測