实验记录格式(Experiment Logging Format)

一句话定位

标准化实验日志的记录格式和命名规范,支持wandb/tensorboard等工具,实现实验可追溯性和团队协作。

前置依赖

核心思想

为什么需要标准化日志

问题场景

  • 跑了100个实验,不知道哪些有效
  • 需要复现上周的结果但忘了配置
  • 团队成员无法理解你的实验记录

标准化日志的价值

  • 快速定位好的实验配置
  • 自动化生成实验报告
  • 团队知识共享

日志层次结构

实验记录
├── 实验元信息(谁、何时、为什么)
├── 配置文件(完整超参数)
├── 训练日志(loss曲线、metrics)
├── 评估结果(最终性能)
└── 分析总结(教训learned)

实验命名规范

命名格式

推荐格式

[任务]_[模型]_[关键修改]_[日期]_[备注]

示例

dmc_walker_walk_dreamerv3_kl10_20240522_v1
dmc_quadruped_run_transfoxr_longseq_20240523
atari_breakout_transformer_wm_20240524_baseline

禁止

  • test_experiment_1(无意义)
  • run1(太短)
  • new_model_final_v2_actual(混乱)

Tags和Groups

使用wandb tags组织实验:

wandb.init(
    project="world-model-ablation",
    name="kl_weight_ablation_0.1",
    tags=["ablation", "kl_weight", "dreamerv3"],
    group="kl_weight_study"
)

核心Metrics记录

训练Metrics

必须记录的Metrics

# 训练日志 - 每个train step记录
train_metrics = {
    # 损失
    "train/loss_total": loss_total,
    "train/loss_obs": loss_obs,
    "train/loss_reward": loss_reward,
    "train/loss_kl": loss_kl,
 
    # KL统计
    "train/kl_mean": kl_mean,
    "train/kl_std": kl_std,
    "train/kl_per_dim": kl_mean / z_dim,
 
    # 梯度
    "train/grad_norm": grad_norm,
 
    # 学习率
    "train/lr": current_lr,
}

评估Metrics

# 评估日志 - 每个eval interval记录
eval_metrics = {
    # Return统计
    "eval/return_mean": np.mean(returns),
    "eval/return_std": np.std(returns),
    "eval/return_min": np.min(returns),
    "eval/return_max": np.max(returns),
 
    # 长度统计
    "eval/ep_length_mean": np.mean(lengths),
 
    # 特殊指标
    "eval/success_rate": success_count / total_episodes,
}

详细日志配置

# wandb_config.yaml
logging:
  project: world-model-experiments
  entity: your-team
 
  # 记录频率
  train_log_interval: 10  # 每10步
  eval_log_interval: 1000  # 每1000步
  save_checkpoint_interval: 10000  # 每10000步
 
  # 上传
  log_gradients: true
  log_parameters: false  # 太大,不建议开启
  log_predictions: false  # 可开启用于debug
 
  # watched metrics
  watch_log_frequency: 100  # wandb.watch 记录频率

Tensorboard配置

目录结构

logs/
├── tensorboard/
│   ├── exp001_dmc_walker/
│   │   ├── train
│   │   └── eval
│   └── exp002_atari_breakout/
│       ├── train
│       └── eval
└── checkpoints/
    ├── exp001_dmc_walker/
    │   ├── step_10000.pt
    │   └── best.pt
    └── exp002_atari_breakout/

代码配置

from torch.utils.tensorboard import SummaryWriter
 
# 创建writer
writer = SummaryWriter(log_dir=f"logs/tensorboard/{exp_name}")
 
# 记录scalar
writer.add_scalar("train/loss_total", loss, global_step)
 
# 记录多个同一类型的scalar
writer.add_scalars("losses", {
    "obs": loss_obs,
    "reward": loss_reward,
    "kl": loss_kl
}, global_step)
 
# 记录直方图
writer.add_histogram("weights/dynamics_layer1", weights, global_step)
 
# 记录图像
writer.add_image("reconstruction", recon_grid, global_step)
 
# 关闭
writer.close()

实验配置记录

YAML配置模板

# config.yaml - 必须保存的完整配置
experiment:
  name: dmc_walker_walk_dreamerv3_kl10_20240522
  description: "KL weight ablation: kl=0.1 baseline"
  created_by: your_name
  created_at: 2024-05-22
 
  # 实验类型标签
  tags:
    - baseline
    - dreamerv3
    - kl_weight_study
  group: world_model_ablation
 
  # 相关实验
  related_experiments:
    - dmc_walker_walk_dreamerv3_kl01_20240520  # 上一组kl=0.01
    - dmc_walker_walk_dreamerv3_kl05_20240521  # 上一组kl=0.05
 
