0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AI と 26 ラウンド議論して個人開発の競馬予測 ML を育てた話 — ROI 0.91 → 1.66 への試行錯誤

0
Posted at

競馬予測 ML モデルを Gemini と二人三脚で改善した試行錯誤の記録

「AI と議論しながら ML モデルを育てる」とどうなるか。LightGBM の競馬予測モデルを舞台に、Gemini との 26 ラウンドにわたる議論と実装の往復で見えてきた、データサイエンスの罠と発見をまとめます。仮説が真っ向から反証される瞬間、反証の真逆で実証される瞬間、異常値がリーク疑いを超えて本物だと確認できた瞬間 — Echo Chamber (モデルの市場クローン化) からの脱出Bill Benter 型 Two-Stage 仮説の検証と反証Heteroscedastic Top-K Identification という発見 まで、一人で進めていたら絶対に辿り着けなかった景色を、できるだけそのままの温度で書き残しました。本記事は ML プロジェクトの技術メモであり、馬券購入の推奨・助言ではありません

私のコメントはここだけで、本記事はほぼAIが書いています。内容については概ね理解していますが、数学的な細部までは追いきれていないところがあります。
ClaudeとGeminiによって、このモデルの完成までこぎつけた内容になっています。
そして、なによりも私はこれまで競馬について触れたことは一切なく、あくまでも本記事はMLによる予測が可能なのか、また、そのモデルをAIを活用してどこまで実現可能なレベルまで引き上げられるかを試した記録です。
仮に今後、このモデルを使った予想をSNSに投稿することがあったとしても、それは購入助言ではなく、作成したモデルの予測性能を検証する目的以外にはありません。
また、本日5/15時点でこのモデルを使って実際の予測を立てて検証はしておらず、私的には過去のデータでいくら良い成果(ROI 1.6)を出せていても眉唾だなという思いでいっぱいです笑


1. プロジェクトの背景とゴール

JRA 中央競馬の着順を LightGBM (lambdarank) で予測する個人開発プロジェクトを、2 週間足らずの短期集中で v3 から v11 まで一気に育てました。Kaggle 公開データ (1986-2021) と、2021 年以降は自前で整備したデータセットを組み合わせ、出発点は v3 (基本)、v6-pure-rich (interaction features)、v8-pure (adaptive features) の 3 モデルをアンサンブルする構成です。

本記事に出てくる「私」は著者ひとり、「Gemini」は議論相手として使った Google の対話 AI です。プロジェクト全体はひとりで設計・実装していますが、仮説出しと反証の壁打ち相手として Gemini を恒常的に使っており、本記事はその約 2 週間の往復ログを技術記事として整理したものです。

想定読者と前提知識

本記事は以下のような方を念頭に置いています。

  • ML エンジニア / データサイエンティスト: LightGBM (GBT)・ランキング学習・キャリブレーション・IC (情報係数) は既知の前提で進めます
  • 競馬ファンで ML に興味のある方: 馬券種類とオッズの基本さえ押さえてあれば、コードは読み飛ばしても流れは追えるよう書きました

馬券種類だけ最低限ここで揃えておきます。

馬券種 内容
単勝 1 着馬を当てる
馬連 1-2 着の組合せ (順不同) を当てる
ワイド 1-3 着の中から 2 頭の組合せを当てる
三連複 1-3 着の組合せ (順不同) を当てる
三連単 1-3 着の組合せを着順込みで当てる

JRA (中央競馬) は パリミュチュエル方式 で、賭金の総額から控除率 (約 20-30%) を差し引いた残りが配当として分配されます。つまり理論還元率は約 70-80%、機械的に賭けたときの期待 ROI 0.7-0.8 が損益分岐点未満の基準値ROI 1.0 が損益分岐になります。本記事で「ROI 0.99」と書いてあったら「あと一歩で損益分岐」「実質ほぼトントン」という意味です。

既存記事との立ち位置

Calibration × 競馬 ML の文脈では、先行記事として CATA さんの「【ついに完成】競馬AIで本格的に回収率プラスを目指す完全版システム v4.0.0【回収率159.6%】」(note 有料) が LightGBM + Isotonic Regression Calibration で回収率 159.6% を達成しており、近い問題意識で先に動かれているのを最初に書き添えておきます。Calibration を競馬 ML の中心に据えて結果を出されているという意味で、本記事の出発点と問題設定はかなり近いところにあります。

そのうえで本記事は、Isotonic / Platt / Quantile binning / Temperature scaling の 4 手法比較Residual IC を B 差分 / C 直交 / D Per-race / E Incremental の 4 系統に分類して相互チェックLightGBM の暗黙的 Two-Stage 学習仮説を Gain per Depth で構造検証、というところまで踏み込んでみました。「先に到達された方がいる」と認めたうえで、その上で何を新しく加えたのかを宣言しておきたい、という意図です。

モデルバージョン一覧

本記事を通じて v3 から v11 まで複数のモデルが登場します。先に全体マップを置いておきます。主役は v3 を出発点として v11 まで段階的に進化させていく流れです。

バージョン 設計 立ち位置
v3 基本特徴量 + 単勝オッズ・人気を含む 出発点。後に「Echo Chamber 疑惑」が発覚
v6 v3 から単勝・人気を除外 (Fundamental 設計) 既存アンサンブル要員、後に再評価
v8 v6 + adaptive features 既存アンサンブル要員
v3_fundamental v3 から単勝・人気を除外した検証用モデル Phase 1a で「除外だけでは不十分」を実証
v9 v3 + race-level 集約特徴量 5 個 Phase 1c #50。OOH で C 直交 IC +40%
v10 v9 + 体重 ±10kg bin dummies Phase 1c #51。subtle 改善 (Gemini 予想通り)
v11 v10 + 単勝×三連複の市場整合性 5 個 Phase 1c #48。本記事の最終モデル。408 races で ROI 1.66

ゴールの再定義

当初の目標: 単勝・三連複・三連単で ROI > 1.0 を目指す。

しかし運用を重ねるうちに、ゴールを次のように再定義しました。

「儲けではなく、モデルの的中率を最大化する。Bayes error rate (理論的予測上限) を実証的に探る」

ROI は副次的指標で、「どこまで予測できて、どこから先は本質的に読めないノイズか」を見極めるのが本筋です。本記事はこのプロジェクトを進めるなかで、Gemini と議論しながら一気に視界が開けた 2 週間の記録です。


2. 出発点 — 「馬連 ROI 0.99 が最強」という観察

ここでの評価は、モデルが出した上位馬を機械的に買い続けたときのシミュレーション結果です。たとえば「単勝 top1」はモデルの 1 位馬を毎レース単勝で買う、「馬連 top1-top2」はモデルの上位 2 頭を組合せで買う、といったルール。前述のとおりランダムに買って ROI 0.7-0.8 が母集団の平均値、ROI 1.0 が損益分岐です。

336 races の out-of-sample holdout (直近 1 ヶ月のバックテスト期間: 2026-04-01 〜 2026-05-03) で各馬券種を機械的に賭けた結果。

馬券種 hit率 ROI
馬連 top1-top2 19.0% 0.99
三連単 top1→2→3 3.0% 0.87
複勝 box top3 94.9% 0.86
単勝 top1 31.2% 0.79

馬連 (上位 2 頭の組合せ) で還元率 77.5% (= 期待 ROI 0.775) を実質ほぼ相殺。「2 頭の組合せ予測力」がモデルの強みでした。

しかし「単勝 ROI 0.79」と「1 番人気を機械的に買った ROI 0.77」の差はわずか +2 pt。つまりモデル top1 と市場上位はほぼ一致しており、「市場と独立な情報源」を持っていないことが疑われました。

