見出し画像

[競馬予想AI] モデルを改良、調整していく

前回は現在作っている競馬予想AIについてサラッと紹介しました。

今回はそのAIの改良と調整について紹介しようと思います。

評価指標を熟慮する

まず、モデルの性能が良くなっているのか悪くなっているのか判断するための指標をきっちり決めておく必要があります。指標は次のようなものがある。

・Accuracy(正解率)
・Precision(適合率)
・Recall(再現率)
・F1値
・ROC-AUC

今回取り扱うデータは勝ち馬をラベル1、それ以外の馬をラベル0として扱うので不均衡データです。そのため、評価指標として正解率は不適切です。なぜなら、例えばラベル1のデータが1割、ラベル0のデータが9割だった場合、すべてラベル0という答えを出しても正解率90%と不適切に高くなります。

適合率と再現率については予測問題の性質によってどちらを選択するか異なります。簡単に説明すると、正例を取りこぼしたくないときは再現率、正例を厳密に判定したいときは適合率使用します。F値は両者の調和平均となります。ROC-AUCはROC曲線の下側面積です。詳しい解説は省きますが、今回はF値を考慮しつつROC-AUCを使用します。

使用するアルゴリズム

アルゴリズムはxgboostを使用しています。以降の変更作業についてはxgboostを前提とした話となります。

データの標準化

ここからは実際の施策について紹介していきます。

まず簡単な、データの標準化から行いました。trainデータを標準化します。結果、精度の向上は見られませんでした。xgboostは木構造のため各特徴量の値の相対的な大小関係について考慮するため、標準化して値の幅を縮小しても恩恵はありません。

標準化の方法は数行のコードで完了します。

from sklearn.preprocessing import StandardScaler

sc = StandardScaler()
X_train = sc.fit_transform(X_train) 

不均衡データへの対応

不均衡データへの対策はいくつか存在します。

・オーバーサンプリング
・アンダーサンプリング
・xgboostのパラメータによる調整

少ないラベルのデータを増やすアップサンプリング、多いラベルのデータを減らすアンダーサンプリング、モデルのパラメータを設定することによって重みの与え方を変更する方法などがあります。
まずは簡単なxgboostのパラメータ変更を行いました。scale_pos_weightを設定します。

param = {'scale_pos_weight':10.0}

このパラメータの設定値は"negative cases / positive cases"とするのが良いようです。この結果、すべてラベル0だという予測結果を出すようなことはなくなりました。出力値の閾値調整も不要になりました。ただし、直接的な精度の向上は見られませんでした。

ハイパーパラメータをチューニングする

ハイパーパラメータのチューニングは当然といえば当然ですが、やりすぎると過学習になります。
今回はhyperoptを使っています。チューニングの対象となるパラメータは以下の5つです。

・eta(学習率)
・min_child_weight
・max_depth
・subsample
・colsample_bytree

hyperoptを使ったチューニングでは下のように柔軟に探索パラメータの範囲を指定できます。

space = {
       'booster': 'gbtree',
       'objective': 'binary:logistic',
       'scale_pos_weight':10.0,
       'gamma': 0.0,
       'lambda': 1.0,
       'random_state': 777,
       'eta': hp.quniform('eta', 0.02, 0.2, 0.02),
       'min_child_weight': hp.loguniform('min_child_weight', np.log(0.1), np.log(10)),
       'max_depth': hp.choice('max_depth', np.arange(3, 10, dtype=int)),
       'subsample': hp.quniform('subsample', 0.6, 0.95, 0.05),
       'colsample_bytree': hp.quniform('colsample_bytree', 0.6, 0.8, 0.05)
   }

チューニングによって多少の精度向上を見られますが格段にはよくなりませんでした。
hyperoptでチューニングした後は様子を見ながら細かい数値を指定してさらにチューニングするとよいそうです。

アーリーストッピングを行う

過学習を防ぐためにアーリーストッピングを行います。
今回は損失関数が10回改善されなかった場合に学習をストップするようにしました。だいたいの場合はこれくらいで十分でしょう。

model = xgb.train(params, dtrain, num_round, evals = watchlist, early_stopping_rounds=10,)

これにより多少の柔軟性が出てきましたが、やはりAUCやF1に大きな変化は見られませんでした。

今後の施策

機械学習のモデルとして基本的な施策を試してみました。
しかしながらなかなか性能向上には繋がりませんでした。その理由としてはアルゴリズムがそもそも適さなかったか、多少の調整をせずとも強いアルゴリズムだったか、学習データが不適切であったかなどが考えられます。

現在のモデルのAUCは0.75ほどです。0.5がランダム、1.0で完璧な予測となりますので、ちょうどその中間ほどに位置しています。最低でも0.8以上を目指していきたいです。

次の施策としてはもう少し評価関数や損失関数の見直しをしたのち、深層学習の適用を目指すこととします。

・評価指標にはROC曲線ではなくPR曲線のAUC(AP)を使う。
・損失関数にはLogLossではなくNormalized Entropyを使う。
・評価関数としてMCCを使う。
・深層学習モデルを作成したのち、xgboostのモデルとアンサンブル学習させる。
・オーバーサンプリングを試してみる。

(上記施策内容について更新しました。以下の記事をご覧ください。)


よろしければサポートをよろしくお願い致します。いただいたサポートは今後の技術向上のために書籍費用等に当てられ、このnoteで還元できればと思います。