AIの作り方③競馬AI予測モデルの構築ガイド!初めてのモデル作成

AIの作り方

AIの作り方③競馬AI予測モデルの構築ガイド!初めてのモデル作成

前回の記事「AIの作り方②データは宝の山!競馬AI予測に必要なデータ前処理・特徴エンジニアリング」では、競馬予測AIを作るために必須なデータ前処理と特徴エンジニアリングについてお話ししました。今回はついにそのデータを用いてモデル作成について説明していきます!データサイエンスにおけるモデル作成には注意すべき点がたくさんあるのでわかりやすく解説します。

まずは理解しよう!分類と回帰ってどんな予測ができる?

AIを使って競馬を予測する際には、どんな種類の予測が必要なのかを考えることが大切です。そのためにまず押さえておきたいのが「分類」と「回帰」の違いです。これらの手法は、予測の目的によって使い分けることになります。

分類とは?

分類は、データをあらかじめ決められたカテゴリに分ける予測方法です。競馬で言えば、「どの馬が1着になるか?」を予測する場合がこれにあたります。予測したい結果が、例えば「1着」「2着」「3着」などのクラスに分かれているときに分類を使います。

他にも、「今レースで注目すべき馬はどれか?」を予測する場合、AIはその馬が「注目するべき馬」か「そうでない馬」か、という二つのカテゴリに分けて予測を行います。このように、分類は結果が明確なクラス(カテゴリ)に分けられる場合に使われる手法です。

回帰とは?

一方、回帰は、数値としての結果を予測する手法です。例えば、「今レースでの馬の着順を予測する」といった場合、着順は1着、2着、3着という整数の数値で表されますが、これを回帰モデルで予測します。回帰を使うことで、着順を予測するだけでなく、例えば「どの馬が何秒でゴールするか」といった連続的な数値を予測することもできます。

競馬のように、馬の走るタイムや速度が数値で表される場合には、回帰が有効です。この予測は、単に「1着」といったカテゴリに分けるだけでなく、具体的な数値として結果を出すことができるため、予測精度を高めることができます。

どちらを使うべきか?

それでは、競馬予測において分類と回帰はどちらを使うべきか、迷うこともあります。基本的には、結果がカテゴリとして決まる場合(例えば、「1着」「2着」など)には分類を使い、連続的な数値を予測したい場合(例えば、タイムや速度など)には回帰を使うことになります。

予測の内容に応じて、どの方法が最適かを考えることで、より精度の高い予測モデルを作成することができます。

次のステップでは、どのように実際にこれらの手法を使って競馬予測モデルを構築するかについて解説していきます。

競馬予測の第一歩:モデル構築の流れをざっくり知ろう!

ここからは、実際にAIモデルを構築していく全体の流れをざっくりとご紹介します。初めてのAIモデル作成で「何から始めればいいの?」と悩む方も多いと思いますが、基本的な流れを理解するだけでもスムーズに取り組むことができますよ。

ゴールを決める

最初に重要なのは、どんな予測をしたいのか「ゴール」を決めることです。競馬予測であれば、例えば「1着馬を予測する」「次のレースでのゴールタイムを予測する」などの具体的な目標が考えられます。目標が決まると、分類と回帰のどちらのモデルを作るべきかが見えてきます。

今回は「3着以内」に入るかカテゴリ分類することゴールとします。

モデルを選んで作成する

モデルの選択は、AI予測の精度を左右する非常に重要なステップです。競馬予測では、選ぶモデルによって予測のアプローチが変わり、最終的な結果にも影響が出ます。ここでは、競馬予測に役立ついくつかの代表的なモデルを紹介し、今回は「ロジスティック回帰」を選んだ理由についても詳しく説明します。

ロジスティック回帰:簡単で理解しやすい分類モデル

ロジスティック回帰は、「分類」に適したシンプルで分かりやすいモデルです。例えば、競馬の予測で「この馬が勝つかどうか」を二値(0または1)で予測したい場合、ロジスティック回帰はその確率を算出し、最終的な勝敗の判定をしてくれます。

ロジスティック回帰の主なメリットは、計算が比較的軽量で、特に小規模なデータでも実用的な予測ができる点です。また、特徴量(馬の過去成績や騎手情報など)と予測結果の関係が線形である場合に効果的に機能します。さらに、確率で結果を出すため、「勝つ確率がどれくらいか」を解釈しやすいのも魅力です。

