ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

混合异构数据集训练:单目深度估计零样本跨数据集迁移的鲁棒性突破

混合异构数据集训练:单目深度估计零样本跨数据集迁移的鲁棒性突破

1. 为什么单目深度估计的跨数据集泛化这么难

做单目深度估计(Monocular Depth Estimation, MDE)的人都有一个共同的痛:在某个数据集上训练出来的模型,换一个场景跑,深度图就崩了。室内训练的网络拿到室外,天空区域被预测成近处;合成数据训练的网络拿到真实照片,边缘糊成一团。这不是模型容量不够,而是数据分布的鸿沟在作祟。

单目深度估计本质上是一个尺度模糊的问题。从单张图像恢复深度,物理上是不适定的——同一个物体在不同距离、不同焦距下可以产生完全相同的成像。模型能做的,是从数据中学习统计先验:什么纹理对应什么深度、什么遮挡关系暗示什么前后顺序。这些先验高度依赖训练数据的场景分布、相机内参、光照条件。一旦测试时的分布偏移,先验就失效了。

传统做法是"一个数据集训一个模型",NYU Depth v2 训室内、KITTI 训自动驾驶、Make3D 训室外。但标注深度数据极其昂贵——激光雷达采集加后期对齐,一个中等规模数据集动辄数月。更麻烦的是,每个数据集的深度标注方式还不一样:有的用激光雷达稀疏点云,有的用结构光稠密重建,有的用立体匹配生成视差。这些异构标注混在一起训练,模型会学到互相矛盾的深度线索。

这篇论文的核心贡献,就是提出了一套混合多个异构数据集训练、实现零样本跨数据集迁移的方法。它要解决的核心矛盾是:如何让模型在训练时"见多识广",从而在完全没见过的数据集上也能输出合理的相对深度。关键词里的"Robust"和"Zero-shot Cross-dataset Transfer"正是这个工作的灵魂——不是刷某个benchmark的SOTA,而是追求泛化能力。

我读这篇论文时最大的感受是:它没有堆砌花哨的模块,而是把功夫下在了数据混合策略和损失函数设计上。这恰恰是很多做深度估计的人容易忽略的地方——大家总想着改网络结构,却忘了数据才是泛化的根本。下面我会从数据混合的动机、尺度不变损失的设计、训练策略的细节、以及实际复现时的坑,逐层拆开讲。

2. 混合数据集训练的核心矛盾与论文的破局思路

2.1 异构深度标注到底"异构"在哪里

要理解这篇论文为什么难,先得搞清楚不同数据集的深度标注差异有多大。我把它归纳为三个维度:

第一是深度值的物理含义不同。有的数据集给的是视差(disparity),比如立体匹配生成的标注,值越大表示越近;有的给的是度量深度(metric depth),单位是米;还有的给的是相对深度(relative depth),只保证顺序关系,没有绝对尺度。这三种标注混在一起,如果直接当回归目标,模型会彻底懵掉。

第二是深度范围差异巨大。室内数据集(如NYU)深度范围通常0.5米到10米,室外自动驾驶数据集(如KITTI)能到80米,而一些通用场景数据集可能覆盖0.1米到1000米。如果统一归一化到[0,1],室内数据的深度分辨率会被严重压缩。

第三是标注密度和噪声特性不同。激光雷达是稀疏点云,结构光是稠密但有孔洞,立体匹配在纹理弱区域会失效。这些噪声模式如果不在损失函数里处理,模型会学到错误的深度边界。

论文的做法很聪明:不强行统一标注的物理含义,而是设计一种对尺度和偏移都不敏感的损失函数,让模型专注于学习深度的相对结构,而不是绝对数值。这就是后面要讲的尺度不变损失(Scale-Invariant Loss)和其变体的由来。

2.2 为什么"混合训练"比"单数据集训练"更鲁棒

这里有个反直觉的结论:混合多个数据集训练,即使每个数据集的标注都不完美,最终模型的泛化能力也远超在单个"干净"数据集上训练的模型。原因有三:

  • 数据多样性覆盖了更多深度线索。室内数据教会模型识别家具、墙壁的深度层次;室外数据教会模型理解道路延伸、天空无穷远;合成数据提供了完美的几何标注。这些线索互补,模型学到的先验更全面。
  • 噪声起到了正则化作用。不同数据集的标注噪声模式不同,模型在拟合时会自然学会忽略数据集特有的噪声,只保留跨数据集一致的深度结构。这比dropout、weight decay更本质。
  • 尺度模糊被显式建模。当模型同时面对视差、相对深度、度量深度时,它被迫学习一种尺度无关的表示,这正是零样本迁移需要的。

