Mímisbrunnr知恵の泉

← MLOps 一覧

🎓 レベル:標準 | 重要度:B(推奨)

📎 前提:実験トラッキング | 関連:ハイパーパラメータ最適化(機械学習)

要点(BLUF)

1. HPO の運用で何を管理するのか

機械学習の授業では「ベイズ最適化が効率的」といったアルゴリズムを学びます。MLOps で問うのは別のことです:その探索を、後から再現でき、コストを管理でき、最良構成を確実にデプロイできるか。管理対象は3つ——探索空間(設定)・各試行の記録・最良構成の再現性です。

2. 探索空間を設定として宣言する

ハイパーパラメータをコードに埋め込むと、探索のたびにコードを書き換えることになり、版管理も再現もできません。設定ファイルに外出しします。

# hpo_config.yaml — 探索空間の宣言
model: GradientBoosting
search:
  n_estimators: [50, 100, 200]
  max_depth: [2, 3, 4]
  learning_rate: [0.05, 0.1]
strategy: grid          # grid | random | bayesian
metric: f1
early_stopping:
  enabled: true
  min_metric: 0.80      # この水準に届かない枝は早期に打ち切り

この YAML を版管理すれば、「どの探索空間で実験したか」が記録され、同じ探索を再実行できます。

3. 図解:HPO の運用フロー

flowchart LR
  C["探索空間(設定ファイル)"] --> G["試行を生成"]
  G --> T["各試行を学習・評価"]
  T --> L["トラッキングにrun記録(params metrics 出自)"]
  L --> E{"早期終了の判定"}
  E -->|"見込みなし"| X["打ち切り"]
  E -->|"継続"| G
  L --> B["最良構成を選択 -> 出自つきで再現"]

4. 動く最小例:グリッド探索を記録・再現する

設定の探索空間でグリッド探索し、各試行を記録、最良構成を出自つきで再現します。

import itertools
import numpy as np
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.metrics import f1_score

rng = np.random.default_rng(0)
X = rng.normal(0, 1, (600, 6))
y = (X[:, 0] + X[:, 1] - X[:, 2] + 0.4 * rng.normal(size=600) > 0).astype(int)
k = int(len(y) * 0.8)
Xtr, Xval, ytr, yval = X[:k], X[k:], y[:k], y[k:]

# 設定ファイル相当(本来はYAMLから読む)
space = {"n_estimators": [50, 100], "max_depth": [2, 3], "learning_rate": [0.05, 0.1]}
trials = []
for ne, md, lr in itertools.product(*space.values()):
    params = {"n_estimators": ne, "max_depth": md, "learning_rate": lr, "random_state": 0}
    model = GradientBoostingClassifier(**params).fit(Xtr, ytr)
    f1 = f1_score(yval, model.predict(Xval))
    trials.append({"params": params, "f1": round(float(f1), 4)})

best = max(trials, key=lambda t: t["f1"])
print(f"試行数 : {len(trials)}")
print(f"最良 f1 : {best['f1']}")
print(f"最良構成 : {best['params']}")

# 再現:最良構成を同じseedで再学習 -> 同じf1が出る
m2 = GradientBoostingClassifier(**best["params"]).fit(Xtr, ytr)
f1_repro = round(float(f1_score(yval, m2.predict(Xval))), 4)
print(f"再現f1   : {f1_repro}  -> 一致:{f1_repro == best['f1']}")

出力:

試行数 : 8
最良 f1 : 0.9009
最良構成 : {'n_estimators': 100, 'max_depth': 3, 'learning_rate': 0.1, 'random_state': 0}
再現f1   : 0.9009  -> 一致:True

出力の意味:8通りの構成を探索し、最良(f1=0.9009)の構成を記録しました。その構成を同じシードで再学習すると同じ f1 が再現します(最終行 True)。random_state を構成に含めて記録するのがポイントで、これが無いと最良構成でも再現できません。実運用ではこの各試行を実験トラッキングの run として残し、設定ファイルを版管理します。

5. 運用の勘所

なぜそうするのか

HPO を運用の観点で管理するのは、「最良構成を確実に再現してデプロイする」ためです。探索で見つけた最良モデルが再現できなければ、本番に出せません。設定を外出しし、シードを記録し、各試行をトラッキングする——これらはすべて「探索結果を再現可能な資産にする」ための仕掛けです。アルゴリズムの効率(ベイズ最適化等)はその上の最適化で、まず再現性が土台になります。

⚠️ よくある落とし穴

対応 lab

関連ノート