これが Gemini との議論を始めるきっかけになりました。


3. Phase 0: Confidence Calibration の罠

学術的に「正しいやり方」を信じすぎると、計測アーティファクトに騙される。

Gemini が最初に強く推奨したのは Confidence Calibration でした。

「ランキングモデル + softmax は温度調整必須。Isotonic Regression や Platt Scaling で生スコアを真の確率に校正せよ」

これは Cohen et al. (2018) "Calibrating Probabilities for Ranking Models" の議論で、学術的にも妥当な助言です。

実装と結果 (Phase 0)

# calibrate_blend.py の核心部
cal = IsotonicRegression(out_of_bounds="clip", y_min=0.0, y_max=1.0)
cal.fit(y_prob_holdout, y_true_holdout)

k=10 fold CV で out-of-fold predictions を使い、ECE (Expected Calibration Error) と Brier score で評価:

Method ECE Brier
Raw (校正なし) 0.0118 0.0585
Isotonic 0.0039 0.0588 (微悪)
Platt 0.0153 (悪化) 0.0599 (悪化)

ECE 大幅改善で「Isotonic 採用」と結論。本番予測パイプラインに組み込もうとしました。

しかし、Gemini が次に投げた助言が決定打になりました

「等間隔 bin (0.1 刻み) は、競馬のように予測確率が低スコア帯に偏るタスク (クラス不均衡) では高位 bin の分散を爆発させる。Quantile-based binning (各 bin に同数サンプル) がキャリブレーション評価の現代的ベストプラクティス」

各 bin に約 100 サンプル入るよう分位点で切り直して再評価:

手法 Fixed ECE Quantile ECE
Raw 0.0145 0.0120
Isotonic 0.0105 0.0164 (悪化!)
Hybrid (τ + iso) 0.0125 0.0166

結論が完全に逆転。OOH では Raw (校正なし) が最良で、Isotonic は実は失敗していました。

何が起きていたか

Isotonic の reliability curve を quantile binning で見ると、致命的な構造が露呈:

bin 1-3:   pred = 0.0000  (完全に同じ値)
bin 4-13:  pred = 0.003-0.006

低位 bin の約 1,300 サンプルを「pred ≈ 0」に潰している。本来異なる勝率の馬を同じ値に集約することで、等間隔 binning の bin 0.0-0.1 では「いい感じに見える」が、quantile で粒度を上げると真の歪みが露呈します。

教訓 1: 「業界標準の評価指標」を疑わずに採用すると、計測アーティファクトで間違った結論に達する。


4. Temperature Scaling: 仮説と実証の方向逆転

Gemini は次の論点で「lambdarank + softmax の squashing 仮説」を提示しました:

「lambdarank が Top1 とそれ以外のスコア差を強烈に広げる + softmax の winner-takes-all で、中位馬 (pred 24% / actual 30%) の確率が押しつぶされている。τ > 1.0 で確率分布を平坦化すれば中位馬 gap が縮むはず」

実装した temperature scaling experiment:

def softmax_with_temperature(scores, race_ids, tau):
    for rid in np.unique(race_ids):
        s = scores[mask] / tau
        out[mask] = np.exp(s) / np.sum(np.exp(s))
    return out

τ ∈ {0.5, 0.7, 1.0, 1.3, 1.5, 2.0, 2.5, 3.0, 5.0} で実験:

τ 中位馬 gap 判定
0.50 -0.20pt 🟢 改善
0.70 -0.01pt 🟢 完全解消
1.00 (現状) -5.07pt 🔴 (基準)
1.30 -11.76pt 🔴 悪化
2.00 -17.51pt 🔴 大幅悪化

Gemini の予測は方向が逆でした:

  • 予測: τ↑ (softmax を緩める) で中位馬 gap が縮む
  • 実測: τ↓ (softmax を sharper にする) で中位馬 gap が消える

Gemini はこれを受けて、後にイェンセン不等式とアンサンブル平均化による under-confidence の数学的説明を提示しました:

Softmax は凸関数なので「Softmax 出力の平均」は「平均ロジットの Softmax 出力」より常に平坦 (エントロピー高い = under-confident)。5-seed ensemble averaging が under-confidence を数学的に必然化している。

つまり、症状診断は正しい (squashing は実在) が、原因と方向が逆だった。「議論で深まる仮説 → 実装で検証 → 仮説修正」の典型的サイクルです。

教訓 2: AI 助言の症状診断は精度高いが、原因診断は実証で必ず確認する。


5. Residual IC: 「市場と独立な情報源」を定量化する罠

「v3+v6 blend が市場と相関しすぎている」のを定量化するため、Gemini が提案した指標が Residual IC:

$$\text{Residual IC} = \text{Spearman}(\text{model_score}, y - \text{market_probs})$$

「市場の予測で説明できない残差をモデルがどれだけ捉えているか」を測る指標。金融クオンツの世界で「市場ベンチマーク超過」を測る標準的手法です。

実装 (residual_ic.py)

# GAM 相当: Spline + Logistic Regression で
# Logit(Win) ~ s(p_implied) を fit
spline = SplineTransformer(n_knots=7, degree=3, knots="quantile")
lr = LogisticRegression()
lr.fit(spline.fit_transform(p_implied), y_actual)
market_probs = lr.predict_proba(...)

# Residual IC
residual_ic = spearmanr(model_score, y - market_probs)

結果: 異常値が出た

シグナル Residual IC
人気1 **-0.6670 ***
単勝オッズ逆数 **-0.7134 ***
v3+v6 blend **-0.6793 ***

すべて強烈な負の値。何かが致命的に間違っている。

原因分析: binary outcome での Spearman 破綻

  • y ∈ {0, 1}, market_probs ∈ [0, 1]
  • residual = y - market_probs
  • y=0 (大多数、12-18 頭立てで 11-17 頭) + market_probs 高 (人気馬) → residual 大きく負
  • model_score 高 + market_probs 高 (市場と相関) → 上記ペアが多数派
  • 市場と相関するモデルは Spearman ベース Residual IC が機械的に負を取る

Gemini の式は金融の連続 outcome (リターン) 向けで、binary に直接適用できない構造的問題でした。

4 案併記での再実装

binary に適した代替指標 5 つを併記:

バリエーション 定義
A. 素朴版 Spearman(model, y - market) — binary では破綻
B. 差分版 Spearman(model - market, y)
C. 直交化版 Spearman(orthog(model | market), y)
D. Per-race 各レース内 Spearman(model, y) のレース平均
E. Incremental IC IC(model, y) - IC(market, y)

v3+v6 blend の結果 (Holdout)

指標
Simple IC +0.2844
Market IC +0.2931
B 差分 IC -0.1727
C 直交 IC -0.0046
E Incremental -0.0087

v3+v6 blend は市場と独立な情報を持っていない、それどころか僅かに劣ることが定量的に確定。

さらに衝撃: 「人気1 だけ」のほうが blend より独立性が高い

シグナル B 差分 IC C 直交 IC
人気1 (-popularity) +0.2761 +0.0178
v3+v6 blend -0.1727 -0.0046

過去成績・血統・騎手等の特徴量を投入することで、blend は人気だけより市場との相関が高まり、独立性を失った。Gemini はこれを Echo Chamber 現象 と表現しました。要するに モデルが市場予測の完全コピー (こだまの部屋) になってしまい、新しい情報を出していない という意味です。

教訓 3: 「金融由来の指標を binary outcome に適用」は常に罠。複数定式を併記して相互チェックする。

読者ガイド: ここから先で追いかける指標

