LightGBM+Optuna モデリング自動パラメータ調整チュートリアル

機械学習のコンテストでは、パラメーター調整アーティファクトの組み合わせが非常に人気があり、 LightGBM+Optuna はkaggle多くのトップ ソリューションに頻繁に登場しますパラメータ調整に時間がかかり悩んでいる友人も多いと思い、今回は私自身の経験も交えて、仕事でも使えるモデル+パラメータ調整の使い方についてのチュートリアルをお届けします。LGBMOPTUNA

これについてはあまり言うことはありませLightGBMんが、以前にも多くの記事で紹介しましたが、XGBoost基本をベースに効率化を図るために最適化されたバージョンであり、マイクロソフト社からリリースされており、精度を落とすことなく非常に高い作業効率を実現しています。現在、比較的優れた機械学習モデルとして広く認識されており、分類と回帰をすべて満たすことができます。

パラメータチューニング、つまりモデルのハイパーパラメータチューニングに関しては、 と考えられるかもしれませんGridSearch実際、私も最初に使用しましたGridSearch。暴力の美学は優れていますが、欠点は明らかです。実行するには時間がかかりすぎ、時間コストが高すぎます。対照的に、ベイジアン フレームワークに基づくパラメーター調整ツールははるかに快適です。一般的なツールなど、そのようなオープンソース ツールも多数ありますHyperOPTもちろん、今日の主役はそれではなく、より香りが良くOPTUNA、軽量でより強力で、離陸するのに十分な速度を持った別のモデルです。

LGBM例を使って説明する必要があるため、以下ではLGBM主なハイパーパラメータから始めて、Optunaこれらのハイパーパラメータ設定に従ってパラメータを調整します。

技術交流

テクノロジーは共有とコミュニケーションを学ぶ必要があり、密室で作業することはお勧めできません。1 人で速く進むこともできますし、グループでより遠くまで進むこともできます。

関連するファイルとコードがアップロードされており、コミュニケーション グループに参加することで入手できます。グループのメンバーは 2,000 人を超えています。メモを追加する最良の方法は、ソース + 興味の方向です。これにより、同じ考えを持つ人を見つけるのに便利です友達。

方法①、WeChatアカウントを追加:dkl88194、備考:CSDNから+グループを追加
方法②、WeChat検索公式アカウント:Python学習とデータマイニング、バックグラウンド返信:グループを追加

LightGBMパラメータの概要

一般に、ツリーベース モデルのハイパーパラメータは 4 つのカテゴリに分類できます。

  1. デシジョン ツリーの構造と学習に影響を与えるパラメータ

  2. トレーニング速度に影響するパラメータ

  3. 精度向上のためのパラメータ

  4. 過学習を防ぐためのパラメータ

ほとんどの場合、これらのカテゴリは多くの部分で重複しているため、1 つのカテゴリの効率を上げると、別のカテゴリの効率が低下する可能性があります。パラメータを完全に手動で調整すると、さらに苦痛になります。したがって、初期段階では、いくつかの自動パラメータ調整ツールを使用して大まかな結果を得ることができます。自動パラメータ調整ツールの核心は、適切なパラメータ範囲を与える方法です。適切なパラメータ グリッドがあれば、Optunaこれらのカテゴリ間で最もバランスのとれたパラメータの組み合わせが自動的に見つかります。

ハイパーパラメータとしては以下のLGBM4種類が導入されています。

1. ツリー構造のハイパーパラメータを制御する

max_ Depth と num_leaves

ではLGBM、ツリー構造を制御するために調整する最初のパラメータはmax_depth(ツリーの深さ) とnum_leaves(リーフ ノードの数) です。これら 2 つのパラメーターは、ツリー構造を制御するのに最も簡単です。なぜならLGBMleaf-wiseツリーの深さを制御しないと、非常に簡単にオーバーフィットしてしまうからです。max_depth一般設定を に設定してみてください3到8

これら 2 つのパラメータの間には一定の関係もあります。二分木なのでnum_leaves最大値は となるはずです2^(max_depth)したがって、決定するということは、値の範囲を決定するmax_depthことも意味します。num_leaves

min_data_in_leaf

ツリーのもう 1 つの重要な構造パラメータは、min_data_in_leafそのサイズが過学習かどうかにも関係していることです。これは、下向きに分割するリーフ ノードのサンプルの最小数を指定します。たとえば、100 に設定すると、ノード サンプルの数が 100 未満になると、成長が停止します。もちろん、min_data_in_leafの設定はトレーニング サンプルの数 と にも依存しますnum_leaves大規模なデータ セットの場合、通常は 1,000 を超えるレベルが設定されます。

精度を向上させるハイパーパラメータ

learning_rate と n_estimators

より高い精度を達成する一般的な方法は、より多くのサブツリーを使用し、学習率を下げることです。つまり、最適なLGBM中和の組み合わせを見つけることですn_estimatorslearning_rate

