AccuracyBasedSurrogateSwitcher#

Layer 3: Extend Components

サロゲートの精度に応じて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つです。

クラス

範囲

意味

SpearmanCorrelation

[-1, 1]、高いほど良い

目的ごとのSpearman順位相関の平均。EAではランクの保存性が重要という観点[33]に基づく

RMSE

[0, ∞)、低いほど良い

二乗平均平方根誤差

R2Score

(-∞, 1]、高いほど良い

決定係数

AccuracyEvaluatorのコンストラクタでmetricsを省略すると、この3指標全てが既定として使われます。

精度評価方法:AccuracyEvaluator#

AccuracyEvaluatorが実装を要求するのはevaluate(surrogate, train_x, train_y) -> SurrogateAccuracyの1つだけです。

クラス

パラメータ

評価方法

KFoldAccuracyEvaluator

metrics=None, n_splits=5

サロゲートをfoldごとに複製して再学習するk分割交差検証

LOOAccuracyEvaluator

metrics=None

n_splits=n_samplesのKFoldAccuracyEvaluatorと等価(1件抜き交差検証)

HeldOutAccuracyEvaluator

held_x, held_y, metrics=None

既に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

primary, fallback, *, metric="spearman", threshold=0.5

SurrogateManager

StrategySwitcher

primary, fallback, *, metric="spearman", threshold=0.56

OptimizationStrategy

GenCtrlSwitcher

*, gm_max=5, gm_min=0, update_rate=0.5, metric="spearman", initial_error=0.5

gen_ctrl(整数)

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が切り替える対象

参照#