LightGBMによるAI競馬予想(ランキング学習)

AI競馬

この記事を読む前に「LightGBMによるAI競馬予想(準備編)」の記事を先に読んでください。

ランキング学習(lambdarank)

二値分類や回帰分析が絶対的な「値」を求めるのに対し、ランキング学習は相対的に順位付けします。具体的な数値ではなく順位なので、いかにも競馬予想に向いてそうです。

ここに公開するPythonのソースコードは「特徴量重要度」の可視化を実装しています。学習データを作るSQLで目的変数の項目名を「target」にすれば、オリジナルの学習データで分析する場合でもそのまま使えます。

ソースコードは学習用と予測用に分けてます。

欠損値(null)は、SQLで何らかの値(0など)に変換しておくことを前提にしてます。欠損値についてPythonでは何もしてないってことです。

学習用ソースコード

以下が「ランキング学習」で学習するPythonのソースコードです。

このページの最後の、有料会員限定のダウンロードリンクからもファイルをダウンロードできます。

import pandas as pd
import numpy as np
import lightgbm as lgb
import math
import matplotlib.pyplot as plt
def train_test_split(df): # 説明変数の項目名を取得 columns=['target', 'query_id'] feature = list(df.drop(columns, axis=1).columns)
group = df['query_id'].value_counts() df = df.set_index(['query_id']) group = group.sort_index()
# 説明変数(x)と目的変数(y)をインデックスでソート df.sort_index(inplace=True) # 説明変数(x)と目的変数(y)を設定 x = df[feature] y = df['target']
return x, y, group
# ファイル読み込み in_file_name = 'lambdarank_train.csv' df = pd.read_csv(in_file_name, encoding='SHIFT_JIS')
# 訓練データとテストデータを分割 test_size = 0.2 point = max(df['query_id']) * test_size point = math.trunc(point) train = df[df['query_id'] > point] test = df[df['query_id'] <= point]
# 訓練データとテストデータを分割 x_train, y_train, group = train_test_split(train) x_test, y_test, eval_group = train_test_split(test)
# モデルの学習 model = lgb.LGBMRanker(random_state=0) model.fit(x_train, y_train, group=group, eval_set=[(x_test, y_test)], eval_group=[list(eval_group)]) model.booster_.save_model('lambdarank_model.txt')
# 特徴量重要度 feature = list(df.drop(columns=['target', 'query_id']).columns) importance = np.array(model.feature_importances_) df = pd.DataFrame({'feature':feature, 'importance':importance}) df = df.sort_values('importance', ascending=True)
n = len(df) # 説明変数の項目数を取得 values = df['importance'].values plt.barh(range(n), values)
values = df['feature'].values plt.yticks(np.arange(n), values) # x, y軸の設定
plt.show()

学習データを作る

説明変数は他の分析方法と共通にしました。内容は「LightGBMによるAI競馬予想(準備編)」の記事を見てください。学習データのファイル名は「lambdarank_train.csv」とします。

今回のサンプルでは目的変数の「確定着順」を、次のように編集します。

  • 1着は「出走頭数」で1番大きい数値
  • 2着は「出走頭数 – 1」で2番目に大きい数値
  • 最下位は「1」で1番小さい数値

ランキング学習の学習データには目的変数以外に「ラベル」と呼ばれる項目が必要です。ラベルの項目名は「query_id」にしてます。競馬予想におけるラベルとは1つのレースを表す、学習データ内でユニークなレース番号みたいなもんです。

このページの最後に、サンプルのSQLを有料会員に公開しています。ユーザーがカスタマイズして利用することも可能ですし、SQLを学習したい方の参考にもなります。

LightGBMに学習させる

今回の例では、Cドライブの直下に「pckeiba」というフォルダを作って、

  • 学習データ(*.csv)
  • 学習用ソースコード(*.py)

2つのファイルを置きます。こういう状態です。

