機械学習 (15): 高度なハイパーパラメータ調整_ベイジアン最適化 (コード付き)

全文9,000語以上、読了時間目安は約18~30分 | 乾物(コード付き)も充実、コレクションもオススメ!
ここに画像の説明を挿入

データセットとコードのダウンロード アドレス

1. はじめに

ベイジアン最適化手法は、ハイパーパラメーター最適化の分野における最先端技術、State of the Art (SOTA) として認識されています優れた効率とパフォーマンスを示すハイパーパラメータ最適化スキームのほとんどは、ベイズ最適化の概念に基づいて構築されています。

グリッドサーチ、ランダムグリッドサーチ、Halvingグリッドサーチの3つの探索方法において、構築の考え方がどのように変わっても、基本は大きなパラメータ空間内の全点を検証した上で最適な損失関数値に戻すことであり、ランダム化や半分化などの戦略はトレーニング時間を短縮し、大規模なデータと大きなパラメータ空間に適応できますが、これらの方法は効率と精度の点で双方にとって有利な状況を達成することはできません。パラメータ検索をより速く実行し、最適な汎化能力を備えたパラメータを見つけるには、ベイジアン プロセスに基づくパラメータ チューニング ツールなど、アプリオリなプロセスを備えたパラメータ チューニング ツールを使用することをお勧めします。

2. ベイズ最適化の基本概念

2.1 動作原理

ベイジアン最適化の動作原理は次のとおりです。まず目的関数 (通常はガウス過程で表される) の全体的な動作に関する事前知識を確立し、次にさまざまな入力点で目的関数の出力を観察することによってこの事前知識を更新し、事後的に配布されました。事後分布に基づいて、次のサンプリング ポイントが選択されますが、この選択には、以前に観察された最適値 (つまり、利用率) とグローバルな未探索領域 (つまり、探査) の両方を考慮する必要があります。この選択の戦略は、通常、最も一般的に使用される期待改善など、いわゆる取得関数によって定義されます。これにより、ベイジアン最適化は、ハイパーパラメーター空間を効率的に検索できるだけでなく、検索をガイドする既存の知識に基づいて、回避することができます。無駄な試みがたくさん。

ちょっとわかりにくいですか?笑、大丈夫、この記事を読めば簡単に理解できますよ!

ベイズ最適化は非常に強力ですが、全体的な学習の難易度は非常に高くなります。ベイズ最適化をしっかり学びたい場合は、機械学習の主な概念とアルゴリズムを完全に理解し、典型的なハイパーパラメータ最適化プロセスに精通している必要があり、さらに、微積分、確率論、線形代数を超えた数学的知識を習得する必要があります。特に、ベイジアン最適化アルゴリズム自体は、HPO で使用されるベイジアン最適化プロセスとは異なります。

したがって、この記事の焦点は、HPO のベイジアン最適化の中核プロセスをマスターすることです

2.2 関数の最小値を解く考え方

HPO の問題とは関係なく、この例を見てください。

関数f ( x ) f(x)がわかったとします。f ( x )の式とその引数xxxの定義域。xxを解決したいと考えています。xの値の範囲はf ( x ) f(x)f ( x )の最小値、この最小値を解決するにはどうすればよいですか?

この問題に直面すると、通常、次の 3 つの解決策があります。

  1. f ( x ) f(x)の場合f ( x )の導出。その最小値を見つけるためにその一次導関数を 0 とします。

制限: 関数f ( x ) f(x)f ( x )は微分可能であり、微分方程式は直接解くことができます。

  1. 勾配降下法などの最適化手法を反復してf ( x ) f(x)を取得します。f ( x )の最小値

制限: 関数f ( x ) f(x)f ( x )は微分可能であり、関数自体は凸関数です

  1. グローバルxxを変更しますxをf ( x ) f(x)に変換f ( x )は、考えられるすべての結果を計算し、最小値を見つけます。

制限: 関数f ( x ) f(x)f ( x )は比較的単純で、独立変数の次元は比較的低く、計算量は許容できます。

関数f ( x ) f(x)がわかっている場合f ( x )式を使用する場合、上記の方法は多くの場合効果的ですが、各方法には独自の前提条件があります。ここで、関数f ( x ) f(x)があると仮定します。f ( x )は滑らかで一様な関数ですが、非常に複雑で微分不可能であるため、上記の 3 つの方法のいずれでも解くことができません

効果的な解決策は次のとおりです。

ステップ 1: xxでxの領域上で 4 つの点がランダムに選択されf ( x ) f(x)f ( x )が計算されます

いくつかの観測点をランダムにサンプリングして、関数全体の可能な傾向を観測します。

141

ステップ 2: 観測値が 4 つある場合、関数の最小値を見つけるために、関数の全体的な分布を次のように推測できます。