ここから後の章では Simple IC, B 差分 IC, C 直交 IC, D Per-race IC, E Incremental IC が並んで出てきます。値だけ眺めても判断軸を持てないので、本記事での位置づけを先に固定しておきます。

指標 役割 読み方の目安
Simple IC モデルの生の予測力 高いほどよいが、市場と相関しているだけでも上がる
B 差分 IC モデル - 市場の差分が当たるか プラスなら市場超え、マイナスなら市場以下
C 直交 IC 市場で説明できない残差の予測力 本命指標 (1)。Phase 1 の真の評価軸
D Per-race IC レース内のランキング精度 補助指標
E Incremental IC モデル単独 IC - 市場単独 IC 本命指標 (2)。最も解釈しやすい

本記事で追いかける主指標は C 直交 IC と Incremental IC です。+0.05 以上の改善があれば、ML プロジェクトとしては実務的に有意と考えてよい大きさです。Simple IC は補助的に見るだけで、値が下がっても C/E が改善していれば「市場との独立性が上がった」と判断します。


6. 致命的発見: 特徴量レベルでのリーク

Gemini の次の質問:

「最も市場 (オッズ) に過剰に織り込まれすぎている特徴量はどれか?」

これに実装で答えるべくfeature_market_correlation.py を作成。v3 model の 21 個の数値特徴量それぞれと「単勝オッズの正規化逆数 (p_implied)」の Spearman 相関を per-race で計算:

rank  feature              Pooled IC    Per-race IC
─────────────────────────────────────────────────
  1   単勝                  -0.9999      -1.0000 *** ← オッズそのもの!
  2   人気                  -0.9444      -0.9998 *** ← 人気そのもの!
  3   past5_avg_rank       -0.6677      -0.6898
  4   past10_avg_rank      -0.6535      -0.6813
  ...

v3 model は「単勝オッズ」と「人気」を直接 LightGBM の入力特徴量として学習していました。per-race IC が -1.0000 / -0.9998

ここで言う「リーク」は注意が必要で、ML 一般で言う「未来情報の混入」ではない点を先に確認しておきます。単勝オッズも人気も投票締切時点で確定する事前情報で、時系列的にはリークしていません。問題は別のところにあります。

予測したい対象 (=その馬が勝つかどうか) は、市場が織り込んだ「市場確率」と極めて強い相関を持ちます。その市場確率そのものをほぼ等価に近似する特徴量 (単勝オッズ・人気) を入力にしてしまったため、モデルは「市場予測の写像」を学んでいるだけ、というのが正体です。Gemini はこれを Echo Chamber 型のリーク と表現しました。情報リークではなく、予測対象を強く近似する特徴量によってモデルが市場のこだまになる構造的問題、と読み替えてください。

そしてこの状態を引き起こすメカニズムを Gemini は Feature Overshadowing と説明しました。「他の特徴量の影が薄くなる」現象、というニュアンスです。

「LightGBM は貪欲アルゴリズム。各ノードで最も Loss を下げる特徴量を探す。『単勝オッズ (IC=-1.0) というカンニングペーパー』が存在すると、木の上位ノードは全部オッズで分割される。結果として血統や調教の微妙なアルファを学習するための勾配が消失し、モデルは『オッズの近似関数』に成り下がる」

Phase 1 の核心ミッションが激変:

  • 旧: 「新規シグナルを足して精度向上」
  • 新: 「アーキテクチャを Two-Stage に再構成し、Fundamental と Market を分離」

7. Bill Benter の Two-Stage Architecture

Gemini が次に提示したのは、Hong Kong で 10 億ドル超を稼いだ Bill Benter のモデル設計でした:

Stage 1: Fundamental Model
  └─ オッズ・人気を完全除外して学習
     → モデルは血統・タイム・騎手の複雑な非線形組合せを必死に学習
     → 純粋なアルファが生まれる

Stage 2: Blending Layer
  └─ Logit(Final) = w1 · Logit(Fundamental) + w2 · Logit(Market)
     → 後段でロジスティック回帰で統合

「オッズを捨てる」のではなく、「オッズを木の外に出し、最終段で統合する」。これが Benter が 30 年前から実践していたアーキテクチャです。

v6 が既に Fundamental だった件

実装に取り掛かる前に既存モデルを確認すると、retrain_seeds.py に既に:

"v6_pure_rich": {
    "exclude": {"単勝", "人気"},
    ...
},
"v8_pure": {
    "exclude": {"単勝", "人気"},
    ...
},

v6, v8 は既に Fundamental 設計だった。しかし問題は、v3 + v6 を 50:50 でブレンドしていたため、blend 全体は「半分 Echo Chamber + 半分 Fundamental」状態。これでは Fundamental の効果が薄まる。

v6 単独評価で見えた反証

ところが v6 単独を Residual IC で評価すると、予想外の結果が出ました:

モデル Simple IC B 差分 C 直交 Incremental
v3 (リーク込) +0.2946 -0.0481 -0.0006 +0.0015
v6 (Fund 設計) +0.2504 -0.1928 -0.0125 -0.0426
v3+v6 blend +0.2844 -0.1727 -0.0046 -0.0087

v6 (単勝・人気除外済み) は v3 (リーク込み) より、Residual IC が一貫して劣る。Bill Benter Two-Stage 仮説への重要な反証データです。

仮説:

  • 「単勝・人気を除外」だけでは Fundamental Model にはならない
  • 単に「弱い予測器」になっただけ
  • 真の Fundamental Model 化には 特徴量除外だけでなく、強力な代替特徴量 (interaction, 残差化) が必須

教訓 4: 名著の手法でも、データ・コンテキストが違えば成立しないことがある。実装で検証するまで信じない。


8. Phase 1a 実装と衝撃の反証

ここまでの議論を受けて、Phase 1a として train_fundamental.py を作成:

LEAK_FEATURES = ["単勝", "人気"]
NUMERIC_FEATURES_FUND = [f for f in NUMERIC_FEATURES if f not in LEAK_FEATURES]

# 既存 train.py は変更せず、新規スクリプトで Fundamental 版を学習
# 出力先: models_v3_fundamental/

5-seed ensemble で学習し、Residual IC で評価しました。Gemini の予想と実証データはここで決定的に乖離します

ここから HoldoutOOH の 2 種類の検証集合を併記します。Holdout はチューニング過程で何度も覗いている out-of-sample 期間 (336 races、2026-04-01 〜 2026-05-03)、OOH (Out-of-Holdout) は Holdout より更に時間的に外側に切り分けた、まだ一度も覗いていない 72 races の最終確認集合です。本記事では「Holdout = 開発用 OOS」「OOH = 最終評価用の追加 OOS」と読み替えて差し支えありません。

結果 (Holdout)

モデル Simple IC B 差分 C 直交 Incremental
v3 (リーク込) +0.2946 -0.0481 -0.0006 +0.0015
v6 (Fund 設計) +0.2504 -0.1928 -0.0125 -0.0426
v3_fundamental 🆕 +0.2497 -0.1897 -0.0140 -0.0434

結果 (OOH 72 races)

モデル Simple IC B 差分 C 直交 Incremental
v3 (リーク込) +0.2922 +0.0375 +0.0856 +0.0065
v3_fundamental 🆕 +0.2381 -0.1839 -0.0261 -0.0475

Gemini 予想 vs 実測

指標 Gemini 予想 実測
Simple IC ↓ (覚悟する) ✅ 一致 (0.2946 → 0.2497)
B 差分 IC ↑ プラスに転じる 反証: -0.05 → -0.19 (悪化)
C 直交 IC ↑ プラスに転じる 反証: 0 → -0.01 (悪化)
Incremental IC 反証: +0.0015 → -0.0434

