DMAD 训练侧盯显存和步数——推理侧只比同一批提示词的出图

文章导读
把 DMAD 的训练和推理拆成两条观察线,目的只有一个:减少同时变化的变量。训练侧固定记录显存峰值、单步耗时、迭代数和损失值;推理侧固定使用同一批提示词、同一个种子和同一个分辨率,只比较两次出图的差异。只要两侧各有一份可对照的基线记录,出图变差时就能先判断是训练侧已经跑偏,还是推理设置被人改动过,不必在两个方向上反复试错。
📋 目录
  1. Ⅰ 把训练侧要记录的字段固定下来
  2. Ⅱ 整理一批固定提示词作为推理侧标尺
  3. Ⅲ 训练中途暂停并出图观察
  4. Ⅳ 两侧结论不一致时先回到训练侧核对
  5. Ⅴ 确定一组可复用的训练与推理搭配
A A

把 DMAD 的训练和推理拆成两条观察线,目的只有一个:减少同时变化的变量。训练侧固定记录显存峰值、单步耗时、迭代数和损失值;推理侧固定使用同一批提示词、同一个种子和同一个分辨率,只比较两次出图的差异。只要两侧各有一份可对照的基线记录,出图变差时就能先判断是训练侧已经跑偏,还是推理设置被人改动过,不必在两个方向上反复试错。

适用场景:单机或少卡环境、边调训练参数边看推理出图的阶段,尤其是“改了学习率又换了采样步数”之后说不清原因的场合。操作动作:训练侧按固定频率把显存峰值、单步耗时、迭代数、损失写进同一份日志;推理侧冻结一批提示词连同种子、分辨率一起入库。验证方式:同一检查点重复出图应得到一致结果,训练日志里显存峰值与单步耗时若出现台阶式变化,应能对应到具体迭代数。风险边界:整卡显存统计与框架内统计面向不同统计范围,比较时前后必须使用同一种统计方式,否则趋势判断无效。

把训练侧要记录的字段固定下来

训练侧要回答的只有四个问题:显存够不够、每步多快、跑到第几步、损失是否平稳。字段一旦定下来,每一轮训练的结果才具备可比性;否则换一次 batch 或分辨率,前后日志就没法放在一起看。建议把记录频率和日志位置先写进配置,不要靠临时手敲命令补记。

字段记录位置记录频率用来判断什么
显存峰值训练循环内统计 + 整卡采样兜底每 N 步打印一次,N 固定batch、分辨率、梯度累积是否已接近上限
单步耗时训练日志时间戳每步或每 N 步是否因显存吃紧被换入换出拖慢
迭代数日志与检查点文件名每步;检查点按固定间隔出图问题对应到训练哪个阶段
损失值日志,建议同时写 csv每 N 步,与显存同一行是否发散、是否长期不动

整卡显存用外部采样即可,框架内的峰值统计则要放进训练循环,两者统计范围不同,注意不要混着比较:

# 整卡显存采样,5 秒一次,追加到文件
nvidia-smi `--query-gpu`=timestamp,memory.used,memory.total,utilization.gpu \
  `--format`=csv,noheader -l 5 >> logs/gpu_mem.csv

# 训练循环里的峰值打印(通用骨架,按自己的写法替换)
peak = torch.cuda.max_memory_allocated() / 1024**3
print(f"iter={step} loss={loss:.4f} step_time={dt:.3f}s peak_mem={peak:.2f}GB")
torch.cuda.reset_peak_memory_stats()

记录频率建议固定为每若干步一行,不要遇到问题时改成每步、平时又关掉,那样日志本身就成了变量。显存峰值如果出现台阶式抬升,先回看那个迭代数附近改了什么配置。

DMAD 训练侧盯显存和步数——推理侧只比同一批提示词的出图

整理一批固定提示词作为推理侧标尺

推理侧只做一件事:比较同一组输入下的出图。提示词条数不必多,建议 20 到 50 条,覆盖人物、室内场景、文字与标牌、多物体结构、风格化插画这几类容易暴露问题的主题,另留少量自己业务里的真实用例。条目太少时单张图的随机波动会被误读成训练效果变化。