model:
  stochastic_channels: 32
  deterministic_hidden: 512
  action_channels: 256
 
  encoder:
    type: rgb
    resolution: [84, 84]
 
training:
  total_steps: 1000000
  batch_size: 64
  sequence_length: 32
 
  optimizer:
    type: AdamW
    lr: 1e-4
 
  kl_weight: 0.1
  kl_free_nats: 0.0
 
environment:
  name: DM Control Suite/walker_walk
  num_train_envs: 16
  num_eval_envs: 10

自动化配置保存

def save_experiment_config(config, save_dir):
    """保存实验配置到指定目录"""
    config_path = Path(save_dir) / "config.yaml"
 
    # 添加元信息
    config["experiment"]["saved_at"] = datetime.now().isoformat()
    config["experiment"]["git_commit"] = get_git_commit_hash()
 
    with open(config_path, "w") as f:
        yaml.dump(config, f, default_flow_style=False)
 
    # 同步保存到wandb
    wandb.config.update(config)

Checkpoint管理

保存策略

# checkpoint_manager.py
class CheckpointManager:
    def __init__(self, save_dir, keep_last_n=5):
        self.save_dir = Path(save_dir)
        self.keep_last_n = keep_last_n
        self.checkpoints = []
 
    def save(self, model, optimizer, step, metrics):
        """保存checkpoint"""
        ckpt_path = self.save_dir / f"step_{step}.pt"
 
        torch.save({
            "step": step,
            "model_state": model.state_dict(),
            "optimizer_state": optimizer.state_dict(),
            "metrics": metrics,
        }, ckpt_path)
 
        self.checkpoints.append(ckpt_path)
 
        # 只保留最近的N个
        if len(self.checkpoints) > self.keep_last_n:
            old_ckpt = self.checkpoints.pop(0)
            old_ckpt.unlink()
 
    def load_best(self):
        """加载最佳checkpoint"""
        best_path = self.save_dir / "best.pt"
        if best_path.exists():
            return torch.load(best_path)
        return None

最佳模型选择

# 基于eval return选择最佳
best_return = -float("inf")
 
if eval_return_mean > best_return:
    best_return = eval_return_mean
    save_checkpoint(model, optimizer, step, "best.pt")
    logger.info(f"New best model: return={eval_return_mean:.2f}")

实验对比分析

wandb实验对比

import wandb
import pandas as pd
 
# 查询实验
api = wandb.Api()
runs = api.runs("your-team/world-model-ablation",
                filters={"tags": {"$in": ["ablation"]}})
 
# 转为DataFrame
data = []
for run in runs:
    data.append({
        "name": run.name,
        "state": run.state,
        "kl_weight": run.config.get("kl_weight"),
        "eval_return": run.summary.get("eval/return_mean"),
        "created_at": run.created_at,
    })
 
df = pd.DataFrame(data)
print(df.sort_values("eval_return", ascending=False))

生成对比报告

# 实验对比报告: KL Weight Ablation
 
## 实验配置
 
| 实验名 | KL Weight | 学习率 | 潜在维度 |
|--------|-----------|--------|----------|
| kl01_baseline | 0.1 | 1e-4 | 32 |
| kl05_lower | 0.05 | 1e-4 | 32 |
| kl20_higher | 0.2 | 1e-4 | 32 |
 
## 结果
 
| 实验名 | Eval Return | KL/dim | 训练步数 |
|--------|-------------|--------|----------|
| kl01_baseline | 95.2 ± 3.1 | 0.08 | 1M |
| kl05_lower | 87.3 ± 4.2 | 0.04 | 1M |
| kl20_higher | 91.8 ± 2.8 | 0.15 | 1M |
 
## 结论
 
KL weight = 0.1 在walker_walk任务上表现最佳。

章节摘要

本章提供了实验记录格式的完整指南:

  1. 命名规范:标准化实验名称便于搜索和识别
  2. Metrics记录:训练和评估核心指标的日志格式
  3. Tensorboard配置:本地日志记录方法
  4. 配置保存:YAML配置模板和自动化保存
  5. Checkpoint管理:保存策略和最佳模型选择
  6. 对比分析:wandb查询和报告生成

良好的实验记录习惯是科研效率的关键,建议从第一个实验开始规范记录。

关键词

实验日志 wandb tensorboard 实验命名 checkpoint metrics 实验管理 实验对比 超参数记录 日志格式