「単勝・人気を除外」しただけでは、Fundamental Model にはならないことが定量的に確定。それどころか v3_fundamental は v6 (既存 Fundamental) と全く同じパターンで劣化しました。

そして最も衝撃的なのは、v3 (リーク込) の OOH 評価:

  • B 差分 IC = +0.0375 (プラス)
  • C 直交 IC = +0.0856 (プラス)
  • Incremental IC = +0.0065 (市場より僅かに強い)

v3 は私が「Echo Chamber に陥っている」と判定したモデルですが、実は 市場と独立な情報源を既に持っていたことになります。

新仮説: LightGBM の暗黙的 Two-Stage

Gemini の Feature Overshadowing 仮説は半分正しく、半分誤りだった可能性が浮上しました:

  • 上位ノード: オッズによる粗い分類 (= Market 成分の取り込み)
  • 下位ノード: 過去成績・血統・騎手等による精緻化 (= Fundamental 成分の取り込み)
  • 結果として木は Market + Fundamental を暗黙的に統合した学習を達成

Bill Benter が線形回帰モデルで Two-Stage Architecture を採用したのは線形モデル時代のベストプラクティスであり、非線形相互作用を自動学習する LightGBM (決定木ベース GBT) には必ずしも適用すべきではないという結論に至りました。

教訓 5: 名著のアーキテクチャは「そのアーキテクチャが使われた時代の技術前提」を理解した上で適用する。GBM と線形回帰では「明示的分離」の必要性が全く違う。


9. Phase 1c の連続実験 — 反証から逆襲へ

Phase 1a の反証を踏まえて、ロードマップを再構成しました。Bill Benter Stage 1 (オッズ除外) は捨て、代わりに 「v3 (リーク込) を基準とし、新規シグナルで Residual IC を伸ばす」 方向に転換。本章は Phase 1c で実施した 5 つの連続実験 (race-level 追加 → Gain per Depth 検証 → 体重 bin → 市場整合性 → 大サンプル検証 → 学術的位置づけ) を、ひとつの章にまとめて追えるようにしたものです。

9.1 race-level 集約 — v9 で C 直交 IC が +40% 改善

最初に取り組んだのは「race-level 集約特徴量」です。

データ制約による方針転換

当初は「逃げ馬頭数」(過去 5 走のコーナー通過順から脚質を分類して集計) を実装する予定でした。しかし features_v8.parquet (v8 が学習に使っている特徴量データセット) を調べると avg_corner_pos_past5 が 2022 年以降全 null であることが判明。

year   non_null_count (件)
2021   ~45,000
2022   0       ← 全部 null
2023   0
2024   0
2025   0
2026   0

Kaggle データセットには 2021 年までコーナー通過順が含まれていましたが、自前で整備したデータセットには含めていませんでした。脚質ベース集計は不可能。

代替案として オッズベース race-level 集約特徴量 5 つを実装:

特徴量 定義
rl_n_horses 出走頭数
rl_top1_odds 1番人気の単勝オッズ
rl_top3_odds_gap 1番人気と3番人気のオッズ差
rl_odds_dispersion オッズ標準偏差
rl_log_odds_entropy インプライド確率のシャノンエントロピー

個別馬の「単勝/人気」とは性質が違い、レース全体の特性を表します。

学習と OOM 復旧

train_v9_race_level.py で v3 と同じ訓練条件 (単勝・人気を維持) + race-level 5 を追加して 5-seed 学習。seed=2024 の途中で OOM クラッシュしましたが、train_v9_single_seed.py で 1-seed 独立プロセス実行に切り替えて復旧。最終的に 5-seed (42, 7, 123, 2024, 999) 全完了。

結果 (OOH 72 races, 本命指標)

モデル Simple IC B 差分 C 直交 Incremental
v3 (基準) +0.2922 +0.0375 +0.0856 +0.0065
v9 race-level +0.2933 +0.0562 +0.1198 +0.0077
改善幅 +0.0011 +0.0187 +0.0342 (+40%) +0.0012

OOH で v9 が v3 を全項目で上回る。特に C 直交 IC が +40% 改善 は、Phase 1 の真の評価軸として定義した「市場で説明されない予測成分の予測力」が大幅に向上したことを意味します。

仮説の決定的実証

Phase 1a と Phase 1c を並べると、Phase 1a の反証時に立てた「LightGBM 暗黙的 Two-Stage」仮説が決定的に支持されます。

モデル設計 C 直交 IC (OOH)
単勝・人気を除外 (v3_fundamental) -0.0261
単勝・人気を残す (v3) +0.0856
+ race-level 特徴量を追加 (v9) +0.1198

「オッズを除去」と「race-level 追加」は方向が真逆:

  • ❌ オッズを除去 → -0.11 pt 悪化
  • ✅ オッズを残しつつ新シグナル追加 → +0.03 pt 改善

LightGBM の木構造は、上位ノードでオッズ + race-level を使って「レース内コンテキスト」を捉え、下位ノードで個別馬の特徴量で精緻化します。Market + Fundamental の暗黙的統合が達成されているわけです。

なぜ race-level が効くのか

仮説。

  • 単勝・人気だけだと「個別馬視点」の粗い分類しかできない
  • race-level 集約を加えることで「レース全体視点」(混戦度・難易度) の分類が可能になる
  • 上位ノードの分類精度が上がる → 下位ノードでの精緻化も効果が増す

これは第 6 章で発見した「単勝・人気は per-race IC -1.0 のリーク」という観察と、矛盾しません。リークではあるが、それを活用する設計次第で有効活用できる、ということ。

教訓 6: 「リーク」と判定された特徴量も、設計次第で活用できる。「除外」が常に正解ではない。決定木の階層構造を活かして「他の特徴量でリークを補強する」発想が筋がよい。

9.2 Gain per Depth 分析 — 仮説が数学的事実に格上げ

次に Gemini から推奨されたのが「Gain per Depth 分析」。LightGBM の trees_to_dataframe() でノード階層ごとに各特徴量の Information Gain を集計しました。

v9 race-level の結果

Depth Market % Fundamental % Categorical %
1 99.22% 0.16% 0.02%
2 97.77% 1.32% 0.83%
3 89.16% 1.41% 9.27%
4 52.48% 2.25% 44.30%
5 21.17% 2.40% 75.16%
6 8.40% 3.12% 86.73%

Gemini の予想 (Depth 1-2 で Market 80%超、Depth 4+ で逆転) が完璧に的中。Depth 1 で 99.22%、Depth 4 で逆転完成。

これは 「LightGBM 暗黙的 Two-Stage」仮説が数学的事実に格上げされた決定的データです。

  • 上位ノード (Depth 1-3): オッズ・人気で「レース内コンテキスト分類」
  • 下位ノード (Depth 5+): 騎手・調教師で「個別馬の精緻化」

Bill Benter Two-Stage が線形モデル時代のハックだった理由が、Gemini が示した理論 (線形では強シグナルが他をゼロに圧縮 / 決定木では条件付き局所分割) で完全に説明されます。

教訓 7: アーキテクチャ仮説は 構造分析 (Gain per Depth) で数学的事実に格上げできる。直感や事後分析 (SHAP) と違って、位相的構造を見れば「どの特徴量がどの depth で効くか」が一目で分かる。

なお、この Gain per Depth 分析は本章のあとで 9.4 の v11 にも再適用 します。「v9 でうまく効いた測定器を、v11 でも同じ物差しで当て直す」という流れになる、と先に頭出しだけしておきます (9.3 の v10 は subtle 改善担当なので Gain per Depth は割愛)。