142

ステップ 3: 関数の全体的な分布については人によって異なる推測があり、異なる推測の下での対応する最小値も異なります。

143

ステップ 4: 何万人もの人々が関数の全体的な分布を推測すると仮定します。各人が推測した曲線は次の図に示されています。

145

画像からの解析:観測点(つまり最初に選択した4点)付近では、誰もが推測した関数値に大きな差はありませんが、遠い側の点から離れた場所では関数値が大きく異なります。誰もが推測していることは非常に矛盾しています。**観測点間の関数の分布はまったく不明であるため、分布が観測点から離れるほど、実際の関数値がどこにあるのかが不確かになります。**そのため、人々が推測する関数値の範囲は非常に大きくなります。大きい。

ステップ 5: すべての推測の平均を計算し、任意の平均の周囲の潜在的な関数値の領域をカラー ブロックで表して、全員が推測した平均曲線を取得します。

146

カラーブロックでカバーされる範囲は、ステップ4で数万人が推測した関数値の上限と下限、任意のxxです。xに対応する上限と下限の差が大きければ大きいほど上限と下限の差は、観測点に対する人々の信頼度を測ることができ、カラー ブロックの範囲が広いほど、信頼度は低くなります

ステップ6: 信頼度が非常に低い実際の観測点を追加し、数万人の推測を統合します。**

観測点の周囲では常に信頼度が高く、観測点から離れると常に信頼度が低いため、信頼度の低い区間で実際の観測が行われると、その区間付近の「推測」が一気に集中してしまい、そして、この区間の信頼レベルは大幅に増加します。たとえば、x 6 x_6バツ6そしてx 7 x_7バツ7新たなポイントはこの2点。

147

