この記事の要点(30秒版)
- 実験管理の問題は1つではなく、再現性(同じ条件で動かせるか)と比較(どの条件が良かったか)の2つ
- Hydra は「設定を整理して残す」、MLflow は「結果を並べて比べる」のが得意。役割を分けて組み合わせる
- つなぐコツは3つ。Hydraの実行フォルダを実験の単位にする、確定後の設定をMLflowのartifactに保存する、paramsはフラット化する
- 注意点: Hydra 1.2 以降は作業ディレクトリが出力フォルダに変わらない。出力フォルダは
HydraConfigから取る
実験管理は、やり始めるとすぐ気づくのですが、問題は1つではありません。
- 再現性: その実験、あとから同じ条件で動かせる?
- 比較: どの条件が良くて、どこが効いたのか一目で分かる?
この2つは似ているようで、解決策が少し違います。
- Hydra は「設定を整理して残す(再現性)」が得意
- MLflow は「結果を並べて比べる(比較・可視化)」が得意
なので、役割を分けて組み合わせると、実験管理が一段安定します。それぞれの単体記事はこちらです。
- Hydraの記事: 【機械学習】Hydraで「再現できない実験」とおさらば
- MLflowの記事: 【機械学習】MLflowで実験結果を「可視化・比較」する
この記事では、実験ごとの出力フォルダ(Hydra)と実験結果の比較UI(MLflow)を、同じ「実験単位」で揃えて管理する方法を、最小構成から紹介します。
想定読者: HydraとMLflowをそれぞれ触ったことがあり、2つをつなぎたい人
1. この記事でやること
最終的に、1回の実行で次の状態を作ります。
| 役割 | 何が残るか |
|---|---|
Hydra が outputs/.../ を作る |
.hydra/config.yaml が残る(再現性) |
| 同じ実行で MLflow にもRunが作られる | パラメータ・スコアがUIで比較できる(比較) |
| Hydraの設定ファイル自体を MLflow にも保存する | 「UIから見て、設定ファイルまで辿る」ができる |
2. 組み合わせの基本方針
HydraとMLflowをきれいに繋ぐコツは、次の3点です。
- Hydraの実行単位(run dir)を「実験の粒度」にする
- MLflowのRunに、Hydraの設定(確定後のconfig)を保存する
- MLflowに入れるparamsは「フラット化」して管理する(ネスト対策)
この方針で作ると、あとから実験を見返すときに迷いません。
3. ディレクトリ構成(例)
Hydra側は普通に conf/ を切っておけばOKです。
.
├── conf/
│ ├── config.yaml
│ └── model/
│ └── lightgbm.yaml
├── train.py
└── README.md
4. 実装:Hydra × MLflow の最小構成
以下が、最小で回るコードです。ポイントは次の4つです。
-
mlflow.set_experiment(cfg.exp_name)で実験名を揃える -
cfgはネストが深いので、params用にフラット化する -
.hydra/config.yamlを artifactとして保存する(重要) - 出力フォルダは
HydraConfig.get().runtime.output_dirで取る
from pathlib import Path
import hydra
import mlflow
from hydra.core.hydra_config import HydraConfig
from omegaconf import DictConfig, OmegaConf
def flatten_dict(d, prefix=""):
"""ネストしたdictを MLflow向けにフラット化する(a.b.c=...)"""
items = {}
for k, v in d.items():
key = f"{prefix}{k}" if prefix == "" else f"{prefix}.{k}"
if isinstance(v, dict):
items.update(flatten_dict(v, key))
else:
items[key] = v
return items
@hydra.main(config_path="conf", config_name="config", version_base=None)
def main(cfg: DictConfig):
# Hydraの出力フォルダ(outputs/....)を取得
run_dir = Path(HydraConfig.get().runtime.output_dir)
# MLflowの実験名(Experiment)
mlflow.set_experiment(cfg.exp_name)
# 1実行 = 1Run
with mlflow.start_run(run_name=run_dir.name):
# 1) パラメータ記録(フラット化)
cfg_dict = OmegaConf.to_container(cfg, resolve=True)
flat_params = flatten_dict(cfg_dict)
mlflow.log_params(flat_params)
# 2) 設定ファイル自体も保存(artifact)
# Hydraが生成する確定config と、コマンドラインの上書き内容
for name in ("config.yaml", "overrides.yaml"):
path = run_dir / ".hydra" / name
if path.exists():
mlflow.log_artifact(str(path), artifact_path="hydra")
# --- ここに学習処理を書く ---
# 例:ダミー
auc = 0.82
# 3) 指標を記録(metric)
mlflow.log_metric("auc", auc)
# 4) Hydra run dir のパスも残す(相互参照しやすい)
mlflow.set_tag("hydra.run_dir", str(run_dir))
print(f"[done] run_dir={run_dir}")
if __name__ == "__main__":
main()
os.getcwd() で出力フォルダは取れません。 Hydra 1.2 以降(version_base=None を含む)は、実行中も作業ディレクトリが出力フォルダに切り替わりません。os.getcwd() で取ったパスは実行した場所のままなので、.hydra/config.yaml が見つからず、exists() のチェックでエラーも出ないまま artifact が保存されないことになります。
5. 使い方
python train.py model.params.learning_rate=0.05
動作確認は Hydra 1.3.8 / MLflow 3.17.2 で行いました。実行すると、次のようになります。
Hydra側
-
outputs/yyyy-mm-dd/hh-mm-ss/ができる -
.hydra/config.yamlと.hydra/overrides.yamlが残る
MLflow側
mlflow ui
実行したフォルダで起動し、http://localhost:5000 を開くと次のように見えます。
- Experiment =
cfg.exp_name - Run = 実行ごとの記録
- params / metrics が比較できる(上の例では
model.params.learning_rateが0.05になる)
さらに artifact に hydra/config.yaml と hydra/overrides.yaml が付いてくるので、UI上から設定まで辿れます。
6. よくある詰まりどころと対処
6-1. mlflow.log_params(cfg_dict) がそのまま通らない
MLflowのparamsは、基本「key: value(文字列・数値)」を想定しています。Hydraのcfgはネストが深いので、フラット化が安定です(上の flatten_dict)。
| 例 | |
|---|---|
| OK | model.params.learning_rate = 0.05 |
| NG |
model.params = { ... } のように辞書丸ごと |
6-2. mlflow.set_experiment に毎回別名を入れて散らかる
Experiment名は、最初は雑でもいいですが、散らかると見返しづらくなります。おすすめは次の分離です。
-
cfg.exp_nameは「大枠の目的」(例:lgbm_baseline) -
run_nameに日付時刻やHydraの出力フォルダ名を使う(例:22-00-00)
6-3. Hydraの出力フォルダが分からない
os.getcwd() ではなく、次のように取得します。
from hydra.core.hydra_config import HydraConfig
run_dir = Path(HydraConfig.get().runtime.output_dir)
6-4. MLflow UIに記録が出てこない
記録を実行したフォルダ以外で mlflow ui を起動していないか確認します。MLflow 3.17.2 では、実行したフォルダに mlflow.db と mlruns/ が作られました。
7. もう一段便利にする小ネタ
1. 重要なメトリクスは「比較しやすい名前」で揃える
MLflowの比較は「列名」が命です。たとえば次のように、列名を固定すると後で比較が楽です。
aucloglosscv_mean_auc
2. 学習済みモデルや特徴量重要度も artifact に入れる
LightGBMなら model.txt / model.pkl や feature_importance.csv を保存すると、実験の価値が上がります。
mlflow.log_artifact("feature_importance.csv", artifact_path="artifacts")
8. おわりに
HydraとMLflowは、別々に使うだけでも便利ですが、組み合わせると「実験の振り返り」がかなり楽になります。
- Hydra: 実験条件が確実に残る(再現性)
- MLflow: 結果を横並びで比べられる(比較)
設定ファイルを artifact に載せておけば、「UIで見て → 設定を確認して → 再現する」が自然に繋がります。まずはこの最小構成を動かして、必要になったタイミングで artifact(モデルや図)を増やしていくのが無理がないと思います。
見返し用チェック(自分用)
-
出力フォルダは
HydraConfig.get().runtime.output_dirで取る -
paramsは
flatten_dictでフラット化してからlog_params -
.hydra/config.yamlとoverrides.yamlを artifact に保存する -
mlflow uiは、記録したフォルダで起動する