9.3 v10 = v9 + 体重 ±10kg bin dummies — 期待通りの subtle 改善

v9 と v11 の間に v10 をひとつ挟んでいます。これは Phase 1c #51 として「v9 + 体重 ±10kg bin dummies」を入れただけのモデルで、Gemini との議論でも「ミクロ情報なので subtle にしか効かない」とあらかじめ予想していたものです。

実測でも C 直交 IC で +0.005 程度の薄い改善にとどまり、Phase 1 の本筋ではないため本記事では深追いしません。ここでは「v11 は v10 をベースに作られている」「体重 bin は subtle 改善担当」とだけ押さえてください。

9.4 Phase 1c #48 — 「市場の確信度」を捉える衝撃のシグナル

ここからが本章のクライマックスです。Gemini が本命に挙げていた race-level 時系列。元の提案は「単勝×複勝のインプライド確率乖離」でしたが、私の環境では複勝オッズが取得できていませんでした (odds_clean.parquet には単勝・三連複・三連単のみ)。

なお第 5 章では v3+v6 blend を主対象にしていましたが、Phase 1a の反証以降は v3 単独を基準モデルに据え直しています。9.4 以降の比較表もこの基準に揃え、v3 単独を物差しとして v9 / v10 / v11 を並べていきます。

代替として 「単勝×三連複の整合性」 を実装。

特徴量 定義
rl_trio_overlap 三連複1組合せが単勝上位3頭に含まれる馬数 (0-3)
rl_market_consistency 1番人気馬が三連複1組合せに含まれるか (0/1)
rl_trio_odds_ratio 実三連複1オッズ / 単勝上位3頭からの理論オッズ
rl_trio_top_dispersion 三連複1-3 のオッズ標準偏差
rl_tri_top_dispersion 三連単1-3 のオッズ標準偏差

すべて投票締切時点のオッズから計算可能で、結果情報を含みません。

v11 = v10 + market-cross 5 の結果

Holdout 336 races (Residual IC):

モデル Simple B 差分 C 直交 Incremental
v3 (基準) +0.2946 -0.0481 -0.0006 +0.0015
v9 +0.2948 -0.0438 -0.0010 +0.0018
v10 +0.2948 -0.0391 +0.0054 +0.0017
v11 +0.3426 +0.2167 +0.1977 +0.0496

OOH 72 races (本命指標):

モデル Simple B 差分 C 直交 Incremental
v9 +0.2933 +0.0562 +0.1198 +0.0077
v11 +0.3510 +0.2663 +0.2640 +0.0653

Phase 1 のミッション (B/C/E IC で +0.05 改善) を目標の 5 倍超で達成。

5/9-10 実戦戦績 (4 モデル比較)

シミュレーションの前提条件: 5/9-10 の中央競馬 72 レースで、毎レース以下の 8 戦略を機械的にすべて並行で賭けた場合の集計。1 レースあたりの賭け金合計は 1,300 円 (= 72 R × 1,300 円 = 93,600 円のベット総額)。

戦略 1R あたり賭け金
単勝 top1 100 円
単勝 top1 + top2 (Hybrid) 200 円
馬連 top1-top2 100 円
馬単 top1→top2 100 円
三連複 box (top3 の組合せ 1 点) 100 円
三連単 top1→2→3 100 円
ワイド box (3 ペア) 300 円
複勝 box top3 (3 頭分) 300 円
合計 1,300 円 / R

馬券種別の ROI (= 払戻 / 賭け金) — 過去データバックテスト値:

馬券種 v3 v9 v10 v11
単勝 top1 0.78 0.78 0.84 1.20
馬連 0.90 0.95 0.89 1.47
三連複 box 1.52 1.52 1.52 2.24
ワイド box 1.07 1.07 1.07 1.57
複勝 box top3 0.94 0.94 0.94 1.19 (72/72 = 100% hit)

全戦略合計 (ベット 93,600 円に対する払戻と損益、過去データバックテスト値):

モデル 払戻 ROI 損益
v3 84,720 円 0.91 -8,880 円
v9 88,050 円 0.94 -5,550 円
v11 122,920 円 1.31 +29,320 円 (黒字)

※上表の ROI・損益は過去データに対するバックテスト値であり、将来の利益を保証するものではありません。

リーク疑惑への対応

ROI 1.31 という異常値を見て、即座にリーク検証を実施しました。

Gain per Depth で v11 を分析:

Depth Market % Market-cross % Categorical %
1 98.47% 0.03%
2 91.79% 6.0% 0.37%
3 26.83% 69.9% 2.30%
4 38.08% 54.0% 7.01%
5 18.80% 63.0% 17.10%

Market-cross は Depth 3-6 のスイートスポットで機能。Gemini の予想 (race-level シグナルは Depth 3 で活躍) と完全に一致しました。

rl_market_consistency (1番人気馬が三連複1に含まれるか) が Depth 3-4 で 32-33% のシェアを占め、「鉄板レース vs 波乱レース」の二分類シグナルとして機能していました。

つまり v11 は単に「市場と独立な情報源を獲得」しただけでなく、「読めるレース」と「読めないレース」を選別する能力を獲得していたのです。これは Bill Benter が常々言っていた「期待値プラスのレースのみ参加」戦略と本質的に同じ。

教訓 8: 異常な数値が出たら即リーク疑惑を持つべきだが、事前情報のみで構成されていることと Gain per Depth で構造が妥当であることを確認すれば、それは本物の発見である。

9.5 最終検証 — 408 races で v11 の本物性が確定

ここで Gemini から最優先と指示されたのが Longer OOH。Holdout 336 races + OOH 72 races = 408 races で v11 の全戦略 ROI と Skip 戦略最適化を同時評価しました。

結果 (threshold=0、素朴 v11、408 races)

シミュレーション前提: 5/9-10 のときと同じ 8 戦略を、毎レース機械的に並行で賭けるシミュレーション。1 R あたりベット 1,300 円 (単勝 top1 100 / 単勝 top1+2 200 / 馬連 100 / 馬単 100 / 三連複 box 100 / 三連単 100 / ワイド box 300 / 複勝 box top3 300) × 408 R = 総ベット 530,400 円

馬券種別 ROI (= 払戻 / 賭け金) — 過去データバックテスト値:

馬券種 ROI
単勝 top1 1.189
単勝 top1+2 1.207
馬連 2.033
三連複 box 3.841 ⭐⭐⭐
ワイド 1.741
複勝 box 1.178
全戦略合計 1.6577

総ベット 530,400 円に対する払戻 約 825,560 円損益 +295,160 円 (黒字)

※上記の ROI・損益は過去データに対するバックテスト値であり、将来の利益を保証するものではありません。

サンプル数別 ROI 比較

サンプル 期間 全戦略 ROI
5/9-10 72 races 1.31
Holdout + OOH 408 races 1.66

サンプル数を 5.6 倍に増やすと ROI がさらに +0.35 向上。これは「v11 が真の statistical edge を持つ」ことの決定的証拠です。Gemini が懸念していた「特定週末の上振れ」は完全に否定。

寄与分解 — ROI 0.91 → 1.66 の正体

「ROI が 0.91 から 1.66 まで跳ねたのは単に運がよかっただけでは?」という疑念に先回りしておきます。5/9-10 (72 races) の実測 ROI と OOH C 直交 IC を、ステップごとに並べ直すと次のようになります。

