687. CSIRO - Image2Biomass Prediction | csiro-biomass
首先,我要感谢 Kaggle、赞助商和研究团队举办这次比赛。起初,我确实觉得数据集太小了。然而,随着比赛的进行和榜单的巨大波动,很明显数据集小在某种程度上是必要的。这一点在我被公共榜单 (Public LB) 的顶尖选手包围在私有榜单 (Private LB) 上时得到了进一步证实,公共榜单的第 1、2、3 名在私有榜单上分别获得了第 38、35、36 名,而我从公共榜单的第 49 名上升到了私有榜单的第 37 名,因此被顶尖选手包围。有限的数据强烈 penalize 了过拟合,迫使参与者面对解决方案的真正泛化能力。事后看来,这一约束是比赛最有价值的方面之一。
我还要感谢 Qiyu Liao,他是我见过的在此类 Kaggle 比赛中最积极、最支持参赛者的比赛主持人之一。无论是澄清疑问、回复讨论,还是在参与者公开分享发现时给予鼓励,您的存在显著提升了比赛的协作精神。💙
在澄清疑问方面,还要特别提到 PC Jimmy 先生。在调试和澄清疑问方面,您始终做得超出预期。整个 Notebook 都被仔细检查,每个问题都得到了解决,解释得非常清晰和耐心,经常将复杂问题分解为最简单的形式。这种无私且不求回报的做法深受鼓舞,充分说明了这个社区的力量。您是一个巨大的鼓励,展示了一个人可以多么支持他人。
除了最终解决方案外,我在整个比赛期间积极分享了见解和实验结果。我的两篇讨论帖子成为了比赛中第 2 高和第 5 高 投票的讨论。这些讨论主要集中在澄清建模歧义,特别是围绕 Dead Matter 目标,并提出实用策略来处理其固有的不一致性。我相信这些讨论有助于早期暴露重要问题,并鼓励社区设计更稳健的解决方案。
我尝试了几种强大的视觉骨干网络,包括 DINOv2、DINOv3 和 EVA02。其中,EVA02 在早期实验中特别有趣,因为与 DINOv2 和 DINOv3 相比,它以更少的努力 consistently 实现了更高的交叉验证分数。
然而,尽管 EVA02 的交叉验证表现很有希望,但它在榜单上 consistently 表现不如 DINOv3。此外,基于 DINOv3 的模型在训练损失和验证损失之间表现出明显较小的差距。这种差异强烈表明 DINOv3 正在学习更好地泛化到训练分布之外的表示。
解释很大程度上根植于 DINOv3 的训练方式。其自监督学习目标,加上其通过 Gram 矩阵信息保留丰富二阶统计量的能力,使其非常适合密集预测和回归风格的任务。在这次比赛的背景下,微妙的空间线索比明确的语义类别更重要,这一属性被证明是至关重要的。
在尝试了许多架构变体后,最终模型是围绕视觉提示微调 (Visual Prompt Tuning) 结合 DETR 风格的查询 token 构建的,我在这里称之为任务 token。
除了标准的图像 patch 嵌入外,我在 DINOv3 的输入中附加了两种类型的可学习 token。第一种类型由四个任务 token 组成,每个目标变量一个,其中 Dead 目标是派生的。第二种类型由十六个提示 token 组成,旨在引导骨干网络朝向任务相关的表示。
在前向传播期间,所有 token 由骨干网络共同处理。从输出中,我提取了与每个目标对应的任务 token 嵌入,以及来自 patch token 的全局平均池化和标准差池化特征。这些表示被连接起来并通过特定于目标的头产生最终预测。注意,每个目标头只接收其对应的任务 token 以及 GAP 和 STD,而不是其他任务 token。
在监控训练动态时,我观察到任务 token 和提示 token 逐渐收敛到非常相似的表示。这种 collapse 显著降低了拥有多个 token 的有效性。
为了 counteract 这一点,我引入了一个显式的正交损失,鼓励 token 保持去相关。这确保了每个 token 专注于捕获输入的不同方面,而不是冗余地编码相同的信息。添加此约束被证明对稳定收敛和提高鲁棒性至关重要。您可以假设它执行与 MHSA(多头自注意力)中的多头相同的角色。
为了进一步提高收敛性,我采用了自提示微调 (Self Prompt Tuning) 的想法。
对于每个目标变量,我选择了十个具有最高目标值的训练样本。从这些样本中,我提取了 CLS token 嵌入并计算它们的均值。然后使用该均值表示来初始化相应的任务 token。相同的程序应用于初始化提示 token,其中十六个提示 token 被分为四组(鼓励每个目标一组)。
然而,这种初始化策略自然会导致正交损失急剧增加,因为所有 token 都从相关表示开始。为了解决这个问题,我在初始化时应用了 Gram Schmidt 正交化,确保所有 token 在训练开始前相互正交。这允许了知情初始化的好处,而不会牺牲 token 的多样性。
在比赛的第一个月内,我意识到交叉验证策略的选择将主导其他一切。我早期就详细分享了这一见解,包括实现细节,这在后来成为了比赛中投票最多的讨论。然而,大多数人都忽略了这一策略。
最初的策略涉及蒙特卡洛种子搜索,结合基于 State 和 Sampling Date 的 GroupKFold 拆分,这是基于早期的猜测,即某些 State 可能完全不在测试集中。后来比赛主持人的澄清确认所有 State 都存在于测试数据中,而只有特定的站点或位置可能是未见过的。基于此,我将策略简化为仅基于采样日期的 State 分层 GroupKFold 拆分。
即使在早期榜单分数约为 0.63 时,交叉验证和榜单性能之间的一致性也非常惊人。平均交叉验证 R 平方分数与榜单分数非常接近,折叠之间的方差很小。这种一致性贯穿了整个比赛,并作为一个强烈的信号,表明建模选择正确地针对了可泛化的模式,而不是利用验证 artifacts。
随着比赛的进行,训练时间大幅增加,而数据集本身仍然非常小,只有 357 张图像。同时,我想利用 Chris Deotte 先生推广的一个众所周知的想法,即在从交叉验证估计最佳训练持续时间后,在全数据集上重新训练模型。
虽然这种方法最常用于表格模型(如 XGBoost),但 underlying 原则仍然适用于此处。我在全数据集上训练模型,没有任何验证,直到它们达到交叉验证期间观察到的平均训练损失。与集成交叉验证模型相比,这种方法 consistently 产生了稍好的榜单性能,强化了在这种情况下数据效率比验证监控更重要的想法。
我广泛尝试了双流架构,其中输入图像被分成两半。最初,我连接了来自每一半的嵌入,并将它们共同传递给预测头。虽然这效果相当好,但它增加了模型复杂性和对噪声的敏感性。
然后我转向双流求和方法,其中每一半独立产生预测,结果相加。然而,这种公式存在一个根本限制。没有监督信号表明哪一半对误差贡献更大,并且对比损失不直接适用。尝试使用来自强集成生成的伪标签来解决这个问题并没有产生改进。
突破来自于从求和切换到均值聚合。在这种设置中,每个流被迫仅使用一半的可用信息来预测整个区域的生物量。这种有意的信息瓶颈 dramatically 提高了鲁棒性,并显著减少了训练和验证损失之间的泛化差距。
此时,自然出现了一个问题。如果模型已经可以在仅观察一半图像的情况下预测整个区域的生物量,那么它真正依赖多少视觉信息?
为了调查这一点,我使用从原始 1000x2000 图像中采样的 448x448 随机裁剪来训练模型。这将模型限制在每次前向传播中总图像区域的大约百分之十。尽管存在严重的信息瓶颈,模型 continue 表现良好,并实现了 0.6 以上的榜单分数,表明它正在学习全局和纹理线索,而不是记忆局部模式。
然后我使用多裁剪训练策略扩展了这个想法。每张图像采样多个随机裁剪,独立进行预测,并将它们的均值与 ground truth 进行比较以计算损失。使用两个裁剪时,出现了一个重要的平衡点。训练、验证和榜单 R 平方分数都收敛到大约 0.72。这种一致性表明模型已有效地停止过拟合,使得验证变得多余。在这个阶段,我过渡到在没有验证拆分的情况下在全数据集上训练。
随着裁剪数量的增加,行为变得令人惊讶。训练 R 平方分数迅速上升,使用 3 个裁剪时,我得到了 0.85 的训练 R2,但验证分数保持在 0.72。等等,什么?即使使用八个随机裁剪,覆盖几乎整个图像,验证性能也保持在 0.72 左右。这意味着虽然模型正在学习噪声,但它并没有忘记真正可泛化的特征。
当这些模型在全数据集上训练并在榜单上评估时,出现了一个清晰的模式。
训练 R 平方与榜单分数的关系
| 训练 R² | 榜单分数 |
|---|---|
| 0.72 | 0.72 |
| 0.80 | 0.72 |
| 0.85 | 0.73 |
| 0.90 | 0.74 |
| 0.92 | 0.75 |
| 0.95 | 0.75 |
经验上,训练 R 平方每增加大约 0.05,榜单上就会提高约 0.01。这种反直觉的效果最终塑造了我的最终策略。我没有积极地防止过拟合,而是以受控的方式允许它,相信通过严重信息瓶颈和自监督预训练学习到的通用表示将保持稳定。在这个阶段,值得再次注意的是,我根本没有触碰骨干网络。
在推理期间,每张图像被分成 500x500 的 tiles,因此从 1000x2000 图像中提取 8 个 tiles,从中提取中心的 448x448 裁剪。测试时增强 (TTA) 仅限于简单的几何翻转,包括水平、垂直和组合翻转。未应用后处理。
对于最终提交,我集成了从上述同一训练运行中获得的多个 checkpoints。我还尝试了指数移动平均 (EMA) 和随机权重平均 (SWA)。虽然这些技术提高了收敛平滑度,但它们并没有meaningfully 提高性能上限。
该解决方案是持续实验、许多失败的想法以及强烈依赖社区驱动学习的结果。我从公开讨论、共享见解和集体调试中受益匪浅。这篇 write-up 是回馈社区的一个小尝试。
我强烈鼓励问题和讨论。这次比赛中最好的想法是通过共享的好奇心和健康的怀疑主义出现的,我希望这有助于这种精神。