Hyperopt concepts | Databricks on AWS [2022/2/1時点]の翻訳です。
本書は抄訳であり内容の正確性を保証するものではありません。正確な内容に関しては原文を参照ください。
本書では、分散処理でHyperoptを使用する際に理解すべきいくつかのコンセプトを説明します。
DatabricksにおけるHyperoptの使い方を説明しているサンプルについては、Hyperoptによるハイパーパラメーターチューニングをご覧ください。
fmin()
Hyperoptのランを実行するためにfmin()
を使用します。以下の表にfmin()
の引数を示します。詳細に関してはHyperoptのドキュメントを参照ください。それぞれの引数をどのように使うのかのサンプルについては、サンプルノートブックをご覧ください。
引数 | 説明 |
---|---|
fn |
目的関数。Hyperoptは、引数spaceで指定されるハイパーパラメーター空間から生成される値を用いてこの関数を呼び出します。この関数はスカラー値としてのlossや、ディクショナリを返却することができます(詳細に関してはHyperoptのドキュメントを参照ください)。通常、この関数にはモデルトレーニングと損失計算のためのコードが含まれます。 |
space |
探索するハイパーパラメーター空間を定義します。Hyperoptでは、どのようにこの空間を定義するのかに関して、非常に高い柔軟性を提供します。アルゴリズムのようなカテゴリーのオプションや、uniform、logのような数値に対する確率分布を選択することができます。 |
algo |
ハイパーパラメーター空間を探索するために使用するHyperoptの探索アルゴリズムです。最も使用されるのは、ランダムサーチのhyperopt.rand.suggest やTPEのhyperopt.tpe.suggest です。 |
max_evals |
トライするハイパーパラメーターの設定の数(フィッティングするモデルの数)です。 |
max_queue_len | 事前にHyperoptが生成しておくハイパーパラメーター設定の数です。HyperoptのTPEの生成アルゴリズムは時間を要するため、これをデフォルトの1より大きな値に増やしていくことは有用ですが、通常はSparkTrials の設定のparallelism より小さい値にします。 |
trials |
Trials あるいはSparkTrials オブジェクトです。目的変数でscikit-learnメソッドのようなシングルマシンのアルゴリズムを呼び出す際にはSparkTrials を使用します。目的関数でMLlibのメソッドやHorovodのような分散トレーニングアルゴリズムを呼び出す際にはTrials を使用します。 |
early_stop_fn |
max_evals に到達する前にfmin を停止すべきかどうかを決定するオプションの早期停止(early stopping)関数です。デフォルトはNone です。この関数の入力のシグネチャはTrials, *args であり、出力のシグネチャはbool, *args です。出力のブール値は停止すべきかそうでないかを示します。*args は任意のステートであり、early_stop_fn の呼び出し結果は、次の呼び出しの入力となります。Trials はSparkTrials になることもあります。SparkTrials を使う際、それぞれのトライアルの後に早期停止関数が呼び出されることは保証されず、投票されることになります。早期停止関数の例。 |
SparkTrials
クラス
SparkTrials
はDatabricksによって開発されたAPIであり、お使いのHyperoptのコードを変更することなしに、Hyperoptのランを分散させることができます。SparkTrials
はシングルマシンによるチューニングを、Sparkのワーカーに分散させることで高速化を可能にします。
注意
SparkTrials
はscikit-learnのようなシングルマシン向けのMLモデルの計算処理を並列化するために設計されています。MLlibやHorovodのような分散MLアルゴリズムで作成されたモデルに対しては、SparkTrials
を使わないでください。この場合、モデル構築プロセスは自動でクラスター上で並列化されるので、デフォルトのHyperoptのTrials
クラスを使用してください。
このセクションでは、SparkTrials
に渡す引数をどのように設定するのか、SparkTrials
の実装上の側面を説明します。
引数
SparkTrials
は2つのオプションの引数を受け取ります。
-
parallelism
: 同時に評価するトライアルの最大数。値を大きくすることで、より多くのハイパーパラメーター設定のテストにスケールアウトすることができます。Hyperoptは過去の結果に基づいて新たなトライアルを処理するので、並列度と適合度にはトレードオフが存在します。固定のmax_evals
に対しては、並列度を大きくすることで計算速度を高めることができますが、並列度を引き下げることで、それぞれのイテレーションが多くの過去の結果にアクセスできるようになるのでより良い結果につながる場合があります。デフォルト値: 利用可能なSparkエグゼキューターの数。最大: 128。値がクラスター構成で許可される同時実行タスク数を上回った場合、
SparkTrials
は並列度をこの値に削減します。 -
timeout
:fmin()
の呼び出しにかかる最大秒数。この値を超えると、全てのランは停止され、fmin()
は終了します。完了したランの情報は保存されます。
実装
fmin()
に渡される目的関数fn
を定義する際、そして、クラスター構成を選択する際、SparkTrials
がチューニングタスクをどのように分散するのかを理解することは有益です。
Hyperoptにおいては、あるトライアルは通常、1つのハイパーパラメーター設定による1つのモデルのフィッティングに対応します。Hyperoptはトライアルの生成、評価を繰り返します。
SparkTrials
を用いることで、お使いのクラスターのドライバーノードが新たなトライアルを生成し、ワーカーノードがそれらのトライアルを評価します。それぞれのトライアルは1つのタスクを持つSparkジョブとして生成され、ワーカーマシン上のタスクの中で評価されます。クラスターがワーカーごとに複数のタスクを実行できるように設定されている場合には、そのワーカー上で一度に複数のトライアルが評価されます。
SparkTrials
とMLflow
Databricks機械学習ランタイムでは、ワーカーからMLflowへのロギングをサポートしています。Hyperoptに渡す目的関数の中でカスタムのロギングコードを追加することができます。
SparkTrials
は以下のようにネストされたMLflowランとして結果を記録します。
- メインあるいは親のラン:
fmin()
の呼び出しはメインのランとして記録されます。アクティブなランが存在する場合、SparkTrials
はこのアクティブなランを記録し、fmin()
が戻り値を返した際にこの欄を終了させません。アクティブなランが存在しない場合、SparkTrials
が新たなランを作成、記録し、fmin()
が戻り値を返す前にこのランを終了させます。 - 子供のラン: メインのランの下に子供のランとして、テストされたそれぞれのハイパーパラメーターの設定(トライアル)が記録されます。ワーカーからのMLflowログも、対応する子供のランの元に格納されます。
fmin()
を呼び出す際、アクティブなMLflowラン管理を行うことをお勧めします。すなわち、with mlflow.start_run():
ステートメントの中でfmin()
の呼び出しをラップしてください。これによって、それぞれのfmin()
の呼び出しが別々のMLflowメインランに記録されるので、当該ランの追加のタグ、パラメーター、メトリクスの記録が容易となります。
注意
同じアクティブなMLflowランの中で、fmin()
を複数回呼び出す際、MLflowは同じメインランの中にこれらの呼び出しを記録します。記録されたパラメーターやタグの名前の衝突を避けるために、MLflowは衝突する名前にUUIDを追加します。
ワーカーから記録する際、目的関数の中で明示的にランを管理する必要はありません。子供のランにパラメーターを記録するためには、目的関数でmlflow.log_param("param_from_worker", x)
を呼び出してください。目的関数内でパラメーター、メトリクス、タグ、アーティファクトを記録することができます。