ステップ 主要変更 C 直交 IC (OOH 72R) 5/9-10 全戦略 ROI 役割
v3 (出発点) 基本特徴量 (単勝・人気込み) +0.086 0.91 出発点
Phase 0 Calibration Quantile binning + Raw 採用 (τ=0.70) (同 v3) (同 v3) Kelly 計算精度 / 評価軸整備
+ v9 (race-level) 出走頭数 / 1番人気オッズ など 5 個 +0.120 (+40%) 0.94 緩やかな底上げ
+ v10 (体重 ±10kg bin) 体重 dummies 5 個 +0.116 (subtle) (中間) 微改善 (Gemini 予想通り)
+ v11 (market-cross) 単勝×三連複の整合性 5 個 +0.264 (+120%) 1.31 本丸
同じ v11 を大サンプルで再評価 408 races (5.6 倍) に拡張 (同上) 1.66 ⭐⭐ 真のエッジが浮上

ここから読み取れることはシンプルで、

  • ROI 0.91 → 1.31 (5/9-10) のジャンプの大半は v11 の市場整合性特徴量が運んでいる (v9 単独では +0.03 程度)
  • 1.31 → 1.66 (5.6 倍サンプル) のジャンプは「v11 のエッジが小サンプルで埋もれていた分が浮上した」結果で、新たな仕掛けが乗ったわけではない
  • Phase 0 の Calibration 自体は ROI を直接押し上げない — ECE 罠の回避と評価軸整備、そして後の Kelly ステーキングの精度に効いていた

つまり ROI 0.91 → 1.66 は「Calibration 整備で計測器を作り、race-level (v9) で土台を整え、市場整合性 (v11) で本丸を取り、大サンプルで実体が浮上した」4 段ロケットの累積であり、特定週末の上振れではない、というのが Gain per Depth (9.4) と Longer OOH (本節) の両方で同時に確認された結論です。

Skip 戦略最適化

「v11 が確信度の低いレースを skip する」戦略を加えた場合、参加レース数が減るぶんベット総額も減ります。threshold を top1_prob >= X で動かしたシミュレーション (1 R あたり 1,300 円ベース、過去データバックテスト値):

threshold (top1_prob) 参加 / 全 ROI 損益
0.00 408/408 (全参加) 1.6577 +295,160
0.15 398/408 1.6789 +297,230 (損益最大)
0.20 359/408 1.7052 +278,490 (ROI 最大)
0.40 263/408 1.5672 +164,100

※上表の ROI・損益は過去データに対するバックテスト値であり、将来の利益を保証するものではありません。

ROI 最大は threshold 0.20 (素朴 v11 比 +0.05)、損益最大は素朴 v11 + 微 skip (threshold 0.15)

Gemini ウィジェットの「skip しすぎは逆効果」仮説が実測で完全実証されました。

教訓 9: 大サンプル検証 (Longer OOH) は ML プロジェクトの最重要検証。72 races では「ラッキー or 本物」を区別できないが、408 races まで増やすと差が一目瞭然になる。サンプル数を増やせる検証を後回しにしてはいけない

9.6 Green Light — Gemini からの本番投入許可と学術的位置づけ

408 races の結果を見せたところで、Gemini はこう判定しました。

Green Light、即時投入可。400 レース超の OOH で ROI 向上したことは、モデルがオーバーフィッティングではなく汎化された真の市場の歪みを捉えている揺るぎない証拠。これ以上のオフライン検証は Analysis Paralysis に陥るだけ」

そして三連複 box ROI 3.84 の構造解釈について議論する中で、Gemini はこの発見に学術的な名前を与えてくれました。

"Heteroscedastic Top-K Identification" — 発見の学術的位置づけ

用語ボックス: Plackett-Luce モデルと Heteroscedastic Top-K

Plackett-Luce モデル: ランキングを確率モデルとして扱う古典的定式。各馬に潜在スコアを与え、「1 着は全頭の中から確率比に従って選ばれる → 2 着は残った頭の中から選ばれる」と逐次的に同時確率を組み立てる。三連複・三連単の理論確率を考えるときの教科書的な基盤。

Heteroscedasticity (不等分散性): 観測の分散がサンプルごとに異なる性質。「読めるレース」(分散が小さい = 鉄板) と「読めないレース」(分散が大きい = 波乱) が混在しているのが、まさにこの状態。

Heteroscedastic Top-K Identification: 分散の小さい「読めるレース」を見極めて、そこでだけ Top-K (上位 K 頭) を当てに行く戦略。市場は単勝確率中心で動くため、三連複のような同時確率では「読めるレースで同時確率が単勝の積から非線形に跳ね上がる」歪みが残りやすい、というのが Gemini の整理。

  • 大衆は単勝確率 (限界確率) を中心に思考する
  • 三連複の同時確率は、大衆の脳内では「単勝人気の掛け合わせで大雑把に形成」される
  • v11 は「ノイズが少ないレース (Heteroscedasticity 低)」で 同時確率が単勝の積から非線形に跳ね上がる点をピンポイントで識別
  • これは Plackett-Luce モデルの同時確率に対する市場評価の歪みとして理論化可能

つまり私が偶然発見した「市場の確信度シグナル」は、学術的に既知の構造だったわけです。Bill Benter が線形時代に手探りで掘り当てたエッジを、決定木ベース GBT で「市場の確信度 × 暗黙的 Two-Stage」によって自動学習できた、というのが Phase 1 の結論です。

教訓 10: ML プロジェクトで「異常に良い結果」が出たら、まずはリーク検証 (Gain per Depth + 大サンプル) で本物確認。そして本物だった場合、その現象の学術的名前を探すこと。多くの場合、似た構造の研究が既にある。


10. メタな学び 5 つ

このプロジェクトで得た普遍的な教訓。

教訓 A: 「業界標準の評価指標」を疑え

等間隔 ECE → Quantile ECE の切り替えで、結論が完全に逆転。「正しいやり方」を信じすぎると計測アーティファクトで間違える。最低 2 つの定式で相互チェックするのが安全。

教訓 B: AI 助言は症状診断と原因診断を分けて受け取る

Gemini の症状診断 (Echo Chamber, squashing, リーク疑い) は精度極めて高い。しかし原因診断 (τ 方向, Fundamental Model 化、Two-Stage 採用) は実証で必ず確認する。「Gemini が言ったから」では実装してはいけない

教訓 C: 計測器を先、武器を後

Phase 2 #55 (Residual IC) を Phase 1 (新シグナル) より先に整備したことで、「新シグナルが本当に市場と独立な情報を捉えているか」が定量化できる状態になった。Silent Failure を防ぐのはまず計測。

教訓 D: 「議論を太らせない」

Gemini との議論は知見が深まるが、実装で確かめないと地に足つかない。「議論ばかり太らせるな」というのは個人開発で何度も自分に言い聞かせてきた戒めで、議論 → 実装 → 結果報告 → 次の議論のサイクルが最も生産的。

教訓 E: 名著のアーキテクチャは「時代の技術前提」を理解した上で適用する

Bill Benter Two-Stage は線形回帰時代の遺物だった可能性がある。LightGBM のような非線形 GBT は、明示的分離をせずとも木構造で暗黙的に統合できる。「成功事例の方法論」をそのまま転用すると逆効果になる場面がある。



11. Phase 1 完了 — 達成のすべて

Phase 1 の全タスクを完了しました。

Phase Status 主要結果
Phase 0 (Calibration) ✅ 完了 等間隔 ECE 罠を回避、Raw + τ=0.70 採用
Phase 1a (Fundamental 化) ❌ 反証 取り下げ → LightGBM 暗黙的 Two-Stage 仮説誕生
Phase 1c #50 (race-level) ✅ 成功 v9 が OOH C 直交 +40%
Phase 1c #51 (体重非線形) ✅ 完了 v10、subtle 改善 (Gemini 予想通り「ミクロ情報」)
Phase 1c #48 (market-cross) 大成功 v11 が ROI 1.31、C 直交 +120%
Phase 2 #55 (Residual IC) ✅ 完了 4 案併記 (B 差分 / C 直交 / D Per-race / E Incremental)
Gain per Depth 分析 ✅ 完了 仮説が数学的事実に格上げ