関数全体の信頼度が非常に高い場合、真のf ( x ) f(x)を含む直線が得られます。f ( x )曲線は、曲線f ∗ f^*f、つまり曲線f ∗ f^*f実数f ( x ) f(x)f ( x )の最小値(実際のf ( x ) f(x) はf ( x )の関数分布

推定値f ∗ f^*がより正確になるf f ( x ) f(x)に近づくほどf ( x )、次にf ∗ f^*fの最小値はf ( x ) f(x)に近くなります。f ( x )の真の最小値。

f∗f^*の作り方f f ( x ) f(x)に近づくf ( x )はどうでしょうか? 先ほどの信頼度を向上させるプロセスによれば、観測点が増えるほど、推定された曲線が実際のf ( x ) f(x)に近づくことは明らかです。f ( x ) . 観測を行うたびに、観測点を慎重に選択する必要があります。

ステップ 7: 適切な方法で観測点を選択する

いろいろな方法がありますが、最も簡単な方法の一つは、最小値の頻度で判断することです。

関数の全体的な分布については人によって推測が異なるため、異なる推測の下での対応する最小値も異なります。各人が推測した関数の結果によると、XXではX軸では、ドメイン間隔を 100 個の小さな間隔に均等に分割し、いずれかの間隔に推定最小値が含まれる場合、その間隔をカウントします。何万人もの人が推測した結果、○○X 軸上のさまざまな間隔の頻度グラフでは、頻度が高くなるほど、間隔内の最小値を推測する人が多くなり、逆も同様で、間隔内の最小値を推測する人が少なくなります頻度は最小値の出現確率をある程度反映しており、頻度間隔が大きいほど関数の真の最小値の確率が高くなります

148

ステップ 8: 次の観測点を決定する

XXはいつですかX軸上の区間が十分に分割された後、描かれた周波数マップは確率密度曲線に変換され、曲線の最大値に対応する点がf ( x ) f(x)になります。f ( x )の最小値の確率がため、曲線の最大値に対応する点が次の観測点として確定されます。

149

画像によると、最小値の最も可能性の高い間隔は x=0.7 付近です。

ステップ 9: このプロセスを継続的に繰り返します

x=0.7 で観測値を取得した後、既知の観測値は 5 つになります。次に、数万人が既知の 5 つの観測点に基づいて全体の関数分布を推測させ、推測が完了した後、現在の最小値の最も高い頻度の区間を計算し、新しい観測点のペア f ( x ) を取得します。 f(x )f ( x )が計算されます。許容される計算数 (たとえば、500) を使い果たすと、推定全体が停止します。

実際、このプロセスでは、目的関数f ( x ) f(x)を常に最適化しています。f ( x )の推定値( f ( x ) f(x)の推定値はありませんf ( x ) はすべての領域で計算を実行しますが、最終的な決定はf ( x ) f(x)でなければならないことがわかりません。f ( x )分布の曲線ですが、観測点が増えるほど関数の推定が正確になるため、f ( x ) f(x)f ( x )の真の最小値この最適化プロセスはベイズ最適化です

150

2.3 HPO のベイジアン最適化プロセス

上記のプロセスをしっかり理解すれば、ベイズ最適化プロセスの定義を簡単に理解できるようになります。

ベイズ最適化の数学的プロセスでは、主に次の手順が実行されます。

  1. 推定関数と領域を定義します。推定されるf ( x ) f(x)を定義します。f ( x )xxxの領域

    f ( x ) f(x)f ( x )

    推定関数f ( x ) f(x)f ( x )はブラックボックス関数です。つまり、xxxf ( x ) f(x)f ( x )の対応関係はありますが、関数の内部法則がまったく分からず、関数のクラスの特定の式を書くことができません。つまり、その明示的な式がまったく取得できないことを意味し、一部の関数は実験や観察によってしか得られない、その時点での関数値。

    x の定義域:

    通常は高次元であり、連続、離散、または混合の可能性があります。

  2. 観察を行う: 限定された n xxを取り出すxの値xxx はf ( x ) f(x)に対応します。f ( x ) (観測値を求める)

    ランダム選択や、何らかの設計 (ラテン超立方体サンプリングなど) による実験など、一部のヒューリスティックを使用して初期点を選択できます。

  3. 関数推定: 限られた観測に基づいて関数を推定し (この仮定はベイズ最適化では事前知識と呼ばれます)、推定値f ∗ f^*を取得します。f目標値(最大値または最小値)

    確率的プロキシ モデル:

    限られた観測値に基づいて関数の分布を推定するツールは、確率サロゲート モデルと呼ばれますが、結局のところ、数学的計算では、観測点を接続するために何万人もの人々を招待することは実際には不可能です。

    これらの確率的代用モデルには特定の仮定があり、目的関数f ∗ f^*の分布はいくつかの観測点に基づいて推定できます。f (f ∗ f^*f各点の値とその点の対応する信頼水準)実際の使用では、確率的プロキシ モデルは強力なアルゴリズムであることが多く、ガウス過程や混合ガウス モデルなどの最も一般的なアルゴリズムです。ガウス プロセスは従来の数学的導出でよく使用されますが、現在最も一般的な最適化ライブラリは基本的に、デフォルトで混合ガウス モデルに基づく TPE プロセスを使用します。たとえば、ガウス プロセスは予測の平均と分散を提供し、予測の不確実性を説明できるため、一般的に使用される方法です。

  4. 次に計算する観測点を決定するための何らかのルールを定義します。

    取得機能:

    次の観測点を決定するときは、通常、取得関数 (取得関数) とも呼ばれるトレードオフ戦略が使用されます。取得関数は、観測点のペア フィッティング f ∗ f^ *を測定します。f発生した衝撃に最も大きな影響を与える点を選択して次の観測ステップを実行するため、取得関数の値が最も大きい点に焦点

    最も一般的な取得関数は、主に確率増分 PI (計算された頻度などの改善の確率)、期待増分 (Expectation Improvement)、信頼上限 (Upper Confidence Bound)、情報エントロピー (エントロピー) などです。予期されるデルタは、ほとんどの最適化ライブラリでデフォルトで使用されます。

  5. モデルと反復の更新: 新しい観測値が取得されると、モデルを更新する必要があり、取得関数が再計算され、次の観測点が再度決定されます。このプロセスは停止条件に達するまで繰り返されます。

151

この画像は、ベイズ最適化のすべての基本要素を示しています。目標は、取得関数の指導の下でf ∗ f^*を実行することです。f f ( x ) f(x)にできるだけ近づけるf ( x ) . 確率プロキシ モデルに従って、推定 f が取得され、f 上の各点と対応する信頼区間が取得されます**

3、ベイズ最適化を実現する方法

3.1 一般的に使用される最適化ライブラリ

ベイズ最適化では、同じ逐次モデルの下で異なるプロキシ モデルと取得関数を使用します (逐次モデルはセクション 2.3 のプロセスであり、逐次モデル最適化 (SMBO) と呼ばれ、最も古典的なベイズ最適化手法です)。より高度なベイズ最適化アルゴリズムを開発できます。したがって、ハイパーパラメータ最適化のためのほとんどすべてのプロフェッショナル ツール ライブラリにはベイジアン最適化が含まれています。

HPO ツールの概要

以下に、一般的に使用されるいくつかのライブラリについて説明します。

152

この記事では主に、エンジニアリングでよく使用される 3 つのライブラリ、bayesian-optimizationhyperopt、を紹介します。optuna

153

3.2 Bayes_opt に基づく GP 最適化

Bayes-optimization は、最も初期のオープンソース ベイズ最適化ライブラリの 1 つです。以前からオープンソース化されており、コードはシンプルですが、これは、bayes-opt でパラメータ空間を処理する比較的原始的な方法にもつながり、対応する効率が欠けています。改善/監視関数: 計算量が多いため、最適化する際に最初に選択するライブラリではないことがよくあります。

Bayes-optmization の公式ドキュメント。その基本的な機能と原則について詳しく知りたい場合は、それを読むことができます。

3.2.1 実際のプロセス

ステップ 1: Bayes_opt ライブラリをインストールする

!pip install bayesian-optimization

画像-20230712122331292

ステップ 2: 関連ライブラリをインポートする

import pandas as pd
import numpy as np

import time
import os 

import sklearn
from sklearn.ensemble import RandomForestRegressor
from sklearn.model_selection import KFold, cross_validate

#优化器
from bayes_opt import BayesianOptimization

ステップ 3: データを読み取る、または Kaggle プラットフォームの住宅価格予測データを使用する

data = pd.read_csv("../datasets/House Price/train_encode.csv",index_col=0)

X = data.iloc[:,:-1]
y = data.iloc[:,-1]

データは次のとおりです。

画像-20230712122719519

ステップ 4: 目的関数を構築する

目的関数の値はf ( x ) f(x)です。f ( x )の値。ベイジアン最適化はf ( x ) f(x)異なるxxでのf ( x )xに関する観測

HPO プロセスでは、モデルの一般化能力を最大化するパラメーターの組み合わせを選択することが目的であるため、f ( x ) f(x)f ( x )は、損失関数またはある種の評価指標の相互検証値である必要があります。

Bayes_opt ライブラリには、目的関数の定義に影響を与える 3 つのルールがあることに注意してください

1. 目的関数の入力は、ハイパーパラメータ空間全体ではなく、ましてやデータやアルゴリズムなどのハイパーパラメータ以外の要素ではなく、特定のハイパーパラメータである必要があるため、目的関数を定義する際には、ハイパーパラメータを目的の入力として使用する必要があります。機能。

2. ハイパーパラメータの入力値は浮動小数点数のみであり、整数と文字列はサポートされていませんアルゴリズムの実パラメータが文字列を入力する必要がある場合、bayes_opt を使用してパラメータを調整することはできません。アルゴリズムの実パラメータが整数を入力する必要がある場合、パラメータの型を目的関数で指定する必要があります。
3. Bayes_opt はf ( x ) f(x)の検索のみをサポートします。f ( x )の最大値は、最小値の検索をサポートしていませんしたがって、定義された目的関数が何らかの損失である場合、目的関数の出力は負である必要があります (つまり、RMSE が使用される場合、目的関数は負の RMSE を出力する必要があります。そのため、負の RMSE を最大化した後、実質 RMSE が最小化されます。)、定義された目的関数が精度、または auc などの指標である場合、目的関数の出力をそのまま維持できます。

def bayesopt_objective(n_estimators,max_depth,max_features,min_impurity_decrease):
    
    #定义评估器
    #需要调整的超参数等于目标函数的输入,不需要调整的超参数则直接等于固定值
    #默认参数输入一定是浮点数,因此需要套上int函数处理成整数
    reg = RandomForestRegressor(n_estimators = int(n_estimators)
              ,max_depth = int(max_depth)
              ,max_features = int(max_features)
              ,min_impurity_decrease = min_impurity_decrease
              ,random_state=24
              ,verbose=False 
              ,n_jobs=-1)
    
    #定义损失的输出,5折交叉验证下的结果,输出负根均方误差(-RMSE)
    #注意,交叉验证需要使用数据,但不能让数据X,y成为目标函数的输入
    cv = KFold(n_splits=5,shuffle=True,random_state=24)
    validation_loss = cross_validate(reg,X,y
                                     ,scoring="neg_root_mean_squared_error"
                                     ,cv=cv
                                     ,verbose=False
                                     ,n_jobs=-1
                                     ,error_score='raise'
                                    )
    
    #交叉验证输出的评估指标是负根均方误差,因此本来就是负的损失
    #目标函数可直接输出该损失的均值
    return np.mean(validation_loss["test_score"])

ステップ 5: パラメータ空間を定義する

Bayes_opt では、パラメータ空間を定義するために辞書が使用されます。パラメータの名前がキーであり、パラメータの値の範囲が値です。

param_grid_opt = {
    
    'n_estimators': (80,100)
                     , 'max_depth':(10,25)
                     , "max_features": (10,20)
                     , "min_impurity_decrease":(0,1)
                    }

操作スキル: Bayes_opt はパラメータ空間の上限と下限の入力のみをサポートし、ステップ サイズなどのパラメータの入力はサポートしません。また、bayes_opt はすべてのパラメータを連続ハイパーパラメータとして扱うため、bayes_opt は浮動パラメータを直接取り出します。閉じた間隔でのポイント。オプションのパラメータとして指定しますたとえば、n_estimators の値として 92.28 を取得します。

ステップ 6: 目的関数を最適化する具体的なプロセスを定義する

目的関数とパラメータ空間を取得した後、bayes_opt のルールに従って最適化できます。

def param_bayes_opt(init_points,n_iter):
    
    #定义优化器,先实例化优化器
    opt = BayesianOptimization(bayesopt_objective #需要优化的目标函数
                               ,param_grid_opt #备选参数空间
                               ,random_state=24 
                              )
    
    #使用优化器,bayes_opt只支持最大化
    opt.maximize(init_points = init_points #抽取多少个初始观测值
                 , n_iter=n_iter #一共观测/迭代多少次
                )
    
    #优化完成,取出最佳参数与最佳分数
    params_best = opt.max["params"]
    score_best = opt.max["target"]
    
    #打印最佳参数与最佳分数
    print("\n","\n","best params: ", params_best,
          "\n","\n","best cvscore: ", score_best)
    
    #返回最佳参数与最佳分数
    return params_best, score_best

ステップ 7: 検証関数を定義する

検証関数は目的関数に非常に似ており、パラメーターまたはハイパーパラメーター空間を入力し、最終的な損失関数の結果を出力します。

def bayes_opt_validation(params_best):
    
    reg = RandomForestRegressor(n_estimators = int(params_best["n_estimators"]) 
              ,max_depth = int(params_best["max_depth"])
              ,max_features = int(params_best["max_features"])
              ,min_impurity_decrease = params_best["min_impurity_decrease"]
              ,random_state=24
              ,verbose=False
              ,n_jobs=-1)

    cv = KFold(n_splits=5,shuffle=True,random_state=1412)
    validation_loss = cross_validate(reg,X,y
                                     ,scoring="neg_root_mean_squared_error"
                                     ,cv=cv
                                     ,verbose=False
                                     ,n_jobs=-1
                                    )
    return np.mean(validation_loss["test_score"])

ステップ 7: 最適化操作を実行する

start = time.time()
#初始看10个观测值,后面迭代290次
params_best, score_best = param_bayes_opt(10,290) 
print('It takes %s minutes' % ((time.time() - start)/60))
validation_score = bayes_opt_validation(params_best)
print("\n","\n","validation_score: ",validation_score)

実行結果を見てください。

画像-20230712132511301

3.2.2 効果比較とメリット・デメリット

グリッド検索効果と比較します。

154

一般的に:原理的に効果が優れている

ガウス過程に基づくベイジアン最適化は、3分3秒以内に最高スコア28373.962を決定し、近い時間で最良の結果を得ることができ、原理的にはその優位性を示しています。

ただし、ベイジアン最適化は毎回ランダムであるため、コードを複数回実行すると 28373.962 の結果を再現することはできず、繰り返し実行した場合、最小値が再び見つかる可能性は低いことに注意してください。

したがって、ベイジアン最適化を実行する場合、多くの場合、モデルによって検出された結果を観察するために数回実行する必要があります。

3.3 HyperOpt に基づく TPE の最適化

Hyperopt オプティマイザーは、現在最も一般的なベイジアン オプティマイザーの 1 つであり、ランダム検索、シミュレーテッド アニーリング、TPE (ツリー構造パルゼン推定アプローチ) などのさまざまな最適化アルゴリズムを統合しています。Bayes_opt と比較すると、Hyperopt はより高度で最新の、より適切に保守されているオプティマイザーであり、TPE メソッドを実装するために最も一般的に使用されるオプティマイザーでもあります。

実際の使用においては、ガウス過程に基づくベイジアン最適化と比較して、ガウス混合モデルに基づく TPE の方が効率よくより良い結果が得られる場合が多く、AutoML の分野でも広く使用されています。

TPEアルゴリズムの原理はこちら

3.3.1 実際のプロセス

ステップ 1: hyperopt ライブラリをインストールする

!pip install hyperopt

画像-20230712133633626

ステップ 2: 関連ライブラリをインポートする

import hyperopt
from hyperopt import hp, fmin, tpe, Trials, partial
from hyperopt.early_stop import no_progress_loss

ステップ 3: データを読み取る、または Kaggle プラットフォームの住宅価格予測データを使用する

data = pd.read_csv("../datasets/House Price/train_encode.csv",index_col=0)

X = data.iloc[:,:-1]
y = data.iloc[:,-1]

ステップ 4: 目的関数を構築する

目的関数f ( x ) f(x)を定義する場合f ( x )の場合、 Bayes_opt と同様に、Hyperopt にも定義を制限するいくつかの特定のルールがあります。主に次のようなものがあります。

1.目的関数の入力は、hyperopt 規則に準拠した辞書である必要があります。

sklearn のようなパラメータ空間辞書、パラメータそのもの、データやアルゴリズムなどのハイパーパラメータ以外の要素であってはなりません。したがって、目的関数をカスタマイズする場合は、目的関数の入力としてハイパーパラメーター空間辞書を使用する必要があります。

2. Hyperopt はf ( x ) f(x)の検索のみをサポートします。f ( x )の最小値は最大値を求めることをサポートしていないため、定義された目的関数が正の評価指標 (正解率、auc など) である場合、評価指標は負である必要があります。定義された目的関数が負の損失である場合、負の損失の絶対値も取得する必要があります。定義された目的関数が通常の損失である場合に限り、出力を変更する必要はありません。

def hyperopt_objective(params):
    
    #定义评估器
    #需要搜索的参数需要从输入的字典中索引出来
    #不需要搜索的参数,可以是设置好的某个值
    #在需要整数的参数前调整参数类型
    reg = RandomForestRegressor(n_estimators = int(params["n_estimators"])
              ,max_depth = int(params["max_depth"])
              ,max_features = int(params["max_features"])
              ,min_impurity_decrease = params["min_impurity_decrease"]
              ,random_state=24
              ,verbose=False
              ,n_jobs=-1)
    
    #交叉验证结果,输出负根均方误差(-RMSE)
    cv = KFold(n_splits=5,shuffle=True,random_state=1412)
    validation_loss = cross_validate(reg,X,y
                                     ,scoring="neg_root_mean_squared_error"
                                     ,cv=cv
                                     ,verbose=False
                                     ,n_jobs=-1
                                     ,error_score='raise'
                                    )
    
    #最终输出结果,由于只能取最小值,所以必须对(-RMSE)求绝对值
    #以求解最小RMSE所对应的参数组合
    return np.mean(abs(validation_loss["test_score"]))

ステップ 5: パラメータ空間を定義する

hyperopt では、特殊な辞書形式を使用してパラメータ空間を定義する必要があります。この空間では、目的関数のインデックス パラメータのキーと一致する限り、キーと値のペアのキーを任意に設定できます。 、キーと値のペアの値は、次のような hyperopt hp 関数に固有です。

hp.quniform("パラメータ名", 下限, 上限, ステップ サイズ) - 一様分布の浮動小数点数に適用します

hp.uniform("パラメータ名", 下限, 上限) - 浮動小数点のランダムな分布に適用します

hp.randint("パラメータ名", 上限) - [0, 上限) に適した整数。間隔はフロントクローズでバックオープンです。

hp.choice("パラメータ名",["文字列1", "文字列2",...]) - 文字列型の場合、最適なパラメータはインデックスで表されます。

hp.choice("パラメータ名",[*range(下限, 上限, ステップサイズ)]) -整数型に適しており、最適なパラメータはインデックスで表されます

hp.choice("パラメータ名", [Integer 1, Integer 2, Integer 3,...]) - 整数型に適しており、最適なパラメータはインデックスで表されます

hp.choice("parameter name",["string1", integer1,...]) - 文字と整数の混合に適しており、最適なパラメータはインデックスによって表されます。

hyperopt のパラメーター空間定義メソッドはすべて、フロントクローズ間隔とバックオープン間隔である必要があります。

param_grid_hp = {
    
    'n_estimators': hp.quniform("n_estimators",80,100,1)
                     , 'max_depth': hp.quniform("max_depth",10,25,1)
                     , "max_features": hp.quniform("max_features",10,20,1)
                     , "min_impurity_decrease":hp.quniform("min_impurity_decrease",0,5,1)
                    }

ステップ 6: 目的関数を最適化する具体的なプロセスを定義する

目的関数とパラメーター空間を使用して、次のステップは最適化です。次のパラメーターを知る必要があります。

  • fmin: カスタム プロキシ モデル (パラメータ)。2つのオプションalgoがあります。前者は TPE メソッドを指し、後者はランダム グリッド検索メソッドを指します。tpe.suggestrand.suggest
  • 部分的: モデルが使用する初期観測値 (パラメータ) の数や、n_start_jobs取得関数の値を計算するときに考慮されるサンプル (パラメータn_EI_candidates)の数など、検出力修正アルゴリズムに関係する特定のパラメータ
  • Trials: 反復プロセス全体、つまり hyperopt ライブラリからインポートされたメソッド Trials() を記録します。最適化が完了した後、保存されたトライアルからの損失やパラメーターなどのさまざまな中間情報を表示できます。
  • early_stop_fn: 早期停止パラメータ、hyperopt ライブラリからインポートされたメソッド no_progress_loss() 。特定の数値 n を入力できます。これは、損失が n 回連続して減少しない場合に、アルゴリズムを早期に停止させることを意味します。
def param_hyperopt(max_evals=100):
    
    #保存迭代过程
    trials = Trials()
    
    #设置提前停止
    early_stop_fn = no_progress_loss(100)
    
    #定义代理模型
    #algo = partial(tpe.suggest, n_startup_jobs=20, n_EI_candidates=50)
    params_best = fmin(hyperopt_objective #目标函数
                       , space = param_grid_hp #参数空间
                       , algo = tpe.suggest #代理模型
                       #, algo = algo
                       , max_evals = max_evals #允许的迭代次数
                       , verbose=True
                       , trials = trials
                       , early_stop_fn = early_stop_fn
                      )
    
    #打印最优参数,fmin会自动打印最佳分数
    print("\n","\n","best params: ", params_best,
          "\n")
    return params_best, trials

ステップ 7: 検証関数を定義する

検証関数は目的関数に非常に似ており、パラメーターまたはハイパーパラメーター空間を入力し、最終的な損失関数の結果を出力します。

def hyperopt_validation(params):    
    reg = RandomForestRegressor(n_estimators = int(params["n_estimators"])
              ,max_depth = int(params["max_depth"])
              ,max_features = int(params["max_features"])
              ,min_impurity_decrease = params["min_impurity_decrease"]
              ,random_state=24
              ,verbose=False
              ,n_jobs=-1
             )
    cv = KFold(n_splits=5,shuffle=True,random_state=24)
    validation_loss = cross_validate(reg,X,y
                                     ,scoring="neg_root_mean_squared_error"
                                     ,cv=cv
                                     ,verbose=False
                                     ,n_jobs=-1
                                    )
    return np.mean(abs(validation_loss["test_score"]))

ステップ 7: 最適化操作を実行する

import time

def optimized_param_search_and_report(num_evals):
    start_time = time.time()

    # 进行贝叶斯优化
    params_best, trials = param_hyperopt(num_evals)

    # 打印最佳参数验证结果
    hyperopt_validation(params_best)

    # 打印所有搜索相关的记录
    print("All search records:")
    print(trials.trials[0])


    end_time = time.time()
    elapsed_time = (end_time - start_time) / 60  # 转换为分钟
    print(f"Optimization completed in 0.0708 minutes.")

# 执行优化
optimized_param_search_and_report(300)

実行結果を見てください。

画像-20230712140814266

3.3.2 効果比較とメリット・デメリット

グリッド検索効果と比較します。

155

一般に、TPE メソッドはガウス プロセス計算よりも高速であり、hyperopt は 1 分未満で最高の包括的な効果を得ることができます。

ただし、HyperOpt の欠点は、コードに高精度が要求され、柔軟性が低いため、わずかな変更によりコードが異常なエラーを報告し、実行が困難になる可能性があることです。

3.4 Optuna に基づく実装

Optuna は、これまでで最も成熟しており、スケーラブルなハイパーパラメータ最適化フレームワークであり、機械学習と深層学習用に特別に設計されています。機械学習開発者のニーズを満たすために、Optuna には強力な固定 API が用意されているため、Optuna コードはシンプルで高度にモジュール化されています。

Optuna は PyTorch や Tensorflow などの深層学習フレームワークとシームレスに接続でき、sklearn の最適化ライブラリ scikit-optimize と組み合わせて使用​​することもできるため、さまざまな最適化シナリオで使用できます。

ここで Optuna の公式ドキュメントを参照してください

3.4.1 実際のプロセス

ステップ 1: hyperopt ライブラリをインストールする

!pip install optuna

画像-20230712141412943

ステップ 2: 関連ライブラリをインポートする

import optuna

ステップ 3: データを読み取る、または Kaggle プラットフォームの住宅価格予測データを使用する

data = pd.read_csv("../datasets/House Price/train_encode.csv",index_col=0)

X = data.iloc[:,:-1]
y = data.iloc[:,-1]

ステップ 4: 目的関数を構築し、パラメーター空間を定義する

Optuna では、パラメータまたはパラメータ空間を目的関数に入力する代わりに、パラメータ空間を目的関数で直接定義する必要がありますOptuna オプティマイザーは、代替パラメーターを参照する変数トライアルを生成します。この変数はユーザーが取得したり開いたりすることはできませんが、この変数はオプティマイザー内に残り、目的関数に入力されます。目的関数では、パラメータ空間は変数トレイルによって実行されるメソッドによって構築できます。

def optuna_objective(trial):
    
    #定义参数空间
    n_estimators = trial.suggest_int("n_estimators",80,100,1) #整数型,(参数名称,下界,上界,步长)
    max_depth = trial.suggest_int("max_depth",10,25,1)
    max_features = trial.suggest_int("max_features",10,20,1)
    min_impurity_decrease = trial.suggest_int("min_impurity_decrease",0,5,1)
    
    #定义评估器
    #需要优化的参数由上述参数空间决定
    #不需要优化的参数则直接填写具体值
    reg = RandomForestRegressor(n_estimators = n_estimators
              ,max_depth = max_depth
              ,max_features = max_features
              ,min_impurity_decrease = min_impurity_decrease
              ,random_state=24
              ,verbose=False
              ,n_jobs=-1
             )
    
    #交叉验证过程,输出负均方根误差(-RMSE)
    #optuna同时支持最大化和最小化,因此如果输出-RMSE,则选择最大化
    #如果选择输出RMSE,则选择最小化
    cv = KFold(n_splits=5,shuffle=True,random_state=24)
    validation_loss = cross_validate(reg,X,y
                                     ,scoring="neg_root_mean_squared_error"
                                     ,cv=cv #交叉验证模式
                                     ,verbose=False #是否打印进程
                                     ,n_jobs=-1 #线程数
                                     ,error_score='raise'
                                    )
    #最终输出RMSE
    return np.mean(abs(validation_loss["test_score"]))

ステップ 5: 目的関数を最適化する具体的なプロセスを定義する

Optuna のモジュール サンプラーでは、TPE 最適化、ランダム グリッド検索、その他のより高度なベイジアン プロセスを含む代替アルゴリズムを定義できます。Optuna.sampler で呼び出されるクラスについては、パラメーターを直接入力して初期の観測数を設定できます。 、取得関数が計算されるたびに考慮される観測値の量。

def optimizer_optuna(n_trials, algo):
    
    #定义使用TPE或者GP
    if algo == "TPE":
        algo = optuna.samplers.TPESampler(n_startup_trials = 15, n_ei_candidates = 20)
    elif algo == "GP":
        from optuna.integration import SkoptSampler
        import skopt
        algo = SkoptSampler(skopt_kwargs={'base_estimator':'GP', #选择高斯过程
                                          'n_initial_points':30, #初始观测点10个
                                          'acq_func':'EI'} #选择的采集函数为EI,期望增量
                           )
    
    #实际优化过程,首先实例化优化器
    study = optuna.create_study(sampler = algo #要使用的具体算法
                                , direction="minimize" #优化的方向,可以填写minimize或maximize
                               )
    #开始优化,n_trials为允许的最大迭代次数
    #由于参数空间已经在目标函数中定义好,因此不需要输入参数空间
    study.optimize(optuna_objective #目标函数
                   , n_trials=n_trials #最大迭代次数(包括最初的观测值的)
                   , show_progress_bar=True #要不要展示进度条呀?
                  )
    
    #可直接从优化好的对象study中调用优化的结果
    #打印最佳参数与最佳损失值
    print("\n","\n","best params: ", study.best_trial.params,
          "\n","\n","best score: ", study.best_trial.values,
          "\n")
    
    return study.best_trial.params, study.best_trial.values

ステップ 6: 最適化操作を実行する

import time

def optimized_optuna_search_and_report(n_trials, algo):
    start_time = time.time()

    # 进行贝叶斯优化
    best_params, best_score = optimizer_optuna(n_trials, algo)

    # 打印最佳参数和分数
    print("\n","\n","best params: ", best_params,
          "\n","\n","best score: ", best_score,
          "\n")

    end_time = time.time()
    elapsed_time = (end_time - start_time) / 60  # 转换为分钟
    print(f"Optimization completed in 0.0708 minutes.")

    return best_params, best_score

# 执行优化
best_params, best_score = optimized_optuna_search_and_report(300, "TPE")

実行結果を見てください。

画像-20230712143547212

3.4.2 効果の比較とメリット・デメリット

グリッド検索効果と比較します。

156

明らかに、短期間で最高の結果が得られます。

誰もが自分でデバッグできます。

4. 結論

この記事では、ハイパーパラメータ最適化の高レベルの内容 (ベイズ最適化の基本原理とプロセス) について説明し、3 つの主流ベイズ最適化ライブラリ (Bayes_opt、HyperOpt、Optuna) の実践的なデモンストレーションを示します。ベイズ最適化の仕組みと、それを使用して関数の最小値を見つける方法、およびハイパーパラメーター最適化タスクでベイズ最適化を実際に適用する方法を学びます。

最後に、この記事を読んでいただきありがとうございます! 何か得をしたと感じたら、ぜひ「いいね!」「ブックマーク」「フォロー」をしてください。これが私が創作を続けるモチベーションです。ご質問やご提案がございましたら、コメント欄にメッセージを残してください。できる限りお答えし、フィードバックを受け付けます。知りたい特定のトピックがございましたら、お知らせください。喜んでそれに関する記事を書きます。ご支援に感謝し、あなたと一緒に成長することを楽しみにしています!

おすすめ

転載: blog.csdn.net/Lvbaby_/article/details/131681795