はじめに
初めてQiitaの記事を書きます!
yoshiasaと申します(__)
プロフィール
- メーカー勤めの現在社会人3年目
- 理系大学院卒
- 専門はIC設計、大学時代の研究内容は量子コンピュータや最適化
この記事のモチベーション
この記事では社会人、というか現代人に必須のスキルとなってきている「生成AI×プログラミング」のスキルを身に着けるため、「ChatGPTと作る競馬予想AI」と題して、制作過程を書き残していきます。
プログラミングも生成AIもほぼ初心者ですが、この企画を通してこれらの知識が身についていくかも注目してくれると嬉しいです。
この記事の概要
第一回となるこの記事では、今回の企画の方向性について話していきます。
したがって、なんと今回はプログラムは出てきませんが、次回からはバリバリ書いていきますのでご容赦くださいm(__)m
前提・方向性
どういう環境でやっていくの?
機械学習のモデルも充実しており、生成AIと相性が良いといわれているPythonを用いてプログラミングを行っていきます。
肝心の生成AIは各モデルのPro/Conを掴めていないため、とりあえずはChatGPTを使っていきます。
- Language: Python 3.13
- Editor: Visual Studio Code 1.103
- Generative AI: ChatGPT GPT5
ちなみにPCスペックは以下の通り - CPU: Intel Core i5-12400F
- Memory: 32GB
- GPU: AMD Radeon RX6600 8GB
慣れてきたらClaudeなどの生成AIやCursorといったツールも試していきたいですね。
どんなモデルで何を予測するか
競馬予測といっても競馬の何を予測しよう…競馬は買い方の選択肢が豊富でこの時点で方向性に悩んでしまいます。
せっかくなのでこれもChatGPTに聞いてみましょう。
プロンプト
あなたはデータサイエンスに詳しいプログラマです。 Pythonで回収率が高い競馬予想AIを作成しようと考えています。 まずは以下の問いに答えてください 1. 予測する目的変数はどんなものがあり、どれが最も予測しやすいか 2. その目的変数を予測するにはどんなAIモデルが適しており、そのAIモデルはPythonのモジュールとして存在するか生成AIには事前にペルソナ(Chat内における生成AIの仮定・前提知識)を設定してあげると良いというのを聞いたことがあります。
さらに提示された予測対象(目的変数)に適した予測モデルも聞いちゃいましょう。
(使用回数をなるべく減らすため)
回答
いいですね!「回収率が高い競馬予想AI」を作るにあたって、まず整理してみましょう。1. 予測する目的変数の候補
競馬データから予測できる目的変数はいくつかあります。
-
順位 (着順)
- 1着~n着を直接予測。
- ただしクラス数が多く、ノイズも大きいので難易度高め。
-
連対/入着の有無 (分類問題)
- 例:馬が3着以内に入るか(Yes/No)。
- バイナリ分類になるため扱いやすい。
-
単勝・複勝の的中確率(確率予測)
- 各馬が勝つ確率、3着以内に入る確率を予測。
- オッズと組み合わせて期待値計算 → 回収率改善に直結。
- 実務的には最も利用価値が高い。
-
馬券の期待値(回収率)
- 「この馬券を買うと期待値が何%か」を予測。
- 本質的には確率予測モデルを使って算出することが多い。
👉 最も予測しやすく、かつ実用的なのは「各馬の複勝確率(3着以内に入る確率)」です。
なぜならクラス不均衡が少なく、順位予測より安定して学習でき、さらに複勝オッズを使って期待値ベット戦略を組みやすいからです。
2. 適したAIモデルとPython実装
モデルの候補
-
ロジスティック回帰
- シンプルな分類モデル。まずのベースラインに最適。
-
ランダムフォレスト / 勾配ブースティング (LightGBM, XGBoost, CatBoost)
- 表形式データに強く、特徴量重要度も見える。
- 馬場状態や騎手データなど、カテゴリ×数値混在データに最適。
- 実際の競馬予想AI研究でもよく使われる。
-
ニューラルネット (PyTorch / TensorFlow)
- 時系列特徴(ラップタイムなど)を扱う場合に有効。
- ただし構築とチューニングが難しく、データ量が必要。
Pythonで使えるモジュール
- scikit-learn(ロジスティック回帰・ランダムフォレストなど)
-
XGBoost(
xgboost) -
LightGBM(
lightgbm) -
CatBoost(
catboost、カテゴリ変数をそのまま扱える) - PyTorch / TensorFlow(ディープラーニング用)
👉 最初は LightGBM or XGBoostで複勝確率を予測 → 期待値ベースで馬券シミュレーション → 回収率を確認するのが現実的です。
もしよければ次のステップとして、
- 「どのデータが手元にあるか(レース結果・出走表・オッズなど)」
- 「どの馬券種で回収率を目指すか(単勝・複勝・ワイド・三連単 etc.)」
を教えていただければ、具体的なデータ加工やモデル設計の流れを提案できます。
👉 まずは単勝・複勝の確率予測をやってみたいですか? それとも最初から三連単など複雑な馬券を狙いたいですか?
またAIモデルとしては、LightGBMといった決定木アルゴリズムを勧められました。
他の競馬予想AIでもこのモデルを使ってかなりの回収率をだしていたのでとりあえずは間違いないでしょう。
そして最後に狙う馬券は何が良いか聞いてきました。
おすすめは複勝なのでしょうが、あくまで最終的な決定権は人間様に委ねてくれるらしいです。
とりあえずおすすめの単勝・複勝で予測を行い、またそのために必要な特徴量を聞いてみます。
どんな特徴量が必要か
早速ChatGPTに聞いてみます。
プロンプト
まずは単勝・複勝の確率予測をやってみたいです! 必要な特徴量を教えて回答
いいですね! 「単勝・複勝の確率予測」をやるなら、まずはどんな特徴量(説明変数)を入力として使うかを整理しましょう。特徴量の大分類
競馬予測では、ざっくり以下の種類の特徴量を組み合わせるのが基本です:
-
馬の能力・戦績に関する特徴量
- 過去の勝率・連対率・複勝率(全体/距離別/コース別)
- 過去レースの着順(直近○走の平均着順など)
- タイム指数(スピード指標、調整が必要)
- 上がり3ハロン順位(末脚力)
- 斤量(斤量が増減したときのパフォーマンス)
-
馬場・コース適性
- 芝/ダート成績
- 距離成績(短距離/中距離/長距離)
- コース成績(右回り・左回り)
- 馬場状態(良/稍重/重/不良)での得意不得意
-
騎手・調教師の特徴
- 騎手の勝率・連対率・複勝率
- 騎手×馬の相性(騎乗成績)
- 調教師の勝率・連対率・複勝率
-
レース当日の条件
- 枠順(内枠・外枠有利不利)
- 発走場の天気・馬場状態
- 出走頭数(多頭数レースは荒れやすい)
-
オッズ情報
- 単勝オッズ、複勝オッズ(人気)
- 前日オッズの変化(投票動向)
- ブックメーカー式なら implied probability との差分
-
ラップ・ペース予想(高度な特徴量)
- 各馬の過去の通過順位(逃げ・先行・差し・追込)
- 予想される展開(ハイペース/スローペース)
初期段階で使いやすい特徴量(おすすめ)
まずはシンプルに以下を揃えると良いです:
- 馬の過去3走以内の平均着順・最高着順
- 馬の過去3走以内の複勝率
- 距離別の成績(例:1600mでの勝率/複勝率)
- 騎手の直近勝率・複勝率
- 枠順(ワンホットエンコードでOK)
- 単勝オッズ(ベースラインとして強い)
👉 最初は「過去成績 + 騎手 + オッズ」で十分強いモデルが作れます。
👉 慣れてきたら「ラップ情報」「調教師成績」「馬場適性」などを追加すると精度が上がりやすいです。
Pythonでの実装イメージ
特徴量は Pandas でまとめて DataFrame にして、LightGBM / XGBoost に渡せます。
import pandas as pd
# 仮の特徴量例
df = pd.DataFrame({
"avg_rank_last3": [4.3, 2.0, 7.1], # 直近3走の平均着順
"place_rate_last3": [0.33, 0.67, 0.0], # 直近3走の複勝率
"distance_win_rate": [0.15, 0.25, 0.05], # 距離別勝率
"jockey_place_rate": [0.25, 0.30, 0.10], # 騎手複勝率
"draw": [3, 8, 1], # 枠順
"odds": [4.5, 2.8, 30.0], # 単勝オッズ
"target": [1, 1, 0] # 複勝的中フラグ (教師データ)
})
ここで質問です:
手元にあるデータは JRA-VANデータベースのような詳細情報でしょうか? それとも netkeibaのレース結果や出走表をスクレイピングしたデータのようなものですか?
👉 それによって「使える特徴量の範囲」と「前処理の難易度」がかなり変わってきます。
色々出してくれましたが、普段から競馬をやるわけでもないため何を言っているかよくわかりません…
しかしChatGPT君、そんなアホな人間に対しても丁寧に「初期段階で使いやすい特徴量」を教えてくれます。
確認すると、まずは以下を揃えていけば良さそうです。
- 馬の過去3年の成績(距離別)
- 騎手の過去3年の成績
- 成績に対するオッズ
特徴量は聞いといてなんですけど、やっていきながら徐々に適切なものを増やしていき、精度を上げていきましょう。
そしていよいよ実際に使うデータを集めるスクレイピングに踏み込んできました。
少しずつ軌道に乗っていく感じが楽しいですね(まだプログラミングしてないけど)。
それでは次回はスクレイピング編をお届けします。