🎓 レベル:標準 | 重要度:B(推奨)
📎 前提:実験トラッキング | 関連:ハイパーパラメータ最適化(機械学習)
要点(BLUF)
- ハイパーパラメータ探索(HPO)の運用は、「探索空間を設定として宣言し、各試行をトラッキングに記録し、最良構成を出自つきで再現する」こと。探索アルゴリズム(グリッド/ランダム/ベイズ最適化)の理論は機械学習分野(ハイパーパラメータ最適化)に委ねます。
- 鍵は設定の外出し:ハイパーパラメータをコードに直書きせず設定ファイル(YAML等)で宣言する。これで探索空間が版管理でき、「どの設定で最良が出たか」を後から正確に再現できます。
- 探索は計算資源を食うので、**早期終了(見込みのない試行を途中で打ち切る)**でコストを抑えます。各試行は実験トラッキングの run として記録します。
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. 運用の勘所
random_stateを構成に含める:シードを記録しないと最良構成すら再現できない。- 探索空間を版管理する:設定ファイルにして Git に入れ、「どの空間で探したか」を残す。
- 早期終了でコストを抑える:見込みのない試行を途中で打ち切る(しきい値・中央値打ち切り)。探索は計算資源を最も食う工程。
- 最良だけでなく探索全体を残す:「なぜその構成にしたか」を説明でき、次の探索の出発点にできる。
なぜそうするのか
HPO を運用の観点で管理するのは、「最良構成を確実に再現してデプロイする」ためです。探索で見つけた最良モデルが再現できなければ、本番に出せません。設定を外出しし、シードを記録し、各試行をトラッキングする——これらはすべて「探索結果を再現可能な資産にする」ための仕掛けです。アルゴリズムの効率(ベイズ最適化等)はその上の最適化で、まず再現性が土台になります。
⚠️ よくある落とし穴
- シードを記録しない:最良構成でも結果が再現しない。
random_stateを構成に含める。 - ハイパーパラメータをコード直書きする:版管理も再現もできない。設定ファイルに外出しする。
- 検証データで探索し、その検証データで最終評価する:探索が検証データに過適合。最終評価は触っていないテストで。
- 探索コストを無視する:早期終了なしで巨大空間を全探索すると資源が枯渇する。
対応 lab
- なし(概念ノート)。グリッド探索の記録・再現は本文 §4 に同梱。試行の記録は 実験トラッキング の lab を流用できます。
関連ノート
- 実験トラッキング(各試行の記録)
- モデルレジストリとモデルのライフサイクル(最良モデルの本番管理)
- 再現性とバージョニング(再現の土台)
- ハイパーパラメータ最適化(機械学習・探索アルゴリズムの理論)
- 第3章 実験管理とモデル管理 目次
- MLOps・AI基盤 全体目次