返回专辑
·Johan·5 分钟阅读

DANN 梯度反转与 AdaBN

源域训、目标域测掉点是常态——纯 finetune、DA 方法或采目标域数据,取舍看标注成本和失败 slice 有多痛。

DANN 梯度反转与 AdaBN

1. 晴天训、雨夜测:先量化 gap

视觉模型在源域(白天、干燥路面)训好,部署到目标域(雨夜、眩光)掉点——这不是「再训几 epoch」能解决的,是 domain shift。团队常犯的错误:未量化 gap 就上复杂 DA 方法,或指望无 target label 的 zero-shot 奇迹,汇报时又不报 source-only baseline。

第一步永远是量化:在 target 上跑 source-only 模型,按 slice(天气、时段、场景、传感器批次)报 metric,定位最痛的 failure mode。再决定路线:增广模拟、无标 DA、少量 target 标签 fine-tune,或三者组合。标注成本是核心约束——每张 target 标签若需人工框选,few-shot fine-tune 的 ROI 往往高于纯 DANN。汇报时若只给「DA 后涨 X 点」而不给 source-only 基线,现场无法判断这 X 点值不值得额外算力与工程复杂度。域适应不是万能胶:gap 来自传感器物理差异时,增广与 BN 统计往往比对抗训练先见效。

domain shift 可粗分为 covariate shift(输入分布变、标签条件 近似不变)与 label shift(类先验变)。视觉 outdoor 多数是前者:雨夜改变像素统计,车道线几何与语义仍一致。若 target 出现 source 从未见过的类或标注定义变化,无标 DA 天花板很低,应直接要标注。量化 gap 时除 aggregate metric,还要看 per-slice 置信度分布——某 slice 上 softmax 熵系统性偏高,往往是 domain 未对齐而非单纯难例。

2. DANN:梯度反转学 domain-invariant 特征

Ganin 的 DANN 在 feature extractor 后挂 domain classifier,通过梯度反转层(GRL)让 encoder 骗过 domain 判别器,学 domain-invariant representation:

python
class GradReverse(torch.autograd.Function):
    @staticmethod
    def forward(ctx, x, lambd):
        ctx.lambd = lambd
        return x.view_as(x)
    @staticmethod
    def backward(ctx, grad):
        return grad.neg() * ctx.lambd, None

feat = encoder(x)
L_task = F.cross_entropy(head(feat), y)
L_dom = F.cross_entropy(
    domain_clf(GradReverse.apply(feat, lambd)), d)
loss = L_task + L_dom

lambd 随 epoch 从 0 schedule 到 1——前期让 task head 先收敛,后期加大 domain 对抗。实现上常用 lambd = 2/(1+exp(-10*p)) - 1,其中 p 为训练进度 0→1。CORAL 在特征层最小化 source/target 协方差差,无 adversarial 训练更稳;MMD 对齐分布距离。gap 极大时 DANN domain classifier 易 dominate,task loss 被压制,需调 domain loss 权重。

DANN 的工程契约是 source 有标、target 无标但可 forward:训练 batch 混 source(带 )与 target(只带 domain id )。domain classifier 通常 2–3 层 MLP,挂在 global pool 后的 feature 上;encoder 越深,GRL 作用点越靠语义层,对齐越强但也更易伤 task。CORAL 损失形如 为 batch 特征协方差,实现简单、不引入额外判别器,适合 gap 中等、算力有限的团队。MMD 用核技巧估分布距离,对 batch size 敏感——target unlabeled 不足时 MMD 估计方差大,曲线抖。对抗路线与矩匹配可叠加,但 loss 权重须 ablation,否则难以归因。

3. AdaBN 与增广:无 label 时的低成本选项

AdaBN:在 target 域 unlabeled 数据上跑 forward,更新 BatchNorm 的 running mean/var,不改权重。实现零成本,对「光照/统计偏移为主、语义不变」的场景常有效——前提是 backbone 含 BN 且 target 数据量足够估 stats(通常数百张以上)。SyncBN 或 GN backbone 上 AdaBN 不适用,需换路线。

增广模拟 target:color jitter、blur、noise、rain overlay——对自动驾驶等 outdoor 场景是 first-line 手段,不依赖 target label。有少量 target label(few-shot,几十到几百张)时,fine-tune last layers 通常 ROI 最高;全量 fine-tune 学习率过大易 destroy source knowledge,应分层 LR 或只解冻 head + 最后几层,monitor source val 不掉 cliff。

AdaBN 的隐含假设是:语义由 conv 权重编码,域偏移主要体现在 BN 的一阶二阶矩。target forward 时 model.train() 或专用 eval+momentum=0 刷新 running stats,再 eval 推理。stats 刷新 batch 数不足时 mean/var 噪声大,target metric 反而不如 source stats。增广与 AdaBN 可并行:增广在 source train 阶段缩小 gap,AdaBN 在 deploy 前用 target 无标数据对齐 moment。few-shot fine-tune 建议 head 大 LR、backbone 小 LR 或冻结,并用 early stopping 盯 source val——业务常要求双域可用,target 涨 5pt、source 掉 10pt 往往不可交付。

4. 失败模式

无 label 期望 miracle:AdaBN + 增广仍掉点大时,应承认需要 target 标注,而非堆更复杂 DA。source 太少:DANN domain classifier 过拟合 source 域 id,反而伤害 task。fine-tune 全量 LR 太大:source val 崩而 target 略涨——业务若需双域可用,这是不可接受的 tradeoff。混 batch 时 domain label 错配会 poison GRL。

另一类隐蔽失败是 target 无标数据与 deploy 分布不一致:用白天 target 视频刷新 BN,雨夜 deploy 仍掉点——AdaBN 只适应「你喂给它」的统计。DANN 训练若 target 图像分辨率或 crop 与 source 不一致,domain classifier 学到的是尺度差异而非域语义,GRL 会错误压制有用特征。汇报 slice 时应用同一套 checkpoint 与 eval 协议,避免 source 报 EMA、target 报 last epoch 造成虚假 gap 缩小。

5. 案例:雨夜 slice 掉 twenty 点,AdaBN 先救一半

某车道线检测,source 白天 mIoU 0.82,target 雨夜 0.62。DANN 训完 target 0.68,AdaBN 单独 0.71,增广+AdaBN 0.73。 fifty 张雨夜人工标注 fine-tune head 后 0.78——说明 gap 里一半是统计偏移、一半是语义/几何偏移。汇报若只报 DANN 0.68 而不报 baseline 0.62,会高估 DA 价值。

6. 验收

  • 必报三条曲线:source-only on target、DA 方法 on target、few-shot fine-tune on target。
  • 按 failure slice(雨/夜/雾)分别报 metric,不只看 aggregate。
  • DANN:lambd schedule 与 domain loss 权重做 ablation;AdaBN 对比「不更新 BN stats」。
  • fine-tune 时监控 source val——不应为 target 增益大幅牺牲 source 性能(除非业务接受)。
  • GroupSplit 按 scene_id 划分,避免 target 场景泄漏进 source train。

域适应的取舍看标注成本:无 label 先试 AdaBN + 增广;有少量 label 优先 few-shot FT;DANN/CORAL 在 gap 大且 unlabeled target 充足时再上。改一项时固定 seed 与 batch,日志含 task loss、domain loss、lr,才分得清是对齐有效还是过拟合 domain id。双域部署还须约定:source 性能下限能否牺牲、target 上哪些 slice 必须单独达标——否则 fine-tune 把 source 拉垮也是常见失败。

← 全部文章

johan's blog