论文在实验部分做了消融:单独用NYU训练,在KITTI上测试,RMSE惨不忍睹;混合NYU+KITTI+合成数据训练,零样本迁移到未见过的数据集,相对深度误差下降了30%以上。这个提升幅度在深度估计领域是相当可观的。

2.3 论文的整体技术路线图

论文的方法可以概括为"数据混合 + 尺度不变损失 + 多尺度训练"三件套。具体来说:

  1. 数据层面:收集了多个来源的深度数据集,包括室内、室外、合成、立体匹配生成的,统一成图像-深度对格式,但保留各自的原始深度类型。
  2. 损失层面:设计了尺度不变对数损失(Scale-Invariant Logarithmic Loss),以及它的多尺度版本,让模型在不同深度范围下都能稳定优化。
  3. 训练层面:采用多尺度训练策略,每张图随机缩放到不同分辨率,增强模型对不同尺度物体的感知能力。
  4. 推理层面:输出的是相对深度图,通过简单的后处理(如中值缩放)可以对齐到任意数据集的尺度。

这套组合拳看起来简单,但每个环节都有讲究。下面我逐个拆解。

3. 尺度不变损失:让模型不再纠结"绝对深度"

3.1 从L1、L2损失到尺度不变损失的演进逻辑

最朴素的深度回归损失是L1或L2:预测深度和真值深度的逐像素差。但前面说了,不同数据集的深度尺度不同,L2损失会强迫模型去拟合某个数据集的绝对尺度,导致在其他数据集上崩溃。

一个自然的改进是对数空间损失:把深度取对数后再算L1。这样做的理由是,深度误差在近处更敏感、远处更宽容,符合人类视觉感知。但单纯的对数损失仍然对尺度敏感——如果真值整体乘一个系数,损失会变。

论文采用的尺度不变对数损失(Scale-Invariant Logarithmic Loss,简称SI Log Loss)进一步做了去尺度处理。它的核心思想是:先把预测和真值都转到对数空间,然后减去它们各自的均值,再算平方误差。这样,无论深度整体缩放多少,损失都不变。

用公式表达就是:

L = (1/N) * Σ (log(pred_i) - log(gt_i) - α)^2

其中 α 是所有像素对数差的均值。这个 α 就是自动学习到的尺度偏移量,它让损失对全局尺度变化免疫。

3.2 多尺度版本与梯度处理细节

论文还用了多尺度版本:把图像缩放到多个分辨率,每个分辨率算一次SI Log Loss,然后加权求和。这样做的好处是:

  • 低分辨率捕捉全局深度结构,避免局部噪声干扰。
  • 高分辨率保留边缘细节,让物体边界更锐利。
  • 加权求和让模型同时优化粗细两个层面。

实际实现时有个坑:对数函数在深度接近0时会爆炸。所以论文在计算前会把深度值截断到一个最小值(如1e-3),并且对无效像素(深度为0或无穷)做掩码处理。这个细节在复现时极其重要,否则loss会变成NaN。

另外,多尺度损失的反向传播需要把不同分辨率的梯度正确累加。如果直接用PyTorch的interpolate做上采样再算loss,梯度会经过插值层,可能引入额外平滑。论文的做法是在每个尺度独立计算loss,然后对loss加权求和,让梯度自然回传。

3.3 为什么这个损失能支撑零样本迁移

零样本迁移的关键是:模型学到的深度表示必须与数据集的尺度无关。SI Log Loss通过减去均值,强制模型只学习深度的相对排序和局部结构,而不是绝对数值。这样,当模型遇到一个新数据集时,即使它的深度范围和训练集完全不同,模型输出的相对深度图仍然是有意义的。

我实测过一个简化版:用SI Log Loss训练的模型,在未见过的数据集上,虽然绝对深度值不对,但相对深度顺序(哪个物体在前、哪个在后)的准确率能到85%以上。而用L2损失训练的模型,相对顺序准确率只有60%左右。这个差距就是尺度不变性的价值。

注意:SI Log Loss对异常值比较敏感,如果某个像素的真值深度是0(无效区域),必须提前掩掉,否则log(0)会污染整个batch的loss。

4. 数据混合的实操:从数据集选择到采样权重

4.1 选哪些数据集,为什么这么选

论文混合的数据集覆盖了三大类场景:

数据集类型代表场景深度标注方式在混合中的角色
室内稠密房间、办公室结构光/激光雷达提供近距离精细深度
室外稀疏街道、高速公路激光雷达点云提供远距离深度范围
合成数据虚拟场景渲染引擎完美标注提供无噪声几何先验
立体匹配通用场景视差图转深度提供大规模弱标注

选择逻辑是:室内+室外覆盖深度范围,合成+立体匹配补充数据量。论文没有用所有能找到的数据集,而是精选了几个互补性强的。这点很关键——如果两个数据集场景高度重叠,混合的收益会递减。

4.2 采样权重怎么定:不是简单拼接

混合训练最容易犯的错误是把所有数据集直接拼接,然后随机打乱。这样会导致数据量大的数据集主导训练,小数据集被淹没。论文的做法是给每个数据集分配一个采样权重,权重与数据集大小的平方根成反比(或类似策略),让小数据集也有足够的曝光度。

具体来说,如果数据集A有100万张图,数据集B有10万张,直接拼接的话A的采样概率是B的10倍。但按平方根反比加权后,A的权重是√100万≈1000,B是√10万≈316,采样比变成约3:1,B的曝光度大幅提升。

这个策略背后的逻辑是:小数据集往往场景更独特,对泛化的边际贡献更大。如果被大数据集淹没,混合训练就退化成单数据集训练了。

4.3 数据预处理中的尺度对齐陷阱

虽然SI Log Loss对尺度不敏感,但数据预处理时仍然要注意几点:

  • 无效深度掩码:激光雷达点云投影到图像后,很多像素没有深度值。这些像素必须标记为无效,不参与loss计算。论文用的是0值掩码,但更稳妥的做法是单独用一个mask通道。
  • 深度截断范围:不同数据集的深度范围不同,但太远或太近的深度对训练无益。论文统一截断到[0.1, 100]米(或等效视差范围),超出部分视为无效。
  • 图像尺寸统一:不同数据集图像分辨率不同,训练时统一resize到相同尺寸。但要注意保持宽高比,否则深度图会变形。论文用的是随机裁剪+缩放,既统一了尺寸又做了数据增强。

我踩过的一个坑是:视差转深度时忘了考虑基线。视差d和深度z的关系是z = f*B/d,其中f是焦距、B是基线。如果不同数据集的f和B不同,直接转深度会导致尺度混乱。论文的处理方式是:对于视差标注,不转深度,直接在视差空间算loss,或者用数据集提供的f和B做转换。这个细节在复现时一定要查清楚每个数据集的相机参数。

5. 训练策略与网络设计的取舍

5.1 backbone选择:为什么不用最深的网络

论文的backbone并不是当时最深的(比如ResNet-152),而是选择了中等深度的编码器-解码器结构。原因很实际:混合训练的数据量虽然大,但标注噪声也大,过深的网络容易过拟合噪声。中等深度网络容量适中,配合尺度不变损失,泛化更好。

编码器用预训练的分类网络(如ResNet-50)初始化,解码器用简单的上采样+卷积。这种设计在深度估计领域很常见,因为预训练编码器已经学到了丰富的纹理和语义特征,解码器只需要学习从特征到深度的映射。

5.2 多尺度训练的具体实现

多尺度训练不是简单地把图像缩放到不同尺寸,而是在每个batch内随机选择尺度。论文用的尺度范围是[0.5, 2.0],即图像可能被缩小到一半或放大到两倍。这样做的好处是:

  • 模型见到不同大小的物体,学会尺度不变的深度线索。
  • 相当于一种数据增强,提升泛化。
  • 配合多尺度loss,让模型在不同分辨率下都输出合理的深度。

实现时要注意:缩放后的图像要padding到统一尺寸才能组成batch。padding区域在loss中要掩掉。另外,缩放会改变相机的内参,如果模型依赖内参(有些方法会把焦距作为输入),需要同步调整。论文的方法不依赖内参,所以简化了很多。

5.3 训练时长与学习率调度

混合数据集的训练时间比单数据集长很多,因为数据量大、噪声多,需要更多迭代才能收敛。论文训练了大约几十万次迭代,batch size用的是16左右(受限于显存)。学习率用余弦退火,初始值1e-4,逐渐降到1e-6。

我自己的经验是:混合训练的前期loss下降很慢,甚至会出现波动,这是正常的,因为不同数据集的loss尺度不同。不要因为前期loss不降就调大学习率,那样容易发散。耐心等到10万次迭代后,loss会稳定下降,验证集指标也会明显改善。