そしてコマンドプロンプトを起動して、次の2つのコマンドを「1行ずつ」実行してください。

cd C:\pckeiba

python lambdarank_train.py

LightGBMが学習を開始します。処理が終わると「特徴量重要度」を表示します。

モデルを評価する

今回のサンプルに評価指標はありません。

このモデルを「lambdarank_model.txt」に保存しています。このファイルは予想するとき使います。

特徴量重要度

参考として「特徴量重要度」の可視化を実装してます。特徴量重要度をざっくり言うと、重要度が高い説明変数ほど、目的変数である確定着順に対して影響力が強いということです。

これを見ながら説明変数を取捨選択したり、LightGBMパラメータをチューニングしたりします。今回のモデルでは「1走前 タイム差」が最も影響力が強いと判断されました。「JRA-VANタイム型データマイニング」が3位で意外と頑張ってます。

あくまで今回のモデルによる結果だから、すべての競馬においてこの結果が当てはまると言うわけじゃないです。

いろいろ試してモデルの精度に納得したら、これを使って明日のレースを予想させます。

予測用ソースコード

以下が「ランキング学習」で予想するPythonのソースコードです。

このページの最後の、有料会員限定のダウンロードリンクからもファイルをダウンロードできます。

import pandas as pd
import numpy as np
import lightgbm as lgb
import os
import sys
# 出馬表ファイル読み込み fname = sys.argv[1] x_test = np.loadtxt(fname, delimiter=',', skiprows=1)
# モデル読み込み bst = lgb.Booster(model_file='lambdarank_model.txt')
# テストデータの予測 y_pred = bst.predict(x_test, num_iteration=bst.best_iteration)
# 拡張子を除いたファイル名を取得 fname = os.path.splitext(os.path.basename(fname))[0]
# 予測値を出力 df = pd.DataFrame({'予測値':y_pred}) df.to_csv(fname + '_pred.csv', encoding='SHIFT_JIS', index=False)

出馬表データを作る

予測させる出馬表データは、学習データ作成のSQLと出力後のファイルを少し改造すれば作れます。学習データとの違いは次の3つです。

  1. SQLで目的変数「確定着順」の項目を消す。
  2. SQLで「クエリID」の項目を消す。
  3. SQLで予想するレースでレコードの抽出条件を設定する。

出馬表データのファイル名は何でも良いですが、ここでは「yyyymmddjjrr.csv」とします。
今回のサンプルでは「2021年 天皇賞(秋)」を予想してみます。

このページの最後に、サンプルのSQLを有料会員に公開しています。ユーザーがカスタマイズして利用することも可能ですし、SQLを学習したい方の参考にもなります。

予測(予想)させる

先ほどと同じ「pckeiba」というフォルダに、

  • 出馬表(*.csv)
  • モデル(*.txt)
  • 予測用ソースコード(*.py)

3つのファイルを置きます。こういう状態です。

そしてコマンドプロンプトを起動して、次のコマンドを実行してください。予測用ソースコードの後に、半角スペースと出馬表のファイル名です。

python lambdarank_pred.py 202110310511.csv

処理が終わると1つのファイルが出力されます。「予測値」のファイルです。

  • yyyymmddjjrr_pred.csv (予測値)

このファイルは数値のデータ以外に何も無いので分かりにくいですが、出馬表データと同じ馬番の昇順で出力されます。これで馬券を買うときは、馬番と馬名だけの出馬表をSQLでCSVに出力して、そこへ貼り付けて予測値で並べ替えるとかして使えば良いでしょう。例えばこんな感じです。

レース結果は予測値1~3位馬で3連複を的中してます。

「ランキング学習」による競馬予想の話は以上です。

今回のサンプルはあくまで1つの「サンプル」でしかありません。完成させるのはユーザーのあなたです。

SQLファイルのダウンロードと使い方

残りのコンテンツを表示するには、ログインする必要があります。 . 会員について
タイトルとURLをコピーしました