機械学習を使った株価予測(LightGBMをOptunaでパラメータチューニング)

8回目で精度の高い学習モデルを構築するために「交差検証」「ROC 曲線とAUC」について実装追加しました。

11回目ではファンダメンタルズ指標を追加することで「AUC=0.70」を超えました。

これは、無謀にも「株の自動売買で億り人」を夢見て人生を浪費している一人の中年男の物語です。

今回は学習モデルの「ハイパーパラメータの調整」を実装を学び、加えて過学習の抑制についても検討してみます。

 

パラメータのチューニング

パラメータとは機械学習モデルにおける設定値や制限値のことです。ハイパーパラメータとも呼びます。

そして、モデルが最適解を出せるパラメータを走査し、設定することを「パラメータチューニング」といいます。

代表的なチューニング方法として2種についてまとめます。

グリードサーチ/ランダムサーチ

グリッドサーチは、あらかじめパラメータの候補値を指定し、その候補パラメータを組み合わせて学習を試行することにより最適なパラメータを走査する方法です。

ランダムサーチは、パラメータの設定範囲および試行回数を指定し、指定値範囲内から無作為に抽出したパラメータにより学習を試行することにより最適なパラメータを走査する方法です。

【メリット】

探索するパラメータの候補を把握しやすい

【デメリット】

組み合わせによる探索点の数が膨大になり得るため、探索するパラメータやその候補の数を多くすることができない

ベイズ最適化(Bayesian Optimization)

ベイズ最適化 (Bayesian Optimization) は、過去の実験結果から次の実験パラメータを、確率分布から求めることで最適化する手法です。

ランダムサーチではまったく精度が出なかったパラメータ付近も探索しますが、ベイズ最適化では探索履歴を使うことで精度が良い可能性の高いパラメータを効率良く探索することを試みます。

インストール

実装方法

ベイズ最適化でのパラメータ探索

最近では hyperoptというライブラリが比較的よく使われています。

また2018年にoptunaというライブラリが公開されました。

hyperopt(ハイパーオプト)

TPE(tree-structured parzen estimator) というアルゴリズムで計算します。

次の設定をすることで、パラメータの探索を自動的に行い、探索したパラメータとそのときの評価指標によるスコアを出力できます。

  • 最小化したい評価指標の設定
  • 探索するパラメータの範囲を定義する
  • 探索回数の指定

optuna(オプチュナ)

2018年末に公開されたフレームワークです。

開発会社は「Preferred Networks」。Chainerの生みの会社です。

最適化アルゴリズム自体はhyperoptと同様にTPEを用いていますが、次のような改善がされています。

  • Define by Run スタイルAPI
  • 学習曲線を用いた試行の枝刈り
  • 並列分散最適化

何のパラメータを学習させるか?

重要と思われるパラメータからチューニングします。重要とされる順序は次のとおりです。

max_depth 決定木の深さ
subsample 決定木ごとに学習データの行をサンプリングする割合
colsample_bytree 決定木ごとに特徴量の列をサンプリングする割合
min_child_weight 葉を分岐するために最低限必要となる葉を構成するデータ数
gamma 決定木を分岐させるために最低限減らさなくてはいけない目的関数の値
alpha 決定木の葉のウェイトに対するL1正則化の強さ
lambda 決定木の葉のウェイトに対するL2正則化の強さ

 

その他、パラメータには特徴があります。

モデル訓練のスピードをあげる

  • bagging_fraction(初期値1.0)とbagging_freq(初期値0)を使う
  • feature_fraction(初期値1.0)で特徴量のサブサンプリングを指定
  • 小さいmax_bin(初期値 255)を使う
  • save_binary(初期値 False)を使う
  • 分散学習を使う

推測精度を向上させる

  • 大きいmax_bin(初期値255)を使う
  • 小さいlearning_rate(初期値0.1)と大きいnum_iterations(初期値100)を使う
  • 大きいnum_leaves(初期値31)を使う
  • 訓練データのレコード数を増やす(可能であれば)

過学習対策

  • 小さいmax_binを使う(初期値255)
  • 小さいnum_leavesを使う(初期値31)
  • min_data_in_leaf(初期値20)とmin_sum_hessian_in_leaf(初期値1e-3)を使う
  • bagging_fraction(初期値1.0)とbagging_freq(初期値0)を使う
  • feature_fraction(初期値1.0)で特徴量のサブサンプリングを指定
  • 訓練データのレコード数を増やす(可能であれば)
  • lambda_l1(初期値0.0)、lambda_l2(初期値0.0)、min_gain_to_split(初期値0.0)で正則化を試す
  • max_depth(初期値-1)を指定して決定木が深くならないよう調整する

optunaを使った実装内容

前回、KFoldやAUC、交差検証も取り入れたので、それらを全て含めたクラスを定義しました。

結果は次のようになっています。

出力されたパラメーターを使って実際に学習させてみます。

AUCの出力は「0.69」です。

実際には精度が上がる銘柄と上がらない銘柄がありました。

max_depthを指定して過学習を防いでみる

「max_depth=4」を指定してLightGBMを解いてみます。

作られた決定木です。

これぐらいの木であれば過学習は避けられているかもしれません。

因みに「AUC=0.65」程度でした。

下がりましたが、前回スコアを0.7まで上げていたので昔の値に戻った程度です。

 
 

なお「1998/01/05~2015/12/14」を利用して学習させています。

つまり「2015/12/15~2020/01/24」が未知の予測(フォワードテスト)となります。

その結果です。

利益曲線は次のとおりです。

前回同様、フォワードテスト後に寝ています。

決定木を4階層にすることで、勝率、プロフィットファクターは下がりましたがフォワードテストの勝率が少しだけ改善しました。

誤差の範囲かもしれませんが、多少の自動売買の活路がみえました。

ちなみに「max_depth=3」の場合は次の通りです。

利益曲線は次のとおりです。

「max_depth=4」の場合と大きな差はありません。

これ以上の深さの変更には意味は無さそうです。

まとめ

Optunaでパラメータチューニングは、一度実装できれば非常に簡単に出来ることが分かりました。

しかしパラメータを変更すると、逆に精度が落ちてしまうこともあり、非常に使い辛いです。

また株価予測でチューニングすべきは過学習にならない為であり、そのためには「max_depth」に多少の価値があることが分かりました。

タイトルとURLをコピーしました