決定木:わかりやすい「分岐」での予測

決定木は、予測のためにデータを分岐していくモデルで、分類と回帰の両方に使用可能です。このモデルは、競馬のような複雑な条件が絡む予測に向いています。例えば、馬場の状態や天気、騎手の経験などの条件ごとに分岐を設けていき、最終的な結果を出します。

決定木は「ルールベース」で予測を行うため、モデルがどういった条件で結果を出しているかが可視化しやすく、結果の解釈が比較的容易です。しかし、単純な決定木はデータに過度に適応してしまう(過学習)傾向があるため、大規模データには「ランダムフォレスト」や「勾配ブースティング」といった方法で改良することも一般的です。

ランダムフォレスト:より高精度な決定木の集合

ランダムフォレストは、複数の決定木を組み合わせて予測を行う方法です。単体の決定木が持つ過学習のリスクを軽減し、より安定した予測結果が得られます。これにより、競馬予測のように変動が大きいデータにも強い耐性を持ち、より精度の高い予測が期待できます。

ランダムフォレストのメリットは、多数の木の意見を集約するため、外れ値やノイズの影響を抑えられることです。また、重要な特徴量(例えば騎手のスキル、馬場状況など)を特定しやすく、モデルの解釈性も向上します。

勾配ブースティング:競馬予測のような複雑なデータに適したモデル

勾配ブースティングは、誤差を減らすために一連の弱い予測器(例えば小さな決定木)を組み合わせてモデルを作り上げる方法です。この手法は、特に非線形な関係を学習するのに向いており、複数の特徴量が複雑に絡む競馬予測に適しています。

勾配ブースティングは高精度なモデルを構築できる一方で、計算量が多く、時間がかかることが難点です。競馬予測で高い精度を求める場合には有力な選択肢ですが、リソースや計算コストも考慮する必要があります。

なぜロジスティック回帰を選ぶのか?

競馬予測において、特に「この馬が勝つ確率」を知りたい場合、ロジスティック回帰は最適な選択となり得ます。シンプルで計算が速く、競馬予測に必要な「勝ち・負け」といった二値分類にはうってつけです。また、初学者でもモデルの結果を解釈しやすく、特に少ないデータでも効果的に活用できるため、AI初心者が競馬予測に取り組む第一歩として適しています。

次のステップでは、このロジスティック回帰を用いて実際に競馬予測モデルを構築してみましょう。

データをうまく活かそう!クロスバリデーションで精度を高める

その前にデータサイエンスには必須の「クロスバリデーション」について説明しなければいけません。「クロスバリデーション」は、モデルの精度をしっかりと確認し、安定した予測を実現するために欠かせない手法です。ここでは、クロスバリデーションが何なのか、競馬予測でどのように活用できるのかをわかりやすく解説していきます!

クロスバリデーションとは?何のためにやるの?

クロスバリデーション(Cross Validation)とは、データを複数のグループに分けて、何度もトレーニングとテストを繰り返す手法です。簡単に言うと、「データを効率よく使って、モデルがちゃんと働いているか確かめる方法」です。

例えば、競馬予測である馬が勝つかどうかを予測するモデルを作るとします。通常、手元のデータを「トレーニング用データ」と「テスト用データ」に分けて学習させますが、分け方によって結果が変わることもあります。クロスバリデーションでは、データをいくつかのグループに分け、各グループを順番に「テスト用」に使いながら、他のグループでモデルを訓練します。こうして「データの一部だけに偏った結果」になるのを防ぎ、予測の精度を高めることができるのです。

競馬予測でのクロスバリデーションの使い方

競馬予測では、季節や馬場の状態、レースごとの傾向が異なるため、データにばらつきがあります。そのため、単純にデータを分割して訓練すると、特定のレースでしか強くならないモデルができてしまうこともあります。クロスバリデーションなら、さまざまなデータを使って訓練することで、予測が特定の状況に偏らないモデルを作ることが可能になります。

一般的に「k分割クロスバリデーション(k-fold cross-validation)」が用いられ、データをk個に分けて繰り返し訓練・評価を行います。例えば「5分割クロスバリデーション」では、データを5つのグループに分けて、5回の訓練とテストを行い、最終的な評価を平均してモデルの精度を確認します。