种子、分辨率、采样器、采样步数、CFG 这些设置必须和提示词存在同一个文件里,跟着提示词集一起改版本号,不要放在聊天记录或临时脚本里:

{
  "prompt_set": "dmad-baseline-v1",
  "resolution": [1024, 1024],
  "seed": 12345,
  "sampler": "euler",
  "steps": 28,
  "cfg": 7.0,
  "items": [
    {"id": "p01", "topic": "人物半身", "prompt": "……"},
    {"id": "p02", "topic": "室内场景", "prompt": "……"},
    {"id": "p03", "topic": "文字与标牌", "prompt": "……"},
    {"id": "p04", "topic": "多物体结构", "prompt": "……"},
    {"id": "p05", "topic": "风格化插画", "prompt": "……"}
  ]
}

这个文件提交进版本库,提示词集升级时新建 v2,不要就地改 v1。否则过一段时间回头看,说不清当年的出图是用哪版提示词跑出来的。

DMAD 训练侧盯显存和步数——推理侧只比同一批提示词的出图

训练中途暂停并出图观察

看训练进展是否体现在出图上,最直接的办法是在检查点处停下来出一批图,而不是等训练结束再看。流程建议固定成下面几步,每次照做:

  1. 在预设的迭代数停下训练,确认检查点文件已经完整写盘(大小稳定、可正常加载)。
  2. 用固定的推理脚本加载该检查点,读取同一份提示词集文件,不改采样器、步数、CFG。
  3. 出图写入以迭代数命名的目录,例如 samples/iter_20000/,文件名沿用提示词 id。
  4. 与上一个检查点的同名图并排对比,只记录差异描述,不急着改参数。

这里最容易被破坏的是“推理设置不变”。中途顺手把采样步数从 28 调到 40,或换了分辨率,比较就失去意义。如果确实需要试新参数,另开一组目录并标注参数,不要混进主对比序列。

两侧结论不一致时先回到训练侧核对

常见的不一致是:日志看着没问题,出图却变差;或者损失还在波动,出图反而稳定。这时候优先核对训练侧,因为训练侧的改动影响是全局的,而推理参数改动影响有限且容易被回滚。

DMAD 训练侧盯显存和步数——推理侧只比同一批提示词的出图
典型情形先核对什么
损失明显抖动,出图看不出变化学习率、优化器配置是否被改;日志是否被断点续训打断
出图细节发糊,损失曲线平稳检查点取自哪个迭代数;数据是否换了一版;分辨率是否和训练一致
出图构图或色调整体突变提示词集版本、种子、分辨率、采样器是否被动过
单步耗时变长、显存峰值抬高batch、梯度累积、是否开启了额外的记录或保存

核对顺序建议是:先看训练日志是否连续、有没有断点续训造成的跳变;再看显存峰值与单步耗时是否在同一迭代数出现拐点;然后确认检查点是不是完整、是不是你想要的那个迭代数;最后才动推理参数。按这个顺序走,多数情况下问题在训练侧就能定位,不必反复换采样器。

确定一组可复用的训练与推理搭配

找到一组能稳定出图的搭配之后,要把它固化下来,而不是留在命令行历史里。配置快照至少保存三类字段:训练侧(数据版本、分辨率、batch、梯度累积、学习率、优化器、精度、总迭代数、显存峰值、单步耗时)、推理侧(提示词集版本、种子、分辨率、采样器、步数、CFG)、环境(卡型号、驱动与框架版本)。环境字段容易被忽略,但换机器后出图不一致,往往就出在这里。

runs/dmad_<日期>_<数据版本>_iter<迭代数>_<提示词集版本>/
  train.yaml        # 训练侧配置快照
  infer.yaml        # 推理侧配置快照
  prompt_set.json   # 本次使用的提示词集
  metrics.csv       # iter, loss, step_time, peak_mem
  samples/          # 按 iter 分子目录,文件名用提示词 id

命名建议把数据版本、迭代数、提示词集版本都带上,靠目录名就能判断两组实验差在哪。同一个目录下同时放训练与推理快照,是为了一年后还能复现这批出图;如果只存检查点不存配置,复现成本会高很多。这套做法在单机小规模实验里通常够用,多机或频繁改数据管线的场景需要结合自己的日志系统再确认。