先週のあのモデルを誰も見つけられない
目標
学習1回を「実行(run)」という記録単位にして、パラメーター・指標・コードとデータの指紋を元帳に残し、あとでその実行を復元できるようにします。最後に、記録を残さなかった実行がどのように消えるかを、実際のログで確認します。
なぜ重要なのか
モデルをうまく作ることと、そのモデルをもう一度作ることは、別の仕事です。学習は、乱数のシード・データのバージョン・前処理のコードのすべてに依存していて、そのうち1つだけを書いておかなくても、2か月後には同じ数字が出ません。実験追跡ツールがすることは、華やかなグラフではなく、1回の学習を立て直せるだけの事実を強制的に書かせることです。ここでは、その最小の集合を自分で設計してみます。ツールが自動で埋めてくれていた欄を手で埋めてみれば、あとでその欄が空いている元帳を見て、すぐに気づけるようになります。
ステップ
- 実験の定義: 何を最大化するのかを、先に書きます。
- 最初の実行を、元帳に1行で残します。
- パラメーターを変えながら、実行を4つ以上に増やします。
- すべての実行に、コード・データの指紋を付けます。
- 目標の指標で、最良の実行を元帳から取り出し直します。
- 記録だけを見て、その実行を再現します。
- 記録なしで消えた実行を調べます。
- 元帳を、それだけで成り立つパッケージとして書き出します。
参考
- 作業はすべて
/root/mlopsの下で行います。まずmkdir -p /root/mlopsをしてください。 - 材料は
/opt/fixtures/mlopsにあります。データの説明は、DATA-CARD.mdを見てください。 - 学習器の実行例:
python3 /opt/fixtures/mlops/train_model.py --train /opt/fixtures/mlops/train.csv --valid /opt/fixtures/mlops/valid.csv --lr 0.1 --epochs 40 --seed 7 - 採点ツールは、元帳に書かれた引数で学習器をもう一度回して、指標を照合します。数字をでっち上げると引っかかります。
- よくある間違い:
matchesやreproducibleを、文字列"true"で書くこと、そして元帳を上書き(w)で開いて、前の実行を消してしまうことです。 - ラボのPodにはボリュームがありません。セッションが終わると
/rootはまるごとなくなるので、残したいものは、ステップ8のパッケージのように、別にコピーしておいてください。
何をよい結果とみなすかを先に書く
/root/mlops/experiment.jsonに、実験の定義を保存してください。nameはchurn-baseline、objective_metricはvalid_accuracy、directionはmax、ownerは責任者の名前(2文字以上)、datasetは/opt/fixtures/mlops/train.csvです。
指標を選ぶ前に実験を始めると、あとから有利な数字を選んでしまいます。何を最大化するのかを、先に決めておいてください。
最初の実行を元帳に1行で残す
/opt/fixtures/mlops/train_model.pyを1回回して、その結果を/root/mlops/runs.jsonlにJSONの1行で残してください。1行に、run_id・params(lr・epochs・seed)・metrics(valid_accuracy・train_accuracy)・data(train・validのパス)・started_atが入ります。指標は、実行の出力をそのまま書き写します。
学習器は、標準出力にJSONを1つ出します。その値を手で写さずに、Pythonで受け取って元帳に書けば、写し間違える心配がありません。
4回追加で回して、比べられるようにする
異なるlr・epochs・seedの組み合わせで実行を増やして、/root/mlops/runs.jsonlに4つ以上残してください。run_idは実行ごとに違う必要があり、同じパラメーターの組み合わせを2回書いてはいけません。すべての行の指標は、その引数でもう一度回したときに出る値と同じである必要があります。
パラメーターのリストをコードに置いて繰り返せば、5行が一度にできます。採点ツールは、各行の引数で学習器をもう一度回して、指標を照合します。
コードとデータに指紋を付ける
/root/mlops/runs.jsonlのすべての行に、code_sha256とdata_sha256を入れてください。code_sha256は/opt/fixtures/mlops/train_model.pyの、data_sha256は/opt/fixtures/mlops/train.csvの、SHA-256の16進文字列です。
パラメーターが同じでも、学習コードやデータが変われば、別の実験です。hashlib.sha256で、ファイルのバイトをハッシュしてください。
最良の実行を元帳から取り出し直す
/root/mlops/experiment.jsonの目標の指標と方向を読んで、/root/mlops/runs.jsonlから最良の実行を選び、/root/mlops/best.jsonに、run_id・metric・value・selected_byを保存してください。同点なら、元帳で先に出てきた実行を選びます。
目で選ばずに、コードで選んでください。人が選ぶと、来週もう一度選んだときに、別の答えが出ます。
記録だけを見て、その実行を復元する
/root/mlops/best.jsonが選んだ実行のパラメーターを、/root/mlops/runs.jsonlから読んで学習器をもう一度回し、結果を/root/mlops/reproduce.jsonに、run_id・params・valid_accuracy・matches・code_sha256・data_sha256として保存してください。matchesは、元帳の値と同じならブール値のtrueです。
再現は、「記憶」ではなく「記録」で行うものです。元帳に書かれた引数だけを使い、文字列として書いた「true」はブール値ではありません。
記録なしで消えた実行を調べる
/opt/fixtures/mlops/ghost_run.logは、先週誰かが回した実行のログの断片です。/root/mlops/incident.jsonに、ghost_metric(ログに書かれた値)・best_recorded_metric(/root/mlops/runs.jsonlの最高値)・gap(2つの差、小数点以下4桁に丸める)・reproducible・missing_fields(ログだけではわからない実行記録のフィールドを、辞書順に)・recovery_plan(40文字以上)を保存してください。
ログから読み取れるのは、指標1つだけです。実行記録がそろえるべきフィールドのうち、何が空いているのかを数えてみれば、なぜ再現できないのかがわかります。
セッションが終わる前に元帳を持ち出す
/root/mlops/export/の下に、runs.jsonl・experiment.json・best.jsonをコピーして、/root/mlops/export/manifest.jsonに、experiment・run_count・best_run_id・filesを保存してください。filesの各項目は、path(ディレクトリなしで、ファイル名だけ)・sha256・bytesを持ち、best_run_idは、含めた元帳から計算し直した値である必要があります。
ラボのPodにはボリュームがないので、セッションが終わると/rootがなくなります。パッケージは、それだけで成り立つ必要があります。元帳だけがあって目標がないと、あとから解釈できません。