クロスバリデーションのメリット:モデルの精度が安定する!

クロスバリデーションを使う最大のメリットは、モデルの精度が安定することです。たった一度のテストだけでは「たまたまうまくいった結果」に過ぎない可能性がありますが、複数回のテストを経ることで、予測の精度を総合的に確認することができます。これにより、「この馬が勝つ確率は〇〇%」という予測に自信が持てるようになるのです。

簡単にできるモデル評価:そのモデル、うまく予測できてる?

AIで競馬予測をする上で、モデルがしっかりと機能しているかを確認する「モデル評価」は欠かせないステップです。モデルが予測した勝率がどのくらい正確か、予測結果が現実とどの程度一致しているかを見極めるためのポイントを、ここでしっかり押さえていきましょう!

モデル評価ってどうやるの?

モデル評価の方法にはいくつか種類がありますが、基本的には「正確さ」を測るものです。競馬の予測であれば、予測した馬の勝率が実際のレース結果とどれだけ一致しているかを確認します。この評価によって、モデルが単なる「偶然の当たり」ではなく、信頼性のある予測を提供しているかをチェックするのです。

代表的な評価指標:精度(Accuracy)とF1スコア

1. 精度(Accuracy)

精度は、正しい予測の割合を表すシンプルな指標です。例えば、予測した馬が実際に勝ったかどうかの「当たり率」を見るイメージですね。計算も簡単で、総予測数に対する正解の数を割るだけです。

ただし、注意点もあります。精度は全体的な「当たり率」だけを見ているため、予測の偏りには気づきにくいことがあります。たとえば、ほとんどの馬が負ける場合、「負け」を予測していれば高い精度が出てしまう可能性があります。そこで、次の「F1スコア」が重要になってきます。

2. F1スコア

F1スコアは、特に「勝ち」「負け」のように分類が重要なときに使われる指標です。正確さと精度のバランスを取りつつ、勝ち馬の予測の質を測ります。精度だけでは見落としてしまう「勝ち馬を正しく予測できたか」という点を把握しやすいので、競馬予測にはぴったりの指標です。

競馬予測におけるその他の評価指標

3. ロジスティック回帰の場合の対数損失(Log Loss)

特に確率を出すモデルで使用する「対数損失」は、勝ち馬の確率予測の質をチェックするのに役立ちます。例えば、勝ち馬の予測に確信があった(高い確率を示した)のか、それともかなり迷っていた(低い確率を示した)のかを評価します。正確な確率を出すほど対数損失が小さくなるため、競馬のように確率が大事な分野には向いています。

4. AUC(Area Under Curve)

「AUC」は、モデルの「総合的な予測力」を測定するための指標で、予測がどれだけ正しく当てはまっているかを、グラフ化してわかりやすく見せるものです。勝ち馬や上位馬の予測精度を可視化できるため、競馬のような実用的な場面でも評価の参考にしやすいです。

モデル評価の結果をどう活かす?

評価を行ったら、その結果をもとにモデルを改善していきましょう。例えば、F1スコアが低い場合、勝ち馬の予測に偏りがある可能性があります。この場合、特徴量の選び方を変えたり、データの分割方法を調整したりすると良いかもしれません。

クロスバリデーションのような手法と組み合わせて評価を繰り返し行うと、モデルが安定し、信頼性も高まります。これにより、競馬予測での「当たり率」もぐっと上がることでしょう。

実際のコード

これまでのことを踏まえロジスティック回帰を作成しクロスバリデーションで評価するコードが以下の通りです。以下のコードをcolabにコピペして実行してみましょう。

# 必要なライブラリをインポート
import os
import pandas as pd
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split, cross_val_score
from sklearn.metrics import accuracy_score, f1_score
from sklearn.impute import SimpleImputer

BASE_DIR = "."
all_result = pd.read_csv(os.path.join(BASE_DIR, "processed_all_result.csv"))

X = all_result.drop(columns=['着 順'])  # 特徴量
y = (all_result['着 順'] <= 3).astype(int) # 目的変数

imputer = SimpleImputer(strategy='mean')
X = imputer.fit_transform(X)

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

model = LogisticRegression(max_iter=1000)

