MENU

    LightGBM で Optunaを使うためのハイパーパラメータを理解する。(備忘録)

    LightGBMの精度をあげるためには、ハイパーパラメータのチューニングを行う必要があります。

    しかし、LightGBMのパラーメータ数は非常に多く、自分のような初心者が調節するのは非常に困難です。

    今回はOptunaを使用して、ハイパーパラメータのチューニングを行う過程で、ハイパーパラメータの意味を理解していきます。

    目次

    LightGBMの公式ドキュメント

    「まずは、公式ドキュメントをよめ。」と言われますが、パラメーターの数の多さにびびります。
    公式ドキュメントを参照しながら、進めていきます。

    ・LightGBMの公式ドキュメント
    https://lightgbm.readthedocs.io/en/stable/index.html

    ・Optunaの公式ドキュメント
    https://optuna.readthedocs.io/en/stable/index.html

    Optunaによるハイパーパラメータのチューニングのコード例

    # 固定するパラメータ
    fixed_params = {
        'objective': 'binary',
        'metric': 'auc',
        'boosting_type': 'gbdt',
        'verbosity': -1,
        'random_state': 42,
        'num_threads': 1
    }
    
    # optunaで探索するパラメータ
    def objective(trial):
      params = {
          'learning_rate': trial.suggest_float('learning_rate', 0.01, 0.2, log=True),
          'num_leaves': trial.suggest_int('num_leaves', 31, 255),
          'max_depth': trial.suggest_int('max_depth', 5, 20),
          'min_data_in_leaf': trial.suggest_int('min_data_in_leaf', 20, 100),
          'bagging_fraction': trial.suggest_float('bagging_fraction', 0.6, 1.0),
          'feature_fraction': trial.suggest_float('feature_fraction', 0.6, 1.0),
          'lambda_l1': trial.suggest_float('lambda_l1', 0.0, 10.0),
          'lambda_l2': trial.suggest_float('lambda_l2', 0.0, 10.0),
      }
    
     # パラメータの更新
      params.update(fixed_params)
    
     # Dataset形式に変換
      train_data = lgb.Dataset(X_train, label=y_train, categorical_feature=categorical_features)
      valid_data = lgb.Dataset(X_valid, label=y_valid, categorical_feature=categorical_features)
    
     # モデルの学習
      model = lgb.train(
          params,
          train_data,
          valid_sets=[valid_data],
          num_boost_round=1000,
          callbacks = [early_stopping(stopping_rounds=50), log_evaluation(period=100)])
     # AUCスコアの表示
      y_pred = model.predict(X_valid, num_iteration=model.best_iteration)
      auc = roc_auc_score(y_valid, y_pred)
      return auc
    
    # Optunaで最適化
    study = optuna.create_study(direction='maximize')
    study.optimize(objective, n_trials=30)
    
    print('Best AUC:',study.best_value)
    print('Best Parameters:')
    for k, v in study.best_params.items():
        print(f"  {k}: {v}")
    
    # 最適パラメータ保存
    best_params = fixed_params.copy()
    best_params.update(study.best_params)

    固定するパラメータの詳細

    fixed_params = {
        'objective': 'binary',
        'metric': 'auc',
        'boosting_type': 'gbdt',
        'verbosity': -1,
        'random_state': 42,
        'num_threads': -1
    }

    固定するパラメータについてそれぞれ公式ドキュメントをみていきます。

    objective

    objective 🔗︎, default = regression, type = enum, options: regressionregression_l1huberfairpoissonquantilemapegammatweediebinarymulticlassmulticlassovacross_entropycross_entropy_lambdalambdarankrank_xendcg, aliases: objective_typeappapplicationloss

    https://lightgbm.readthedocs.io/en/stable/Parameters.html#

    意味:目的関数(損失関数)を指定。

    デフォルトは’regression'(回帰)。

    ・2クラス分類→’binary’
    ・多クラス分類→’multiclass’

    metric

    metric 🔗︎, default = "", type = multi-enum, aliases: metricsmetric_types

    • metric(s) to be evaluated on the evaluation set(s)
    https://lightgbm.readthedocs.io/en/stable/Parameters.html#

    意味:モデル評価指標を指定。

    デフォルトは””。LightGBMがタスクに応じて選択する。

    objective=’binary’の場合は、binary_loglossが自動的に選択される。

    ・ROC曲線の面積→’auc’
    ・2値分類の損失関数→’binary_logloss’

    *損失関数:確率が正解から遠いほど大きなペナルティを与える。分類結果そのものより、予測確率の信頼性を重視したいときに有効。

    boosting_type

    • boosting🔗︎, default = gbdt, type = enum, options: gbdtrfdart, aliases: boosting_typeboost
      • gbdt, traditional Gradient Boosting Decision Tree, aliases: gbrt
      • rf, Random Forest, aliases: random_forest
      • dartDropouts meet Multiple Additive Regression Trees
        • Note: internally, LightGBM uses gbdt mode for the first 1 / learning_rate iterations
    https://lightgbm.readthedocs.io/en/stable/Parameters.html#

    意味:ブースティングのアルゴリズム種類を指定。

    デフォルトは’gbdt’。基本はgbdtでおk

    ・’gbdt’:Gradient-based One-Side Sampling(一般的な勾配ブースティング)
    ・’dart’:Dropouts meet Multiple Additive Regression Trees(過学習に強い)
    ・’goss’:Gradient-based One-Side Sampling(高速な勾配計算)。

    verbosity

    • verbosity🔗︎, default = 1, type = int, aliases: verbose
      • controls the level of LightGBM’s verbosity
      • < 0: Fatal, = 0: Error (Warning), = 1: Info, > 1: Debug
    https://lightgbm.readthedocs.io/en/stable/Parameters.html#

    意味:ログ出力の詳細レベル。

    デフォルトは1。

    ・<0 :致命的なエラーだけ表示
    ・=0 :エラーや警告だけ表示
    ・=1 :進捗などの通常の情報も表示
    ・>1 :デバッグ情報まで詳しく表示

    num_threads

    • num_threads🔗︎, default = 0, type = int, aliases: num_threadnthreadnthreadsn_jobs
      • used only in trainprediction and refit tasks or in correspondent functions of language-specific packages
      • number of threads for LightGBM
      • 0 means default number of threads in OpenMP
      • for the best speed, set this to the number of real CPU cores, not the number of threads (most CPUs use hyper-threading to generate 2 threads per CPU core)
      • do not set it too large if your dataset is small (for instance, do not use 64 threads for a dataset with 10,000 rows)
      • be aware a task manager or any similar CPU monitoring tool might report that cores not being fully utilized. This is normal
      • for distributed learning, do not use all CPU cores because this will cause poor performance for the network communication
      • Note: please don’t change this during training, especially when running multiple jobs simultaneously by external packages, otherwise it may cause undesirable errors
    https://lightgbm.readthedocs.io/en/stable/Parameters.html#

    意味:LightGBM が トレーニング・予測・再学習時に使うスレッド数(CPUの並列処理の数)

    デフォルトは0。OpenMP(内部ライブラリ)に任せる(自動でコア数を判断)。

    Optunaで探索するパラメータの詳細

    # optunaで探索するパラメータ
    def objective(trial):
      params = {
          'learning_rate': trial.suggest_float('learning_rate', 0.01, 0.2, log=True),
          'num_leaves': trial.suggest_int('num_leaves', 31, 255),
          'max_depth': trial.suggest_int('max_depth', 5, 20),
          'min_data_in_leaf': trial.suggest_int('min_data_in_leaf', 20, 100),
          'bagging_fraction': trial.suggest_float('bagging_fraction', 0.6, 1.0),
          'feature_fraction': trial.suggest_float('feature_fraction', 0.6, 1.0),
          'lambda_l1': trial.suggest_float('lambda_l1', 0.0, 10.0),
          'lambda_l2': trial.suggest_float('lambda_l2', 0.0, 10.0),
      }

    Optunaで探索するパラメータをみていく。

    Optunaのtrial.suggest()メソッド

    suggest_categorical()Suggest a value for the categorical parameter.
    suggest_discrete_uniform(name, low, high, q)Suggest a value for the discrete parameter.
    suggest_float(name, low, high, *[, step, log])Suggest a value for the floating point parameter.
    suggest_int(name, low, high, *[, step, log])Suggest a value for the integer parameter.
    suggest_loguniform(name, low, high)Suggest a value for the continuous parameter.
    suggest_uniform(name, low, high)Suggest a value for the continuous parameter.
    https://optuna.readthedocs.io/en/stable/reference/generated/optuna.trial.Trial.html#optuna.trial.Trial

    各メソッドは、探索すべきハイパーパラメータの「候補値」をOptuna に提案させます。
    指定した範囲や条件に従って、Optunaが自動的に探索していきます。

    ・suggest_int(name, low, high) :整数値を範囲内から提案
    ・suggest_float(name, low, high, log=False):連続値を範囲内から提案(log=Trueで対数スケール)
    ・suggest_categorical(name, choices):カテゴリ変数をリストから提案

    learning_rate

    • learning_rate🔗︎, default = 0.1, type = double, aliases: shrinkage_rateeta, constraints: learning_rate > 0.0
      • shrinkage rate
      • in dart, it also affects on normalization weights of dropped trees
    https://lightgbm.readthedocs.io/en/stable/Parameters.html#

    意味:学習の一回ごとの更新のステップサイズを決めるパラメータ。
    学習率」または「縮小率」とも呼ばれます。

    LightGBMでは、各ラウンド(木を1本追加)ごとに予測を更新していきますが、

    新しい予測=前の予測+learning_rate×新しい木の予測

    のように、新しい木の寄与を弱めて、少しずつ学習する仕組みです。

    デフォルトは0.1。

    低いと精度は上がりやすいが時間がかかる。高いと早く収束するが過学習リスクあり。

    num_leaves

    • num_leaves🔗︎, default = 31, type = int, aliases: num_leafmax_leavesmax_leafmax_leaf_nodes, constraints: 1 < num_leaves <= 131072
      • max number of leaves in one tree
    https://lightgbm.readthedocs.io/en/stable/Parameters.html#

    意味:1本の決定木(tree)で使える「最大の葉の数」を指定します。

    葉とは?
    決定木における「分岐の終点」。
    分類や回帰の最終的な出力が決まる場所
    木の構造において、葉の数が多いほど 複雑な表現が可能(=精度が上がる可能性)。

    デフォルトは31。

    ・精度を高めたい→num_leavesを大きくする
    ・過学習を防ぐ→num_leavesを小さくする

    max_depth

    • max_depth🔗︎, default = -1, type = int
      • limit the max depth for tree model. This is used to deal with over-fitting when #data is small. Tree still grows leaf-wise
      • <= 0 means no limit
    https://lightgbm.readthedocs.io/en/stable/Parameters.html#

    意味:決定木が「どこまで深く分岐できるか(=分割できるか)」を制限するパラメータです。
    深くなるほど複雑なモデルになります。

    デフォルトは-1。深さの制限なし。

    パラメータ意味効果
    num_leaves葉の最大数モデルの複雑さを制御する主パラメータ
    max_depth深さの上限構造上の過学習制御に使う補助的パラメータ

    num_leaves をメインにチューニングしつつ、必要なら max_depthを組み合わせるのが一般的。

    min_data_in_leaf

    • min_data_in_leaf🔗︎, default = 20, type = int, aliases: min_data_per_leafmin_datamin_child_samplesmin_samples_leaf, constraints: min_data_in_leaf >= 0
      • minimal number of data in one leaf. Can be used to deal with over-fitting
      • Note: this is an approximation based on the Hessian, so occasionally you may observe splits which produce leaf nodes that have less than this many observations
    https://lightgbm.readthedocs.io/en/stable/Parameters.html#

    意味:1つの葉(leaf)に含めることができる 最小のデータ数 を指定します。

    何を制御しているか?

    決定木を分割する際に、「この分割をしたら、どちらかの葉にデータ数が少なすぎる」というのを防ぎます。
    葉に十分なデータがあるときだけ、分割を許して、過学習を防止します。

    デフォルトは20。データ量によって調整する。

    bagging_fraction

    • bagging_fraction🔗︎, default = 1.0, type = double, aliases: sub_rowsubsamplebagging, constraints: 0.0 < bagging_fraction <= 1.0
      • like feature_fraction, but this will randomly select part of data without resampling
      • can be used to speed up training
      • can be used to deal with over-fitting
      • Note: to enable bagging, bagging_freq should be set to a non zero value as well
    https://lightgbm.readthedocs.io/en/stable/Parameters.html

    意味各決定木の学習に使うデータの割合(レコード数の比率)を指定するパラメータ

    デフォルトは1.0。

    何をするのか?

    学習時に、全データからランダムに一部だけ使うようにすることで:

    • 学習を速くする
    • 過学習(overfitting)を防ぐ

    feature_fraction

    • feature_fraction🔗︎, default = 1.0, type = double, aliases: sub_featurecolsample_bytree, constraints: 0.0 < feature_fraction <= 1.0
      • LightGBM will randomly select a subset of features on each iteration (tree) if feature_fraction is smaller than 1.0. For example, if you set it to 0.8, LightGBM will select 80% of features before training each tree
      • can be used to speed up training
      • can be used to deal with over-fitting
    https://lightgbm.readthedocs.io/en/stable/Parameters.html

    意味:各決定木の学習に使う特徴量数の割合を指定するためのパラメータ

    デフォルトは1.0。

    何をしているか?

    ・デフォルト(1.0)だと、全ての特徴量を使って木を構築します。
    feature_fraction < 1.0 に設定すると、各木ごとにランダムで一部の特徴量だけを使うようになります。

    lambda_l1

    • lambda_l1🔗︎, default = 0.0, type = double, aliases: reg_alphal1_regularization, constraints: lambda_l1 >= 0.0
      • L1 regularization
    https://lightgbm.readthedocs.io/en/stable/Parameters.html

    意味:葉の重みに対するL1正則化の強さを制御するパラメータ

    デフォルトは0.0。

    lambda_l2

    • lambda_l2🔗︎, default = 0.0, type = double, aliases: reg_lambdalambdal2_regularization, constraints: lambda_l2 >= 0.0
      • L2 regularization
    https://lightgbm.readthedocs.io/en/stable/Parameters.html

    意味:葉の重みに対するL2正則化の強さを制御するパラメータ

    デフォルトは0.0。

    Optunaで最適化するためのパラメータ

    # Optunaで最適化
    study = optuna.create_study(direction='maximize')
    study.optimize(objective, n_trials=30)

    optuna.study.create_study()

    optuna.study.create_study(*storage=Nonesampler=Nonepruner=Nonestudy_name=Nonedirection=Noneload_if_exists=Falsedirections=None)[source]

    https://optuna.readthedocs.io/en/stable/reference/generated/optuna.study.create_study.html#optuna.study.create_study

    新しい最適化studyを作るための関数。
    Optuna のハイパーパラメータ探索の土台になります。

    direction

    • direction (str | StudyDirection | None) –Direction of optimization. Set minimize for minimization and maximize for maximization. You can also pass the corresponding StudyDirection object. direction and directions must not be specified at the same time.NoteIf none of direction and directions are specified, the direction of the study is set to “minimize”.
    https://optuna.readthedocs.io/en/stable/reference/generated/optuna.study.create_study.html#optuna.study.create_study

    意味:どの方向に目的関数(objective)を最適化するかを指定するもの。

    デフォルトは’minimize’。

    ・minimize:値をできるだけ小さくしたい(損失関数、エラーなど)
    ・maximize:値をできるだけ大きくしたい(精度、AUC、スコアなど)

    optimize()

    optimize(funcn_trials=Nonetimeout=Nonen_jobs=1catch=()callbacks=Nonegc_after_trial=Falseshow_progress_bar=False)[source]

    Optimize an objective function.

    Optimization is done by choosing a suitable set of hyperparameter values from a given range. Uses a sampler which implements the task of value suggestion based on a specified distribution. The sampler is specified in create_study() and the default choice for the sampler is TPE. See also TPESampler for more details on ‘TPE’.

    Optimization will be stopped when receiving a termination signal such as SIGINT and SIGTERM. Unlike other signals, a trial is automatically and cleanly failed when receiving SIGINT (Ctrl+C). If n_jobs is greater than one or if another signal than SIGINT is used, the interrupted trial state won’t be properly updated.

    指定した範囲からハイパーパラメータの組み合わせを選び、目的関数(objective)の最適値を探索する関数。

    最適なパラメータを自動で見つける仕組みです。

    n_trials

    • n_trials (int | None) –The number of trials for each process. None represents no limit in terms of the number of trials. The study continues to create trials until the number of trials reaches n_trialstimeout period elapses, stop() is called, or a termination signal such as SIGTERM or Ctrl+C is received.See alsooptuna.study.MaxTrialsCallback can ensure how many times trials will be performed across all processes.

    意味:目的関数(objective)を 何回繰り返して最適化を行うか を決める引数です。

    デフォルトはNone。回数制限なしで最適化を継続する。

    (スポンサーリンク)

    よかったらシェアしてね!
    • URLをコピーしました!
    • URLをコピーしました!

    コメント

    コメントする

    日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)

    目次