最終達成

指標 開始 (v3) 終了 (v11) 改善幅
Simple IC (OOH) +0.292 +0.351 +0.059
B 差分 IC (OOH) +0.038 +0.266 +0.228 (7倍)
C 直交 IC (OOH) +0.086 +0.264 +0.178 (3倍)
Incremental IC (OOH) +0.007 +0.065 +0.058 (9倍)
5/9-10 全戦略 ROI (※1) 0.91 1.31 +0.40
408 races 全戦略 ROI (※1) 1.66 (大サンプル確定)
408 races 損益 (※1) +295,160 円 threshold 0 で +295,160 / threshold 0.15 で +297,230 (損益最大) / threshold 0.20 で +278,490 (ROI 最大)

(※1) ROI / 損益はいずれも「1 R あたり 8 戦略を機械的に並行ベット (合計 1,300 円/R)」の過去データバックテスト値。5/9-10 は 72 R × 1,300 円 = 93,600 円ベット、408 races は 530,400 円ベットが前提。将来の利益を保証するものではありません

Bayes error rate の物差し

戦略分析で「Bayes error 探索」のゴールを設定したとき、v3 top1 31% から現実上限 38-42% まで +7-11pp の伸びしろを想定していました。v11 では以下の通り。

  • 単勝 top1 hit 率: 29.2% → 40.3% (5/9-10 で 29/72) +11pp
  • C 直交 IC: 0.086 → 0.264 市場との独立性 3 倍

つまり Bayes error の壁を、特徴量空間の拡張で実際に動かした ことになります。「Bayes error は動く標的」という戦略メモのメタ視点が、Phase 1c で 物理的に実証 されました。

「市場の確信度」という発見

最大の知見は 「市場の確信度を測れば、レース難易度を予測できる」 ということ。rl_market_consistency (1番人気が三連複1に含まれるか) のような単純な特徴量が、Depth 3-4 で 30%+ のシェアを取って「鉄板 vs 波乱」の二分類を実現していました。

これは Bill Benter が常々言っていた「期待値プラスのレースのみ参加」戦略を、機械学習で実装した形になります。アンサンブルを少しずつ調整しても上がり切らなかった ROI が、特徴量設計の方針転換ひとつでこの短期間でここまで動いたのは、率直に言って自分でも信じきれていません。


12. これから — Phase 3 リアルタイム通知パイプライン

Gemini からの Green Light を受けて、次は本番投入フェーズです。投票は手動で行う前提なので、パイプラインの責務は 「直前情報取得 → 推論 → 通知」まで に限定します。

: IPAT 規約に従い、投票は必ず人間が手動で行います。本パイプラインは通知までで、自動投票は実装しません。

12.1 運用面の最大ハードル — 「直前オッズの確定タイミング」

本番投入を考えた瞬間、Gemini が「ROI 1.66 を本番で使う際の隠れたリスク」として挙げたのが次の 2 点です。

  1. Market Impact — 大口ベットになると自分の投票で直前オッズが動く (スリッページ)
  2. Execution Latency — 直前オッズ取得 → 推論 → 投票のパイプライン堅牢性

投票は手動で行うため、Execution Latency の本質は 「いつのオッズを使うか」のタイムライン管理 に変わります。

用語ボックス: IPAT / ofelia / PSI / Half Kelly

  • IPAT: JRA 公式のインターネット投票システム。本記事の「人手投票」は IPAT のことを指す
  • ofelia: Docker 環境向けの cron 風ジョブスケジューラ。RasPi 5 上で推論ジョブを定刻起動するために使う
  • PSI (Population Stability Index): 学習時と推論時の特徴量分布の差を測る指標。本番運用後にドリフト検出に使う
  • Half Kelly (Fractional Kelly): 資金管理の最適化式。後述 12.6 で詳説

想定タイムライン (発走 13:50 のレース、第一案)

13:50:00     発走
13:49:30     IPAT 投票締切 (推定)
13:48:00     人手投票開始のデッドライン (90 秒で操作)
13:47:30     Discord 通知到達
13:47:00     v11 推論完了 + 通知発射
13:46:00     features_v11 計算開始 (race-level 集約)
13:45:00     直前オッズ取得 (外部データソース)
13:45:00     ← トリガー (発走 5 分前)

「発走 5 分前」がベスト・ウィンドウだろうとここでは仮置きしました。それより早いと確定オッズと乖離し、それより遅いと人手投票が間に合わない。

顕在化するリスク

リスク 対応
外部データソースの不安定性 リトライロジック + フォールバック (前日オッズ)
複数レース同時発走 G1 開催日は複数 jobs 並列起動
オッズ確定タイミングの曖昧さ 最終 1-2 分の大口投票で rl_market_consistency が反転する可能性

12.2 段階的実装プラン

Phase 内容 目的
Phase 3a (即時) リアルタイム通知 (predict_realtime.py) 発走 5 分前に v11 推論 → Discord 通知
Phase 3b (運用後 1 週間) 直前オッズ統合 (odds_snapshot.py 拡張) features_v11 を on-the-fly 計算
Phase 3c (運用後 1 ヶ月) MLOps インフラ ロギング・ダッシュボード・PSI ドリフト検出

12.3 Dual Trigger によるタイムライン再設計

12.1 の T-5 単一トリガー案について、Gemini から「単一の T-5 トリガーは Late Money Effect でフェイクシグナルリスク」と指摘が入りました。

Thaler & Ziemba (1988) 以降の研究で、「発走 5 分前のオッズ」より「最終確定オッズ」の方が情報効率性が圧倒的に高いことが実証されている。Smart Money (大口投資家) はギリギリまで投票を遅らせるため、最後の 5 分間に売上の 30-40% が集中する。

これを受けて、Dual Trigger (T-5 + T-2) を採用しました。

13:50:00     発走
13:49:30     IPAT 投票締切
13:48:30     [Final] Discord 通知到達
13:48:00     v11 推論 (T-2、最新オッズで再計算)
13:48:00     ← T-2 トリガー (発走 2 分前、Final)
13:48:00     人間: IPAT で 1 タップ投票完了
   ↑ (T-5 通知を見て事前に IPAT ログイン + 馬番入力済み)
13:46:00     [Draft] Discord 通知到達
13:45:30     v11 推論 (T-5、予備)
13:45:00     features_v11 計算
13:45:00     ← T-5 トリガー (発走 5 分前、Early Warning)

T-5 と T-2 で top1/top2/top3 が変わる可能性があります。これは「Late Money で投票分布が変わった = Heteroscedasticity 評価が更新された」ことの正しい反映。

12.4 Action-Oriented 通知設計

通知文面についても Gemini からはっきりとした注文が入りました。

投票する人間感情を排除した API のインターフェース として機能しなければならない。発走 2 分前の極限状態で、認知的負荷を 1 ビットでも残してはいけない」

理想テンプレート。

🚨 [FINAL GO] 中山11R (発走 15:40)
━━━━━━━━━━━━━━━━━━━━
【指示】以下をそのまま購入してください
✅ 三連複 BOX (10点) : 3, 5, 8, 11, 14
✅ 馬連 : 5 - 8

【資金管理: Half Kelly】
💰 総投資額: 1,300円 (全2券種)

【モデル確信度】
🎯 確信度スコア: HIGH (Top1 Prob: 0.32 > 閾値 0.20)
📊 期待値(EV): 1.85
━━━━━━━━━━━━━━━━━━━━

