🎓 レベル:標準 | 重要度:A(必須)
📎 前提:実験トラッキング | 関連:デプロイパターン(バッチ・オンライン・ストリーミング)
要点(BLUF)
- モデルレジストリは「合格したモデルを版管理し、状態(ステージ)を遷移させる台帳」です。各モデルは
name:versionで一意に識別され、None → Staging → Production → Archivedと昇格・降格します。 - 登録するのはモデル単体でなく「変換器+モデル+メタデータ(出自・メトリクス)」の束。変換器ごと登録することでスキュー(学習推論スキューの防止)を防ぎ、サービング(デプロイパターン(バッチ・オンライン・ストリーミング))は「Production の最新版」を読むだけで済みます。
- 最大の運用価値は即時ロールバック。本番モデルが劣化したら、レジストリで前の Production 版に戻すだけで復旧できます。
1. トラッキングとレジストリの違い
実験トラッキングが「すべての実験を記録する」のに対し、レジストリは「本番に値すると判断したモデルだけを昇格管理する」層です。何百 run のうち、本番候補に選ばれた一握りがレジストリに登録され、ライフサイクルを歩みます。
flowchart LR T["トラッキング:全runの記録"] -->|"良い run を選抜"| R["レジストリに登録(v1, v2, ...)"] R --> S["Staging:検証中"] S -->|"承認ゲート"| P["Production:本番稼働"] P -->|"新版に交代"| A["Archived:退役"] P -.->|"劣化したら前版へ"| RB["ロールバック"]
2. モデルのライフサイクル(ステージ)
| ステージ | 意味 | 誰が動かすか |
|---|---|---|
| None | 登録直後 | 自動 |
| Staging | 本番相当環境で検証中(シャドー等) | 自動/担当者 |
| Production | 本番でトラフィックを受ける | 承認ゲート |
| Archived | 退役。ロールバック候補として保持 | 自動/担当者 |
Staging → Production の遷移には承認ゲートを置きます。メトリクス基準・前版との比較・公平性チェック(機械学習公平性とバイアスへ)を満たして初めて昇格させます。
3. 動く最小例:バージョンとステージを持つレジストリ
登録・昇格・本番取得・ロールバックを行う最小レジストリです。
class ModelRegistry:
def __init__(self):
self.models = {} # name -> {version: {"stage":..., "metrics":..., "obj":...}}
def register(self, name, obj, metrics):
versions = self.models.setdefault(name, {})
v = max(versions.keys(), default=0) + 1
versions[v] = {"stage": "None", "metrics": metrics, "obj": obj}
return v
def transition(self, name, version, stage):
# Production は常に1つ:既存の Production を Archived に降格
if stage == "Production":
for v, info in self.models[name].items():
if info["stage"] == "Production":
info["stage"] = "Archived"
self.models[name][version]["stage"] = stage
def get_production(self, name):
for v, info in sorted(self.models[name].items()):
if info["stage"] == "Production":
return v, info
return None, None
# --- 運用シナリオ ---
reg = ModelRegistry()
v1 = reg.register("churn", obj="model_v1", metrics={"f1": 0.91})
v2 = reg.register("churn", obj="model_v2", metrics={"f1": 0.94})
reg.transition("churn", v1, "Production") # まず v1 を本番へ
pv, pinfo = reg.get_production("churn")
print(f"本番モデル : v{pv} f1={pinfo['metrics']['f1']}")
# v2 が承認ゲートを通過 -> 本番交代
reg.transition("churn", v2, "Production")
pv, pinfo = reg.get_production("churn")
print(f"昇格後本番 : v{pv} f1={pinfo['metrics']['f1']} (v1は自動でArchived)")
print(f"v1のstage : {reg.models['churn'][v1]['stage']}")
# v2 が本番で劣化 -> v1 へロールバック
reg.transition("churn", v1, "Production")
pv, pinfo = reg.get_production("churn")
print(f"ロールバック後本番 : v{pv} f1={pinfo['metrics']['f1']}")
出力:
本番モデル : v1 f1=0.91
昇格後本番 : v2 f1=0.94 (v1は自動でArchived)
v1のstage : Archived
ロールバック後本番 : v1 f1=0.91
出力の意味:v1 を本番にした後、より良い v2(f1=0.94)が承認を通って本番交代し、v1 は自動で Archived になりました。その後 v2 が本番で劣化したと仮定して v1 へロールバック——get_production が常に「現在の Production 版」を返すので、サービング側はコードを変えずに最新の本番モデルを取得できます。**「本番は常に1つ、過去版は退役として保持」**という不変条件が、安全な交代とロールバックを支えます。
4. 運用の勘所
- 変換器ごと登録する:前処理(特徴量エンジニアリングのパイプライン化)とモデルを1アーティファクトに。サービングは丸ごとロードしてスキューを防ぐ。
- 承認ゲートを明示する:Staging→Production の条件(メトリクス基準・前版比較・公平性)をコード化し、人手の気分で昇格させない。
- 退役版を消さない:ロールバック先として一定期間保持する。即時復旧の生命線。
- サービングはステージで参照する:
churn:Productionのように版番号でなくステージで参照させ、昇格と同時に切り替わるようにする。
なぜそうするのか
レジストリを「ステージを持つ台帳」にする理由は、デプロイとモデル選択を分離するためです。サービングは「Production を読む」とだけ知っていればよく、どの版が Production かはレジストリが管理します。これにより、新版への切り替えもロールバックも「ステージを動かすだけ」になり、サービングのコードやデプロイを触らずに安全に本番モデルを差し替えられます。
⚠️ よくある落とし穴
- Production を複数許す:どれが本番か曖昧になる。本番は常に1つに保つ。
- モデルだけ登録して変換器を捨てる:推論時に前処理が再現できずスキュー。変換器ごと登録する。
- 退役版を即削除する:ロールバック不能になる。一定期間保持する。
- 昇格を口頭・手作業で行う:承認基準が曖昧になり、劣化モデルが本番に漏れる。ゲートをコード化する。
対応 lab
- なし(概念ノート)。最小レジストリは本文 §3 に同梱。サービングからの利用は オンライン推論サービング の lab を参照。
関連ノート
- 実験トラッキング(昇格候補の選抜元)
- デプロイパターン(バッチ・オンライン・ストリーミング)(Production をどう配信するか)
- リリース戦略(シャドー・カナリア・A-Bテスト)(Staging→Production の安全な切替)
- 学習推論スキューの防止(変換器ごと登録する理由)
- 第3章 実験管理とモデル管理 目次
- MLOps・AI基盤 全体目次