n_estimators決定木の数を制御しますlearning_rateが勾配降下のステップ サイズ パラメーターも制御します。経験によれば、LGBMオーバーフィットが容易であり、learning_rate勾配ブースティング学習の速度の制御に使用できます。一般的な値は の間に設定できます0.01 和 0.3一般的なアプローチは、1000 などの少し多めのサブツリーを使用し、それよりも低いサブツリーを設定してlearning_rateearly_stopping最適な反復数を見つけることです。

max_bin

さらに、max_bin精度を向上させるために値を増やすこともできます (デフォルトは 255)。変数ビンの数が多いほど、より詳細な情報が保持されるため、逆に、変数ビンの数が少ないほど、より多くの情報が失われますが、一般化が容易になるためです。これは特徴量エンジニアリングのビニングと同じですが、内部ヒストグラム アルゴリズムを通じてhist処理されます。max_bin高すぎると、過剰適合の危険性もあります。

過学習を制御するためのより多くのハイパーパラメータ

lambda_l1 と lambda_l2

lambda_l1And はと の正則化lambda_l2に対応し、 と同じで、葉ノードの数と葉ノードの重みに対するペナルティで、値が大きいほどペナルティも大きくなりますこれらのパラメーターの最適値は、その大きさが過学習に直接関係しないため、調整がより困難になりますが、関係する可能性があります。一般的な検索範囲は にありますL1L2XGBoostreg_lambdareg_alpha(0, 100)

min_gain_to_split

このパラメータは、スプリットの最小ゲインを定義します。このパラメータはデータの品質を示すものでもあり、計算ゲインが高くないと下方に分割できません。設定した深さが非常に深いにもかかわらず、下方向に分割できない場合は、分割できるものが見つからないというLGBMメッセージが表示されます。warningパラメータの意味はXGBoostと同じでgamma、データ品質が限界に達していることを示します。より保守的な検索範囲は、(0, 20)大規模なパラメーター グリッドでの追加の正則化として使用できます。

Bagging_fraction と feature_fraction

これら 2 つのパラメータの値の範囲は です(0,1)

feature_fraction各ツリーをトレーニングするときにサンプリングする特徴のパーセンテージを指定します。これは、過学習を避けるために存在します。一部の特徴はゲインが高いため、各サブツリーが均質化されるように、各サブツリーが分割されるときに同じ特徴が使用される場合があります。ただし、より低い確率で特徴をサンプリングすると、毎回同じ強力な特徴に遭遇することを回避できるため、サブツリーの特徴が差別化、つまり一般化されます。

bagging_fraction各ツリーのトレーニングに使用されるトレーニング サンプルの割合を指定します。このパラメータを使用するには、それを設定する必要がありますbagging_freq。理由はfeature_fraction同じであり、すべてのサブツリーをより良く、異なるものにすることもできます。

Optuna で検索グリッドを作成する

Optunaの最適化プロセスでは、まず目的関数が必要です。これには次のものが含まれます。

  • 辞書形式のパラメータのグリッド

  • モデルを作成して (おそらく相互検証を使用してkfold)、ハイパーパラメーターの組み合わせを試します

  • モデルトレーニング用のデータセット

  • このモデルを使用して予測を生成します

  • ユーザー定義の指標とリターンに基づいたスコア予測

一般的に使用されるフレームワークは次のとおりです。モデルは 50% オフでKfold、モデルの安定性を確保できます。最後の行は、最適化する必要がある CV スコアの平均を返します。logloss最小値、auc最大値、最大値の指標、ksトレーニング セットとテスト セット間のauc最小ギャップなど、目的関数を自分で設定できます。

import optuna  # pip install optuna
from sklearn.metrics import log_loss
from sklearn.model_selection import StratifiedKFold

def objective(trial, X, y):
    # 后面填充
    param_grid = {
    
    }
    cv = StratifiedKFold(n_splits=5, shuffle=True, random_state=1121218)

    cv_scores = np.empty(5)
    for idx, (train_idx, test_idx) in enumerate(cv.split(X, y)):
        X_train, X_test = X.iloc[train_idx], X.iloc[test_idx]
        y_train, y_test = y[train_idx], y[test_idx]

        model = lgbm.LGBMClassifier(objective="binary", **param_grid)
        model.fit(
            X_train,
            y_train,
            eval_set=[(X_test, y_test)],
            eval_metric="binary_logloss",
            early_stopping_rounds=100,
        )
        preds = model.predict_proba(X_test)
        cv_scores[idx] = preds

    return np.mean(cv_scores)

以下はパラメータ設定です。Optunaより一般的なパラメータ設定方法はsuggest_categoricalsuggest_int、 、ですsuggest_floatこのうち、suggest_intと のsuggest_float設定方法は です(参数,最小值,最大值,step=步长)