accuracy_scores = cross_val_score(model, X_train, y_train, cv=5, scoring='accuracy')
f1_scores = cross_val_score(model, X_train, y_train, cv=5, scoring='f1')

print(f'クロスバリデーションのAccuracyスコア: {accuracy_scores}')
print(f'クロスバリデーションのF1スコア: {f1_scores}')
print(f'平均Accuracyスコア: {accuracy_scores.mean():.4f}')
print(f'平均F1スコア: {f1_scores.mean():.4f}')

model.fit(X_train, y_train)

y_pred = model.predict(X_test)

print(f'テストデータのAccuracyスコア: {accuracy_score(y_test, y_pred):.4f}')
print(f'テストデータのF1スコア: {f1_score(y_test, y_pred):.4f}')

次にこれらのコードの解説をします。いつものごとく「プログラミングに興味ない」という人は実行するだけで次の記事にいってもらってかまいません!ただし自分でAIを応用して作りたいという方は頑張って読んでみましょう。意外と簡単ですよ。

X = all_result.drop(columns=['着 順'])  # 特徴量
y = (all_result['着 順'] <= 3).astype(int)  # 目的変数

この部分では特徴量と目的変数を設定してます。特徴量Xにはすべての情報を含め、「着 順」列は予測対象のため削除します。目的変数yでは、着順が3位以内であれば1、それ以外であれば0にする処理を行い、このようにデータを整理することで、モデルが「3位以内の順位」を学習しやすくします。

imputer = SimpleImputer(strategy='mean')
X = imputer.fit_transform(X)

次に、欠損値(NaN)の処理を行います。欠損値は機械学習モデルの学習に支障をきたす可能性があるため、SimpleImputerを用いて欠損値を各列の平均値で埋めます。これにより、データの完全性が確保され、データが欠損している場合でも問題なくモデルに入力できます。

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

その後、訓練データとテストデータに分割します。この分割により、訓練データを用いてモデルを学習させ、テストデータを使って予測精度を評価できるため、モデルの汎化性能を確認することが可能です。今回は8:2の割合で分割し、random_stateを固定することで毎回同じ分割結果を得られるように設定しています。

model = LogisticRegression(max_iter=1000)

accuracy_scores = cross_val_score(model, X_train, y_train, cv=5, scoring='accuracy')
f1_scores = cross_val_score(model, X_train, y_train, cv=5, scoring='f1')

次に、ロジスティック回帰モデルを作成します。このモデルは、3位以内かどうかの2値分類に適したモデルです。さらに、モデルの精度を確認するためにクロスバリデーションを行います。クロスバリデーションでは、データを5つのグループに分け、交互に訓練と評価を行うことで、モデルの評価を安定させます。評価指標には精度(Accuracy)とF1スコアを用い、これにより、モデルがどの程度正確に3位以内かどうかを予測できるか、またその予測のバランスが取れているかを確認できます。

print(f'クロスバリデーションのAccuracyスコア: {accuracy_scores}')
print(f'クロスバリデーションのF1スコア: {f1_scores}')
print(f'平均Accuracyスコア: {accuracy_scores.mean():.4f}')
print(f'平均F1スコア: {f1_scores.mean():.4f}')

model.fit(X_train, y_train)

y_pred = model.predict(X_test)

print(f'テストデータのAccuracyスコア: {accuracy_score(y_test, y_pred):.4f}')
print(f'テストデータのF1スコア: {f1_score(y_test, y_pred):.4f}')

最後に、訓練データでモデルを学習させ、テストデータで予測を行い、テストデータでの精度とF1スコアを表示します。これにより、未知のデータに対するモデルの実際のパフォーマンスを確認することができます。しばらく待つと以下のような出力が得られると思います。注目してほしいのが「テストデータのAccuracyスコア」です。今回の結果ではテストデータにおけるAccuracyスコアが0.8082となり、これは約80%の正確さで馬が3位以内に入るかどうかを予測できていることを示しています。

>>>クロスバリデーションのAccuracyスコア: [0.80884058 0.8014205  0.79272358 0.80388462 0.80200029]
>>>クロスバリデーションのF1スコア: [0.44926931 0.41801189 0.3956044  0.41906398 0.42411467]
>>>平均Accuracyスコア: 0.8018
>>>平均F1スコア: 0.4212
>>>テストデータのAccuracyスコア: 0.8082
>>>テストデータのF1スコア: 0.4196

