TT Lab
はじめる
学ぶ 学習パス コース

先週のモデルの方が良かった。誰も見つけられない

より悪いモデルが本番に上がった

TT Labで続きを見る

目標

モデルのバージョンとエイリアス(champion・challenger)を備えた小さなレジストリを立て、指標が落ちたらプロモーションを止めるゲートを作り、ゲートを無視したプロモーションをロールバックし、最後に入力の分布が動いたかを数字にします。

なぜ重要なのか

モデルをデプロイするとは、ファイルをコピーすることではなく、どのバージョンを指すかを決めることです。本番がバージョン番号を直接持っていると、ロールバックはデプロイ設定の変更になりますが、エイリアスを1層置けば、ロールバックは、名前が指す先を変えることになります。そのため、レジストリは、バージョン・エイリアス・履歴の3つを一緒に置きます。プロモーションのゲートは、ここに「自動で進めるが、いつでも進むわけではない」を加える仕組みです。再学習が終わったからとすぐに本番へ行くと、ある週には、より悪いモデルが静かに上がります。ゲートが止めたのに人が押し切ることは、実際に起こるので、止めることと同じくらい、止めたという事実と、押し切ったという事実を、一緒に残すことが重要です。

ステップ

  1. 今本番に出ているモデルを、バージョン1として登録します。
  2. championエイリアスが、バージョン1を指すようにします。
  3. 再学習の結果をバージョン2として登録し、challengerとして立てます。
  4. プロモーションのゲートをコードで作り、判定を残します。
  5. エイリアスが動いた履歴を、監査記録として残します。
  6. ゲートを無視したプロモーションを再現し、その事実を記録に残します。
  7. ロールバックして、どれだけ失ったかを書きます。
  8. 入力の分布がどれだけ移動したかを測って、再学習の判断に付けます。

参考

今出ているモデルをバージョン1として登録する

lr 0.1、epochs 40、seed 7で学習器を回してモデルファイルを作り、/root/registry/registry.jsonに、modelを「churn-classifier」として、versionsの最初の項目としてversion 1を登録してください。各バージョンは、version・run_id・params・metrics・model_path・model_sha256・data_sha256・created_atを持ちます。model_sha256はmodel_pathが指すファイルのハッシュで、data_sha256は/opt/fixtures/mlops/train.csvのハッシュです。

学習器の--outオプションが、モデルファイルを書いてくれます。バージョンごとにファイルを別に置いてください。上書きすると、ロールバックする対象が残りません。

デプロイの対象を番号ではなく名前で指す

/root/registry/aliases.jsonに{"champion": 1}を保存してください。このラボで使うエイリアスは、championとchallengerの2つだけです。

本番がバージョン番号を直接見るようにしておくと、ロールバックのときにデプロイ設定を直す必要があります。エイリアスを1層置けば、ロールバックは、このファイルの1行になります。

再学習の結果をチャレンジャーとして登録する

lr 0.3、epochs 30、seed 3でもう一度学習させて、バージョン2を/root/registry/registry.jsonに登録し、/root/registry/aliases.jsonのchallengerが2を指すようにしてください。バージョン番号は1から1ずつ上がる必要があり、championはまだ1である必要があります。

再学習が、そのままデプロイではありません。新しいバージョンは、まずチャレンジャーとして立てておき、プロモーションは、次のステップのゲートが判断します。

プロモーションを人ではなくルールに判断させる

/root/registry/gate.pyを作成して、/root/registry/registry.jsonと/root/registry/aliases.jsonを読み、/root/registry/gate.jsonに、champion_version・challenger_version・champion_metric・challenger_metric・margin・decision・reasonsを保存してください。marginは0.005で、チャレンジャーのvalid_accuracyが、チャンピオン+margin以上のときだけ、decisionはpromote、そうでなければblockです。reasonsは、10文字以上の文のリストです。

マージンを置く理由は、測定のノイズです。0.001の差でチャンピオンを入れ替えると、来週また入れ替えることになります。

エイリアスが動いた履歴を残す

/root/registry/audit.jsonlに、これまでエイリアスを立てたことを、1行ずつ残してください。各行は、ts・alias・from(最初ならnull)・to・actor・reason(10文字以上)を持ちます。記録を最初から再生すると、/root/registry/aliases.jsonとまったく同じ状態が出てくる必要があります。

監査記録は、「今何であるか」ではなく、「どうやってここまで来たか」を持ちます。fromを書いておけば、再生したときに、ずれた場所がすぐに表に出ます。

ゲートを無視したプロモーションが何を残すかを見る

ゲートが止めたのに、人がchampionをバージョン2に上げた状況を再現してください。/root/registry/aliases.jsonのchampionを2に変え、/root/registry/audit.jsonlに、alias champion、from 1、to 2の行を追加して、その行に、gate_decisionというキーで、gate.jsonの判定をそのまま書いてください。

止めるだけでは足りません。押し切った人が何を知っていたのかが残らないと、次に同じことを話し合えません。

ロールバックして、どれだけ失ったかを書く

championをバージョン1に戻して、その変更も/root/registry/audit.jsonlに残してください(記録は全部で4行以上になり、最後の行が、champion 2→1である必要があります)。そのあと、/root/registry/rollback.jsonに、restored_version・bad_version・detected_by(10文字以上)・metric_delta(バージョン1のvalid_accuracy−バージョン2の値、小数点以下4桁に丸める)を保存してください。

ロールバックは、エイリアスを動かすことです。モデルファイルを消したりバージョンを削除したりすると、何があったのかも一緒に消えます。

入力の分布が動いたかを数字にする

/opt/fixtures/mlops/train.csvを基準に、/opt/fixtures/mlops/week2.csvの5つの特徴量(tenure_months・monthly_fee・support_tickets・late_payments・usage_hours)がどれだけ移動したかを測って、/root/registry/drift.jsonに、baseline・current・features・max_abs_shift_sigma・alert・retrain_requiredを保存してください。featuresの各項目は、train_mean・new_mean・pstdev(基準データの母集団標準偏差)・shift_sigma((new_mean − train_mean) ÷ pstdev)を持ち、空の値や数字でない値は数えません。alertとretrain_requiredは、max_abs_shift_sigmaが1.0を超えるかどうかです。

分布の移動は、契約違反ではありません。値がすべて許容範囲の中にあっても、平均が動くことがあります。そのため、別に測る必要があります。