def objective(trial, X, y):
    # 字典形式的参数网格
    param_grid = {
    
    
        "n_estimators": trial.suggest_categorical("n_estimators", [10000]),
        "learning_rate": trial.suggest_float("learning_rate", 0.01, 0.3),
        "num_leaves": trial.suggest_int("num_leaves", 20, 3000, step=20),
        "max_depth": trial.suggest_int("max_depth", 3, 12),
        "min_data_in_leaf": trial.suggest_int("min_data_in_leaf", 200, 10000, step=100),
        "max_bin": trial.suggest_int("max_bin", 200, 300),
        "lambda_l1": trial.suggest_int("lambda_l1", 0, 100, step=5),
        "lambda_l2": trial.suggest_int("lambda_l2", 0, 100, step=5),
        "min_gain_to_split": trial.suggest_float("min_gain_to_split", 0, 15),
        "bagging_fraction": trial.suggest_float(
            "bagging_fraction", 0.2, 0.95, step=0.1
        ),
        "bagging_freq": trial.suggest_categorical("bagging_freq", [1]),
        "feature_fraction": trial.suggest_float(
            "feature_fraction", 0.2, 0.95, step=0.1
        ),
    }

Optuna を作成して自動的に調整する

以下は、参照用の完全な目的関数フレームワークです。

from optuna.integration import LightGBMPruningCallback

def objective(trial, X, y):
    # 参数网格
    param_grid = {
    
    
        "n_estimators": trial.suggest_categorical("n_estimators", [10000]),
        "learning_rate": trial.suggest_float("learning_rate", 0.01, 0.3),
        "num_leaves": trial.suggest_int("num_leaves", 20, 3000, step=20),
        "max_depth": trial.suggest_int("max_depth", 3, 12),
        "min_data_in_leaf": trial.suggest_int("min_data_in_leaf", 200, 10000, step=100),
        "lambda_l1": trial.suggest_int("lambda_l1", 0, 100, step=5),
        "lambda_l2": trial.suggest_int("lambda_l2", 0, 100, step=5),
        "min_gain_to_split": trial.suggest_float("min_gain_to_split", 0, 15),
        "bagging_fraction": trial.suggest_float("bagging_fraction", 0.2, 0.95, step=0.1),
        "bagging_freq": trial.suggest_categorical("bagging_freq", [1]),
        "feature_fraction": trial.suggest_float("feature_fraction", 0.2, 0.95, step=0.1),
        "random_state": 2021,
    }
    # 5折交叉验证
    cv = StratifiedKFold(n_splits=5, shuffle=True, random_state=1121218)

    cv_scores = np.empty(5)
    for idx, (train_idx, test_idx) in enumerate(cv.split(X, y)):
        X_train, X_test = X.iloc[train_idx], X.iloc[test_idx]
        y_train, y_test = y[train_idx], y[test_idx]
        
        # LGBM建模
        model = lgbm.LGBMClassifier(objective="binary", **param_grid)
        model.fit(
            X_train,
            y_train,
            eval_set=[(X_test, y_test)],
            eval_metric="binary_logloss",
            early_stopping_rounds=100,
            callbacks=[
                LightGBMPruningCallback(trial, "binary_logloss")
            ],
        )
        # 模型预测
        preds = model.predict_proba(X_test)
        # 优化指标logloss最小
        cv_scores[idx] = log_loss(y_test, preds)

    return np.mean(cv_scores)

上記のグリッドでは、データのトレーニング前にあまり良くないハイパーパラメータのセットを検出する便利なクラスも追加し、検索時間を大幅に短縮しましたLightGBMPruningCallbackcallback

目的関数を設定したら、パラメータを調整しましょう。

study = optuna.create_study(direction="minimize", study_name="LGBM Classifier")
func = lambda trial: objective(trial, X, y)
study.optimize(func, n_trials=20)

directionminimizeまたは、最大化maximizeするなどの も可能ですauc理論的にはtrials、回数が多いほど結果は良くなりますが、実行時間も考慮する必要があります。

探索が終わったら呼び出しbest_valuebast_params属性を付けるとパラメータ調整が出てきます。

print(f"\tBest value (rmse): {
      
      study.best_value:.5f}")
print(f"\tBest params:")

for key, value in study.best_params.items():
    print(f"\t\t{
      
      key}: {
      
      value}")
    
-----------------------------------------------------
Best value (binary_logloss): 0.35738
 Best params:
  device: gpu
  lambda_l1: 7.71800699380605e-05
  lambda_l2: 4.17890272377219e-06
  bagging_fraction: 0.7000000000000001
  feature_fraction: 0.4
  bagging_freq: 5
  max_depth: 5
  num_leaves: 1007
  min_data_in_leaf: 45
  min_split_gain: 15.703519227860273
  learning_rate: 0.010784015325759629
  n_estimators: 10000

このパラメーターの組み合わせを取得したら、それを使用してモデルを実行し、結果を確認した後に手動で微調整することができるため、時間を大幅に節約できます。

エピローグ

この記事では、上記のコードに限定されず、データの状況に応じてパラメータの範囲を調整したり、最適化の目標をカスタマイズしたりすることができる、非常に使いやすいパラメータチューニングによるコードフレームワークを提供OptunaますLGBMlogloss

おすすめ

転載: blog.csdn.net/qq_34160248/article/details/132025686