Hyperopt を使ってハイパーパラメーターを最適化する
Hyperopt は、ハイパーパラメーター調整用のオープンソース Python ライブラリです。 Databricks Runtime の ML バリアントを使ってクラスターを作成すると、Hyperopt が自動的にインストールされます。 モデルの調整時にこれを使うには、次の手順に従います。
- モデルをトレーニングおよび評価する "目的" 関数を定義します。
- ハイパーパラメーター検索空間を定義します。
- 検索アルゴリズムを指定します。
- Hyperopt fmin 関数を実行して、トレーニング関数を最適化します。
目的関数を定義する
Hyperopt は、数値を返す関数 (多くの場合、"目的" 関数と呼ばれます) を繰り返し呼び出し、関数に渡されるパラメーターを戻り値が最小になるように調整することで機能します。これは、一般的に "最適化" と呼ばれるアプローチです。 そのため、最初の要件は、モデルのトレーニングと評価ロジックを、次のような関数にカプセル化することです。
- ハイパーパラメーター値のリストを含むパラメーターを指定できる。
- 指定されたハイパーパラメーター値を使ってモデルをトレーニングする。
- 予測パフォーマンスのターゲット メトリックに基づいてモデルを評価する。
- モデルのパフォーマンスが向上すると戻り値が "小さくなる" ように、パフォーマンス メトリックが反映された数値を返す。
たとえば、次の関数では、Spark MLlib ライブラリの LogisticRegression アルゴリズムを使って機械学習モデルをトレーニングします。
def objective(params):
from pyspark.ml.classification import LogisticRegression
from pyspark.ml.evaluation import MulticlassClassificationEvaluator
from hyperopt import STATUS_OK
data_df = get_training_data() # This is just an example!
splits = data_df.randomSplit([0.7, 0.3])
training_df = splits[0]
validation_df = splits[1]
# Train a model using the provided hyperparameter values
lr = LogisticRegression(labelCol="label", featuresCol="features",
maxIter=params['Iterations'],
regParam=params['Regularization'])
model = lr.fit(training_df)
# Evaluate the model
predictions = model.transform(validation_df)
eval = MulticlassClassificationEvaluator(labelCol="label",
predictionCol="prediction",
metricName="accuracy")
accuracy = eval.evaluate(predictions)
# Hyperopt *minimizes* the function, so return *negative* accuracy.
return {'loss': -accuracy, 'status': STATUS_OK}
この例では、params パラメーターは、2 つの名前付き値の値を含むディクショナリです。反復と正則化。 これらの値は、モデルのトレーニングに使われるロジスティック回帰アルゴリズムの maxIter および regParam ハイパーパラメーターに代入されます。
次に、この関数ではトレーニング済みモデルを評価して、その accuracy メトリックを計算します。これは、モデルが行った予測のうち正しかったものの割合を示す 0.0 から 1.0 の間の値です。
最後に、この関数は、モデルを改善するために Hyperopt が最小限に抑える必要がある値を返します。 この場合、ターゲット メトリックは accuracy であり、その値が大きいほどモデルが優れていることを示します。したがって、関数はこの値の "負" の値を返します (そのため、精度が高いほど戻り値は小さくなります)。
ハイパーパラメーター検索空間を定義する
目的関数を呼び出すたびに、試行するハイパーパラメーター値を含むパラメーターが必要になります。 使用可能なすべての値の組み合わせを試すには、各評価版の値を選択する Hyperopt の検索領域を定義する必要があります。
Hyperopt には、次のような、各ハイパーパラメーターの値の範囲を定義するために使用できる式が用意されています。
hp.choice(label, options)
: 列挙したoptions
のいずれかが返されます。hp.randint(label, upper)
: [0, upper] の範囲内のランダムな整数が返されます。hp.uniform(label, low, high)
:low
とhigh
の間の値が一様に返されます。hp.normal(label, mu, sigma)
: 平均mu
と標準偏差sigma
で正規分布した実数値が返されます。
ヒント
式の完全な一覧については、Hyperopt のドキュメントをご覧ください。
次のコード例では、前の例で使用されるハイパーパラメーター用の検索空間を定義しています。
from hyperopt import hp
search_space = {
'Iterations': hp.randint('Iterations', 10),
'Regularization': hp.uniform('Regularization', 0.0, 1.0)
}
検索アルゴリズムを指定する
Hyperopt は、検索アルゴリズムを使って検索空間からハイパーパラメーター値を選択し、目的関数の最適化を試みます。 検索空間での Hyperopt によるサンプリング方法には、主に次の 2 つの選択肢があります。
hyperopt.tpe.suggest
: Tree of Parzen Estimators (TPE)。過去の結果に基づいて新しいハイパーパラメーターの設定をアダプティブに選択するベイズ的アプローチです。hyperopt.rand.suggest
: ランダム検索。検索空間をランダムにサンプリングする非アダプティブ アプローチです。
次のコード例では、TPE アルゴリズムを指定しています。
from hyperopt import tpe
algo = tpe.suggest
Hyperopt fmin 関数を実行する
最後に、Hyperopt を実行するには、fmin 関数を使用できます。これは、検索アルゴリズムに基づく検索空間からのハイパーパラメーターの組み合わせを使って、目的関数を繰り返し呼び出します。 fmin 関数の目的は、目的関数から返される値を最小限に抑える (したがって、モデルのパフォーマンスを最適化する) ことです。
次のコード例では、fmin 関数を使って、前に定義した objective 関数を呼び出します。 前の例で定義した検索空間とアルゴリズムが使われ、関数は、fmin 関数が見つかった最もパフォーマンスの高いパラメーター値の組み合わせを返すまで、最大 100 回評価されます。
from hyperopt import fmin
argmin = fmin(
fn=objective,
space=search_space,
algo=algo,
max_evals=100)
print("Best param values: ", argmin)
上記のコードからの出力は、次の例のようになります。
Best param values: {'Iterations': 6, 'Regularization': 0.5461699702338606}