AIの予測を読み解く!モデルの解釈で勝利を目指そう

AIの予測を読み解く!モデルの解釈で勝利を目指そう

AIが競馬の予測をする上で、単に「予測精度が高い」というだけでは、どこを改善すべきかやその予測がなぜ出たのかがわかりません。特に、競馬のような変動要因の多い分野では「AIがどうしてその予測をしたのか」を理解することが大切です。そこで登場するのが、「モデルの解釈」です。モデルの中身を読み解くことで、予測の裏にある根拠を知り、より的確な予測に近づけることができます。

特徴量の重要度:何が予測を左右するのか?

ロジスティック回帰モデルでは、特徴量ごとの「重み(係数)」を確認することで、どの要素が予測結果に大きな影響を与えているかがわかります。この重みが大きければ大きいほど、該当する特徴量が予測結果を左右する重要な要因となります。例えば、過去の成績が良い騎手が勝率を高めている場合、「騎手の成績」という特徴量の重みが高くなるでしょう。

また、重みの正負も見逃せません。正の重みは、その特徴量が増えると予測される結果(例えば、3位以内に入る確率)が高まることを示し、逆に負の重みはそれが下がることを示します。これにより、各特徴量が「どの方向に影響を与えるのか」が見えてくるのです。例えば、「馬の年齢」が若いほど勝ちやすいなら、その特徴量には正の重みがつくことが多く、逆に年齢が上がるほど不利なら負の重みがつくでしょう。

実際のコード

モデルの解釈の一環として、ロジスティック回帰モデルの重み(係数)を確認するコードを以下に示します。このコードでは、特徴量の重要度を確認し、予測に対する影響力を評価します。

!pip install japanize-matplotlib
import matplotlib.pyplot as plt
import japanize_matplotlib

all_result = pd.read_csv(os.path.join(BASE_DIR, "processed_all_result.csv"))
X = all_result.drop(columns=['着 順'])  # 特徴量

coefs = pd.DataFrame(
    data={"coef": model.coef_.squeeze().tolist()}, index=X.columns.tolist()
).sort_values("coef", ascending=True)
coefs = coefs[~coefs.index.str.startswith("騎手_")]

plt.rcParams["axes.axisbelow"] = True
plt.barh(coefs.index.to_list(), coefs["coef"].to_list(), align="center")

plt.title("特徴量ごとの回帰係数")
plt.xlabel("回帰係数")
plt.ylabel("特徴量")
plt.grid(visible=True)

plt.show()

実行結果はおおよそ以下の通りになります。

人気
もっとも影響が大きいのは「人気」という特徴量で、係数が大きくマイナスになっています。これは、「人気」が高い(=数値が低い)馬ほど、上位に入る可能性が高いことを示しています。競馬では一般的に人気馬が好成績を収めることが多いため、この結果は納得できるものです。

枠番
次に影響が大きいのは「枠番」で、係数がわずかにプラスになっています。枠番が大きい(=外枠)ほど3位以内に入りやすいといえます。ただし、これは、ある枠番に出走する馬が順位に影響を与える可能性を示唆していますが、その影響はそれほど強くありません。

性別

「性_」とついた特徴量を観察すると「性_牡」、「性_牝」の順になっています。このことからどちらかというと牡馬の方が3位以内に入りやすいといえそうです。ただしこれもそこまで影響は大きくないですね。

まとめ

今回は競馬AI予測モデルの作り方を、初心者の方にも分かりやすく解説しました。分類と回帰という基本的な予測方法を理解し、モデル作成の流れを把握することで、競馬予測における第一歩を踏み出すことができたと思います。また、クロスバリデーションを活用してデータをうまく使い、精度を高める方法や、モデル評価の仕方を学んだことで、実際に予測がどれくらい当たるのかを測るための大事な指標を手に入れました。

ここまで学んだことを実践に生かして、より高精度な競馬AI予測モデルを作成するためには、さらにデータの質や特徴量の選定に工夫を加えたり、新しいアルゴリズムを試してみたりすることが次のステップになります。最初は少し難しく感じるかもしれませんが、一歩一歩進めていくことで、必ず成果が出るはずです。

次回は、さらに一歩踏み込んで、より高度なモデルを作っていくので、楽しみにしていてくださいね!