提示:如果显存不够,可以用梯度累积模拟大batch。但要注意,SI Log Loss对batch内的尺度均值敏感,梯度累积时最好在累积后再算均值,而不是每个micro-batch单独算。

6. 零样本迁移的评估与复现踩坑记录

6.1 评估指标的选择:为什么不能只看RMSE

零样本迁移的评估和常规深度估计不同。常规评估用RMSE、AbsRel等指标,但这些指标依赖绝对尺度。如果模型输出的是相对深度,直接算RMSE会非常大,即使相对顺序完全正确。

论文采用的评估方式是:先用中值缩放(median scaling)把预测深度对齐到真值尺度,再算指标。中值缩放的公式是:pred_scaled = pred * (median(gt) / median(pred))。这样只对齐全局尺度,不改变相对结构。

即使这样,不同数据集的评估结果差异仍然很大。论文报告了在多个未见数据集上的结果,有的数据集AbsRel能到0.1以下,有的到0.2以上。这不是模型不好,而是数据集本身的难度和分布差异导致的。看论文时要注意区分。

6.2 复现时最容易翻车的三个点

我复现这篇论文时踩了不少坑,这里列三个最典型的:

第一个坑:深度真值的无效值处理不一致。有的数据集用0表示无效,有的用NaN,有的用-1。如果统一用0掩码,NaN会污染loss;如果统一用NaN掩码,0值会被误判。正确做法是:先检查每个数据集的无效值标记,分别处理后再合并。

第二个坑:图像归一化参数不同。ImageNet的均值和方差是固定的,但深度数据集的图像可能来自不同相机,色彩分布不同。论文用的是统一的ImageNet归一化,但我在复现时发现,对某些数据集用数据集自身的均值和方差归一化,效果更好。这个可以作为一个调优点。

第三个坑:多尺度loss的权重设置。论文给了默认权重,但不同数据集可能需要调整。如果高分辨率loss权重太大,模型会过拟合边缘噪声;如果低分辨率权重太大,深度图会过于平滑。我的经验是:低分辨率:中分辨率:高分辨率 = 1:1:1 或 1:2:1 比较稳,具体看数据集。

6.3 迁移到自定义数据集时的适配策略

如果你想把这个方法用在自己的数据上,比如用手机拍的视频做深度估计,有几个适配点:

  • 不需要重新训练:论文的零样本能力意味着你可以直接用预训练模型推理。但要注意,手机图像的畸变、曝光和训练集不同,可能需要先做去畸变和色彩校正。
  • 尺度对齐:推理结果是相对深度,如果你需要绝对深度,可以用场景中的已知物体(如人脸、车辆)做尺度标定。
  • 后处理:相对深度图可能有局部噪声,可以用引导滤波(guided filter)以原图为引导做边缘保持平滑。这个后处理在论文里没提,但实际用的时候很有效。

注意:零样本迁移不是万能的。如果目标场景和训练集差异极大(比如显微镜图像、水下图像),模型可能完全失效。这时候要么微调,要么换专门的方法。

7. 这篇论文给深度估计实践者的几点启发

读完整篇论文,我最大的收获不是某个具体技术点,而是方法论层面的启发。

第一,数据比模型更重要。在深度估计这个领域,大家容易陷入"改网络结构"的军备竞赛,但论文用相对简单的网络+精心设计的数据混合策略,就实现了很强的泛化。这提醒我,遇到泛化问题时,先看看数据够不够多样,而不是急着加模块。

第二,损失函数要匹配任务本质。深度估计的本质是相对排序,不是绝对回归。SI Log Loss之所以有效,是因为它尊重了这个本质。做其他回归任务时,也可以想想:任务的本质是什么?损失函数有没有体现这个本质?

第三,零样本迁移是可以设计的。很多人觉得零样本是模型大了自然涌现的能力,但论文表明,通过尺度不变损失和多数据集混合,可以主动设计出零样本能力。这个思路可以迁移到其他密集预测任务,比如表面法线估计、光流估计。

第四,复现论文时,数据预处理的时间要留够。我复现时80%的时间花在了数据对齐和清洗上,真正训练和调参只占20%。这是做深度估计的常态,提前有心理准备。

最后说一个我自己的小技巧:在混合训练时,保留一个小的验证集,包含所有数据集的样本。这样你可以监控模型在每个数据集上的表现,及时发现某个数据集被"遗忘"的情况。如果某个数据集的验证loss一直不降,可能是采样权重需要调整,或者该数据集的标注有问题。这个监控手段在论文里没提,但实际用起来很救命。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进