AccuracyBasedSurrogateSwitcher#
サロゲートの精度に応じてSurrogateManagerやOptimizationStrategyを動的に切り替える仕組みは、3つの独立した関心事の組み合わせでできています。
精度指標(
SurrogateAccuracyMetric):1回のfit/predictペアからスカラー値を計算する精度評価方法(
AccuracyEvaluator):精度指標を使って、サロゲートの汎化性能をどう測るか(交差検証、held-outなど)を決める切り替え判断(
AccuracyBasedSurrogateSwitcher):評価結果を受けて、次に使うコンポーネントやパラメータを決める
精度評価方法はGlobalSurrogateManagerなどのaccuracy_evaluator引数として注入され、その結果はsurrogate_manager.last_accuracyプロパティを経由して切り替え判断へ渡されます。 この一連の仕組みはiterate()ループでの利用を前提としています。 高レベルAPI(minimize/maximize)は実行中のコンポーネント差し替え手段を提供しないため、これらのSwitcherは使えません。
SurrogateSwitcherの役割#
この仕組みは、精度指標、精度評価、切り替え判断を分離して組み合わせ、次に使うSurrogateManagerまたはOptimizationStrategyの構成を決めます。
精度指標:SurrogateAccuracyMetric#
SurrogateAccuracyMetricが実装を要求するのはname(プロパティ)とcompute(y_true, y_pred) -> floatの2つです。
クラス |
範囲 |
意味 |
|---|---|---|
|
|
目的ごとのSpearman順位相関の平均。EAではランクの保存性が重要という観点[33]に基づく |
|
|
二乗平均平方根誤差 |
|
|
決定係数 |
AccuracyEvaluatorのコンストラクタでmetricsを省略すると、この3指標全てが既定として使われます。
精度評価方法:AccuracyEvaluator#
AccuracyEvaluatorが実装を要求するのはevaluate(surrogate, train_x, train_y) -> SurrogateAccuracyの1つだけです。
クラス |
パラメータ |
評価方法 |
|---|---|---|
|
|
サロゲートをfoldごとに複製して再学習するk分割交差検証 |
|
|
|
|
|
既にfit済みのサロゲートを再学習せず、指定したheld-outデータで評価する |
HeldOutAccuracyEvaluatorは、直近の真の評価点との比較用途[34]で使います。
SurrogateAccuracy(metrics: dict[str, float], n_samples: int)は、評価結果を保持する単純なコンテナで、get(name, default=nan)で指標名から値を取り出します。
切り替え判断:AccuracyBasedSurrogateSwitcher#
AccuracyBasedSurrogateSwitcherが実装する必要があるメソッドはswitch(accuracy: SurrogateAccuracy | None) -> Tの1つだけです。精度結果から次のコンポーネントまたはパラメータを選びます。その選択をRuntimeの計画へ適用する操作は別です。
次の例では、iterate()とoptimizer.set_*()で構成を変更します。実行環境が変更を検出して計画を再コンパイルし、次の世代から変更を適用します。この手順は、反復中に構成を変更する他のケースにも使えます。
switcher = ManagerSwitcher(primary, fallback)
for ctx in optimizer.iterate():
optimizer.set_surrogate_manager(
switcher.switch(optimizer.surrogate_manager.last_accuracy)
)
クラス |
パラメータ |
切り替える対象 |
|---|---|---|
|
|
|
|
|
|
|
|
|
ManagerSwitcher/StrategySwitcherは、指定した指標が閾値以上ならprimary、そうでなければfallbackを返す単純な二値切り替えです。 StrategySwitcherの既定閾値0.56は、[34]によるPS/IB-GB切り替えの設定値に基づきます。
GenCtrlSwitcherは、二値切り替えではなくgen_ctrlを指数平滑化で連続的に調整します[35]。 公開属性smoothed_errorに平滑化済みの誤差推定値を保持する状態を持つため、1回のrunにつき1つのインスタンスを使います。 GenCtrlSwitcher.switch()が返すintは、そのままGenerationBasedStrategyのgen_ctrl引数に渡す想定です。
コンポーネント側から再コンパイルを要求する経路については、OptimizationStrategyの「ランタイム差し替えの動作」を参照してください。
独自Switcherの実装方法#
独自の切り替えロジックが必要な場合は、AccuracyBasedSurrogateSwitcherを継承してswitch()だけを実装すればよいです。
from saealib import AccuracyBasedSurrogateSwitcher
class ThresholdIntSwitcher(AccuracyBasedSurrogateSwitcher):
"""A custom integer-parameter switch: increase n_neighbors if the Spearman correlation is at or above 0.7."""
def switch(self, accuracy):
if accuracy is None:
return 20
return 50 if accuracy.get("spearman") >= 0.7 else 20
関連コンポーネント#
SurrogateManager:
accuracy_evaluator引数とlast_accuracyプロパティstrategies:
StrategySwitcher/GenCtrlSwitcherが切り替える対象