Claude CodeでMLflowの実験管理を組み込む — run比較まで
学習スクリプトにMLflowのtrackingを足させ、複数runの比較結果をClaude Codeに読ませる手順。autologと明示ログの使い分け、権限設計、CLAUDE.mdの書き方まで。
Claude CodeにMLflowの実験管理を組み込ませる作業は、2つに分かれます。学習スクリプトにtrackingのコードを足させること。そして、できあがった複数のrunを「Claudeが読める文字の表」にして渡すことです。MLflowのUIは人間向けの画面なので、Claudeに比較させたいなら、画面の代わりに標準出力へ表を出すスクリプトを1本用意するのが近道になります。
この記事では、scikit-learnの学習スクリプトを題材に、trackingの追加、複数runの作成、比較結果の読ませ方、権限とCLAUDE.mdの設定までを順に扱います。コード例は手順を示すための一例で、Claudeの実際の出力ではありません。
MLflow Trackingは何を記録し、Claudeに何を任せるか
MLflow Trackingは、機械学習コードを実行したときのパラメータ、コードのバージョン、メトリクス、出力ファイルを記録し、あとから可視化するためのAPIとUIです。Python、REST、R、JavaのAPIが用意されています。
記録の単位は「run」です。python train.py を1回実行したときの記録が1つのrunにあたり、メトリクスや開始・終了時刻といったメタデータと、モデルの重みや画像のような出力ファイル(artifact)を持ちます。同じ課題のrunは「experiment」にまとめます。
Claude Codeに任せやすい作業と、人が決める作業を分けると、次のようになります。
| 作業 | Claudeに任せるか | 理由 |
|---|---|---|
start_run と log_param などの追加 | Claudeに任せるか任せやすい | 理由既存コードへの定型的な差し込み |
| 何をメトリクスの主指標にするか | Claudeに任せるか人が決める | 理由指標の選び方は課題の目的で変わる |
| 複数runの実行と比較表の生成 | Claudeに任せるか任せやすい | 理由コマンドを実行し、出力を読む反復 |
| 比較結果の解釈 | Claudeに任せるかClaudeに案を出させ、人が判断 | 理由差が誤差かどうかはデータ量に左右される |
| 保存先(mlruns・DB・サーバー)の選択 | Claudeに任せるか人が決める | 理由チームでの共有範囲に関わる |
W&Bで同じことをする場合は、MCPサーバー経由で実験結果を読む構成になります。手順はClaude Codeでwandb MCPサーバーを使い実験結果を読む手順にまとめています。MLflowはローカルのファイルだけで完結できる点が違います。
保存先を先に決める
MLflow Trackingは、サーバーやデータベースの設定をしないと、実行したディレクトリの mlruns ディレクトリにデータを書き出します。Claude Codeに作業させる最初の段階では、この既定のままで足ります。
ドキュメントは保存先を3段階に分けています。
- ローカルディレクトリ(
mlruns): 設定不要。1人で始めるときの最小構成 - ローカルのデータベース: SQLiteやPostgreSQLなど、SQLAlchemy互換のDBにメタデータを保存する。サーバーを立てずに実験データを整理できる
- リモートのTracking Server: チームで共有する構成。artifactの扱いも含めてサーバーが仲介する
Claudeに「MLflowを入れて」と頼むと、どこに記録するかが曖昧なまま進みます。保存先は最初の指示に書いておくと、後から食い違いません。リモートのサーバーに切り替えるときは mlflow.set_tracking_uri() で接続先を指定します。
学習スクリプトにtrackingを足させる
追加の方法は2つあります。mlflow.autolog() に任せる方法と、log_param や log_metric を自分で書く方法です。
autologで最小の変更にする
autologは、学習コードの前に mlflow.autolog() を呼ぶだけで、メトリクス、パラメータ、モデルを記録します。Scikit-learn、XGBoost、PyTorch、Keras、Sparkなどに対応します。scikit-learnだけを対象にするなら mlflow.sklearn.autolog() を使います。
scikit-learnのestimatorでは、estimator.score で得た学習データのスコアと、get_params で取れるパラメータ、クラス名、学習済みestimatorが記録されます。GridSearchCV のようなパラメータ探索では、親runの下に組み合わせごとの子runが作られます。
Claudeへの指示は、次のくらい短くて足ります。
train.py の学習前に mlflow.sklearn.autolog() を追加して。
experiment 名は iris-logreg。他の処理は変えないで。autologは差分が1〜2行で済みます。一方で、記録される指標は「ライブラリが選んだもの」です。自分で定義した評価指標を残したいなら、明示ログを併用します。
評価指標を明示ログで足す
次の train.py は、正則化の強さ C を引数にして、テストデータでの正解率を記録する例です。
import argparse
import mlflow
from sklearn.datasets import load_iris
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score
from sklearn.model_selection import train_test_split
parser = argparse.ArgumentParser()
parser.add_argument("--C", type=float, default=1.0)
args = parser.parse_args()
mlflow.set_experiment("iris-logreg")
X, y = load_iris(return_X_y=True)
X_tr, X_te, y_tr, y_te = train_test_split(
X, y, test_size=0.2, random_state=42
)
with mlflow.start_run():
mlflow.log_params({"C": args.C, "max_iter": 1000})
model = LogisticRegression(C=args.C, max_iter=1000)
model.fit(X_tr, y_tr)
acc = accuracy_score(y_te, model.predict(X_te))
mlflow.log_metric("test_accuracy", acc)
print(f"C={args.C} test_accuracy={acc:.4f}")mlflow.start_run() でrunを始め、mlflow.log_params() と mlflow.log_metric() で値を残す、というのが基本形です。with ブロックを抜けるとrunが終わります。
autologと明示ログを同じスクリプトで併用するときは、runの扱いに注意が必要です。ドキュメントによれば、autologが記録するときにアクティブなrunが無ければ、MLflowが自動でrunを作り、学習の終了時に閉じます。すでにrunがあるときは、そのrunに記録しますが、自動では閉じません。with mlflow.start_run(): の中で学習すれば、記録は1つのrunにまとまります。
autologと明示ログの使い分け
autolog
学習コードの前に1行足すだけ。ライブラリが選んだ指標とパラメータが残る。まず動かしたいとき向き。
明示ログ
log_param と log_metric を書く。評価指標の名前を揃えられるので、runの比較がしやすい。
複数のrunを作って、比較の材料を揃える
比較するには、条件を変えたrunが複数必要です。Claudeに探索をまかせるなら、シェルのループで train.py を繰り返し実行させます。
for C in 0.01 0.1 1 10; do
python train.py --C $C
doneコマンドの許可は、実行する範囲を絞った形で設定します。Claude Codeの許可ルールは Bash(コマンド *) の形で書き、* はサブコマンドの後ろに置きます。たとえば Bash(npm run *) は npm run build に一致し、npm install には一致しません。この仕組みを使い、学習と比較のスクリプトだけを許可します。
{
"permissions": {
"allow": [
"Bash(python train.py *)",
"Bash(python compare_runs.py *)"
]
}
}この設定を .claude/settings.json に置くと、学習の起動で毎回確認が出ません。mlflow server のように常駐するコマンドは、許可に入れず、人が別のターミナルで起動するほうが扱いやすくなります。
run比較の結果をClaudeに読ませる
UIで見られる「メトリクスの上位run」は、MlflowClient で同じ検索ができます。ドキュメントには、experimentのなかで検証損失が最小のrunを取り出す例が載っています。search_runs に order_by=["metrics.val_loss ASC"] と max_results=1 を渡します。
これを複数件に広げ、標準出力へ表として出すスクリプトを作ります。
import sys
import mlflow
name = sys.argv[1]
metric = sys.argv[2] if len(sys.argv) > 2 else "test_accuracy"
client = mlflow.tracking.MlflowClient()
exp = client.get_experiment_by_name(name)
if exp is None:
sys.exit(f"experiment not found: {name}")
runs = client.search_runs(
[exp.experiment_id],
order_by=[f"metrics.{metric} DESC"],
max_results=10,
)
print(f"run_id status {metric} params")
for r in runs:
value = r.data.metrics.get(metric)
print(
r.info.run_id[:8],
r.info.status,
value,
r.data.params,
)起動は python compare_runs.py iris-logreg test_accuracy です。出力は上位10件が、指標の降順に並んだ文字の表になります。Claudeはこの出力をそのまま読み、「C を大きくすると正解率がどう動いたか」を文章にできます。
読ませるときのプロンプトは、判断の材料を明示するとぶれません。
python compare_runs.py iris-logreg test_accuracy を実行して、
出力を読んで。次の3点に答えて。
1. 最も指標が高いrunのパラメータ
2. 指標の差が小さく、順位が意味を持たなそうなrun
3. 次に試すパラメータの候補(根拠つき)2番目の質問は、Irisのように小さなテストデータでは大事です。テストが30件だと、1件の違いで正解率が3ポイント以上動きます。Claudeに「差が誤差の範囲か」を答えさせると、順位に引きずられた結論を避けられます。
CLAUDE.mdに書いておく規約
プロジェクトのCLAUDE.mdは ./CLAUDE.md か ./.claude/CLAUDE.md に置きます。ビルドやテストのコマンド、コーディング規約、よく使うワークフローを書く場所です。MLflowの運用ルールは、次の程度を書いておけば足ります。
## 実験管理(MLflow)
- experiment名は課題ごとに固定する(例: iris-logreg)
- 学習は必ず `with mlflow.start_run():` の中で行う
- 主指標は test_accuracy。名前を変えない
- 結果は `python compare_runs.py <experiment> <metric>` で確認する
- `mlruns/` の中身は直接読まない。`.gitignore` に入れる指標の名前を固定する項目は効きます。あるrunでは test_accuracy、別のrunでは acc と名前が割れると、search_runs の order_by で同じ列として並べられません。Claudeが毎回違う名前を選ばないよう、規約に書いて固定します。
つまずきやすい点
落とし穴
autologとstart_runの二重管理でrunが想定外に増える
autologは、アクティブなrunが無いときに自分でrunを作ります。スクリプトのなかで start_run を呼ぶ位置がautologの後ろだったり、関数ごとに start_run が分かれていたりすると、1回の学習で複数のrunができます。Claudeに頼むときは「runは1回の実行につき1つ」と書き添えます。
- 保存先がディレクトリごとに分かれる: 既定の
mlrunsは、スクリプトを実行したディレクトリに作られます。Claudeが別のディレクトリでtrain.pyを起動すると、比較スクリプトからは見えないrunができます。UIを起動するときも、mlrunsの1つ上のディレクトリで実行します - experiment名の打ち間違い:
set_experimentに渡す名前が違うと、別のexperimentにrunが入ります。比較スクリプトが「experiment not found」で止まるのは、この種のずれに気づくためです - autologの対応ライブラリの条件: Keras/TensorFlowは
tensorflow>=2.3が対象です。バージョンが合わないと記録されないので、依存のバージョンも確認します - ライブラリごとに止める: 前処理のscikit-learnは記録に入れず、PyTorchだけ記録したいときは
mlflow.sklearn.autolog(disable=True)とmlflow.pytorch.autolog()を使い分けます
まとめ
MLflowのtrackingをClaude Codeに組み込むときの要は、記録と読み出しの両方をコマンドで閉じることです。学習スクリプトには start_run とログ呼び出しを足し、比較は search_runs を使った文字の表で渡します。画面を開く作業が無くなるので、Claudeは「学習する、表を読む、次の条件を決める」の反復をコマンドだけで回せます。
最初の1歩は、mlflow.sklearn.autolog() の1行と、10行程度の比較スクリプトです。指標名の固定と mlruns の扱いをCLAUDE.mdに書いておけば、セッションが変わってもrunが同じ形で積み上がります。scikit-learn自体の実装手順はClaude Codeでscikit-learnモデルを実装する、CLAUDE.mdに規約を書く考え方はClaude CodeにpytestのCLAUDE.md規約を教えるが参考になります。