Claude Media
Claude CodeでMLflowの実験管理を組み込む — run比較まで

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規約を教えるが参考になります。

この記事を共有:XはてブLinkedIn