前回、ロジスティック回帰に見切りをつけて LightGBM で学習モデルを作ってみた。
競馬予想で重要なのは、モデルの精度よりも馬券の回収率が目的になるので、とりあえず馬券の回収率を計算できるコードを追加してみるのだ
前回:【第5回】Python で競馬予想してみる ~ LightGBM ~
ベースとなるモデル
前回(【第5回】Python で競馬予想してみる ~ LightGBM ~)作成したモデルをそのまま使用
コードが汚くなってきたのとデータフレームを作り過ぎてしまったので、関数化したほうが便利なのかなと思いつつコードを整理して、再学習
### AUC
前回と変わらず(あたりまえなのだ)0.770
くらい
train roc_auc_score = 0.801985175031238
eval roc_auc_score = 0.7701583550634967
### ROC曲線
きれいな曲線描いてます(良い悪いは別として)
回収率の計算方法
LightBGM に学習させる前に、X_train X_test のデータフレームから 回収率に必要そうな 単勝オッズ, 複勝配当, 人気, 確定着順, 3着以内
のデータの入ったデータフレームを作成しておいた。
下の df_rslt
# データの分割を行う(学習用データ 0.8 評価用データ 0.2) stratify:層化抽出
X_train, X_eval, y_train, y_eval = train_test_split(dataX, dataY, test_size=0.2, stratify=dataY)
# 学習データの修正
X_train = X_train.drop(['レースID(新)', '単勝オッズ', '複勝配当', '人気', '確定着順', '3着以内'], axis=1) # 不要なデータを削除
# 検証データの修正
df_rslt = X_eval[['レースID(新)', '単勝オッズ', '複勝配当', '人気', '確定着順', '3着以内']]
X_eval = X_eval.drop(['レースID(新)', '単勝オッズ', '複勝配当', '人気', '確定着順', '3着以内'], axis=1) # 不要なデータを削除
###回収率の計算方法
このデータフレームに、y_pred_proba
, y_pred
を追加
y_pred
は、y_pred_proba
の数値を 0.5 を境に 1と 0に変換(今回は使わなかったが。。)
そして、y_pred_proba
の値を 0 から 1 までスライドさせながら単勝と複勝の回収率を計算した。
y_pred_proba = model.predict(X_eval)
y_pred = np.where(y_pred_proba < 0.5, 0, 1) # 1と0に変換
df_rslt['予測'] = y_pred_proba
df_rslt['予測1'] = y_pred
df_rslt.drop(['予測','予測1','馬券期待値', '馬券期待値2'], axis=1)
# 単勝と複勝の回収率を、y_pred_proba の閾値を変化させながら計算
gain_tan = {}
gain_fuku = {}
n_sample = 100
for i in tqdm(range(n_sample)):
threshold = i / n_sample
gain_tan[threshold] = df_rslt[(df_rslt['予測'] > threshold)&(df_rslt['確定着順'] == 1)]['単勝オッズ'].sum()/len(df_rslt[df_rslt['予測'] > threshold])
gain_fuku[threshold] = df_rslt[df_rslt['予測'] > threshold]['複勝配当'].sum()/len(df_rslt[df_rslt['予測'] > threshold])
y_pred_proba
の閾値 0.8を超えるとグラフがばらつくので、サンプル数を確認すると 20万件中の 600件
かなり少ないのだ
今回、回収率の計算ができるモデルも完成。今回はここまでなのだ
コードを書きながら、馬券の買い方次第でもどうにかなりそうな気がしてきたが。。
次回は特徴量の整理して、回収率の変化を見るのだ
参考:【機械学習】競馬予想AIの回収率を上げた意外な方法とは?〜前編〜【Python】