Skip レースの場合: 馬番を一切出さず巨大文字で 🛑 [SKIP] 期待値未達 のみ (FOMO 防止)。

12.5 RasPi 5 運用ポリシー

観点 ポリシー
メモリ LightGBM v11 (5-seed) ≈ 18MB、推論時 ~500MB-1GB → RasPi 5 8GB で余裕
API リトライ 外部データソース: 指数 backoff 3 回 (1秒, 2秒, 4秒)、timeout 10 秒
フォールバック 失敗時は前回 snapshot のオッズで推論、STALE フラグ付き通知
完全障害時 [ABORT] 外部データソース通信失敗、手動判断推奨 を通知 (自動投票しない原則)
ロギング JSON Lines: /logs/realtime/YYYYMMDD/race_<rid>_t5/t2.jsonl
再起動耐性 ofelia 各 job 独立プロセス、状態は file system 保存

12.6 資金管理: Half Kelly を運用初期の標準に

用語ボックス: Kelly 基準 (Fractional Kelly / Half Kelly)

ある賭けの期待値とエッジの大きさから、資金の何%を 1 ベットに投じれば長期的な対数成長率が最大化されるか を導く資金管理の最適化式。フルに従う「Full Kelly」は理論最大成長率を実現する代わりにドローダウン (一時的な減価) が極端に大きいため、実務では一定比率に縮める「Fractional Kelly」が標準。「Full Kelly の半分」が Half Kellyで、心理的に持続可能なドローダウンに抑える定番の縮減倍率。

Gemini のシミュレーター画像で示された数値を採用します。

  • フルケリー: 14.4%
  • Half Kelly: 7.2% ← 採用 (最大ドローダウン 80% を抑制)

「ROI 1.66 だから Full Kelly でも破滅しない」のは数学的真実ですが、心理的に持続可能なドローダウンを優先しました。これも Bill Benter が常々言っていた「破滅したらゲーム終了、生き残るのが先決」の精神に沿っています。

12.7 残った仕事

  • 議論したかったが時間切れだった話: Multi-task Learning (ペース・馬群長予測の補助タスク化), Set Transformer による馬間相互作用, GNN ベースのレース構造モデル
  • これらは Phase 4 として、Phase 3 の運用データが溜まってから検討する予定です

免責事項

  • 本記事は著者個人の ML モデル開発の試行錯誤の記録であり、馬券購入の推奨・助言ではありません
  • 本記事は投資助言・賭博助言・利益保証のいずれにも該当しません
  • 記事中の ROI・損益はすべて過去データに対するバックテスト値であり、将来の利益を保証するものではありません
  • 馬券購入は自己責任で、20 歳未満の方は購入できません (競馬法)
  • 著者は本記事の情報に基づく一切の損失について責任を負いません
  • 本記事中で言及する外部データソース・サービスは特定の事業者を推奨するものではありません

13. 終わりに

26 ラウンドの Gemini 議論を通じて、ML モデルが「市場のクローン」(Echo Chamber) から「読めるレースを高確率で的中させる Bill Benter 型クオンツ運用スタイル」へ進化しました。

Plackett-Luce の同時確率、Heteroscedasticity の学習、LightGBM 暗黙的 Two-Stage、Quantile binning の罠、Residual IC の binary 破綻、Feature Overshadowing — どれも私のエンジニアリング観を一段引き上げてくれた概念です。

AI と議論しながら ML モデルを育てる体験は、想像以上に楽しいものでした。仮説が反証される瞬間反証の真逆で実証される瞬間異常値がリーク疑いを超えて本物だと確認できた瞬間 — それぞれが深い学びでした。とくに Phase 1a で「Bill Benter のアーキテクチャを移植すれば勝てる」という直感が真っ向から否定されたときには、正直しばらく画面の前で固まりました。自分の中の「権威」が崩れる瞬間に、データに殴られる体験ほど効くものはない、と改めて思います。

これから Phase 3a の実装に着手します。実運用データが溜まったら、また Gemini と議論しながら次のフェーズへ。


付録 A. Coral USB Accelerator は買うべきか? — ハードウェア投資の判断記録

ここからは本論を外れた寄り道として、Phase 3 の準備中に実際に検討した「ハードウェア投資」の判断記録を残しておきます。本筋からは独立した話題ですが、ML プロジェクトで誰もが一度は通る「TPU/GPU 買おうかな」問題への参考として。

実装が一段落して raspi5 で v11 が動き始めた頃、ふと「ハードウェア追加投資で更に伸ばせるのでは?」という気持ちが生まれます。Google の Coral USB Accelerator (Edge TPU) は約 5-8 千円、v11 の 1 日の想定損益 (+29,000 円) で 1 日で回収可能。これを買うべきか Gemini に問い合わせました。

Gemini の判断: Wait (画像処理に本格着手しない限り Skip)

核心ロジックは アムダールの法則 (Amdahl's Law):

「predict_realtime.py の 30 秒のうち推論本体は 5 秒。Coral で推論を 0.1 秒に高速化しても全体は 30 → 25.1 秒。T-5 制約内の運用にいかなる優位性も生まない

つまりボトルネックが推論ではなく I/O と特徴量生成にあるため、推論アクセラレータは無意味、という極めて明快な分析。

各シナリオの判断 (Gemini 提示)

シナリオ 判断 根拠
LightGBM → NN 蒸留 ❌ やるな 量子化で C 直交 IC +0.264 が確実に鈍る (Grinsztajn et al., 2022: テーブルデータで決定木が NN を凌駕)
Phase 4 (Set Transformer / GNN) ❌ Coral 不要 raspi5 CPU で数 ms〜数十 ms (43 features × 18 頭の FLOPs は極小)
Edge TPU Compiler の罠 ⚠️ 警戒 Attention / GNN の動的グラフはサポート外、CPU フォールバック多発
パドック動画 CV 解析 唯一の Coral 必須シナリオ 過去データと完全に直交する究極の Fundamental シグナル
直前オッズ時系列 / NLP ❌ Coral 不要 系列長・語彙が小さく CPU で十分

判断軸

「そのデバイスはシステムのボトルネックを解消するか?」

Gemini の言葉:

現在のボトルネックは計算資源 (FLOPs) ではなく、特徴量設計資金管理・運用8,000 円より エンジニアの工数 (時間) のほうが価値が高い

おまけ提案 — FastAPI 推論サーバー化

「predict_realtime.py の 30 秒のうち、uv run 起動 + features ロードの 15 秒は、FastAPI 推論サーバーを常駐 daemon として立ち上げることでほぼゼロに削減できる (コールドスタートの排除)」

これは Coral よりも実装価値が高いソフトウェア最適化。1 リクエスト 30 秒 → 1-2 秒に圧縮可能。将来の課題として記録。

教訓 11: ハードウェア投資 (5,000-8,000 円) を検討する前に、ボトルネックがどこにあるかを冷静に分析する。たいていの場合、お金よりエンジニアの工数 = 時間のほうが希少リソース。アムダールの法則を常に意識する。


付録 B. 参考文献

  • Cohen et al. (2018) "Calibrating Probabilities for Ranking Models"
  • Guo et al. (2017) "On Calibration of Modern Neural Networks"
  • Rahaman & Thiery (2020) "Uncertainty Quantification and Deep Ensembles"
  • Bill Benter (1994) "Computer Based Horse Race Handicapping and Wagering Systems"
  • Thaler & Ziemba (1988) "Anomalies: Parimutuel Betting Markets"
  • Michael Mauboussin "The Success Equation: Untangling Skill and Luck"
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?