687. CSIRO - Image2Biomass Prediction | csiro-biomass
我们的解决方案是三个不同 pipeline 的加权集成,所有 pipeline 均以 DINOv3 Huge 骨干网络为核心。
我们的最终提交结合了:
vit_huge_plus_patch16_dinov3.lvd1689m我想强调仅仅改变骨干网络的影响。以下是进展:
我使用了带有 SiLU 激活和 dropout 的标准回归头。
nn.Sequential(
nn.Linear(in_features, hidden),
nn.SiLU(),
nn.Dropout(0.3),
nn.Linear(hidden, out_features),
)
为了在有限数据上稳定如此大模型的训练,我采用了使用 AdamW 和混合精度 (AMP) 的两阶段训练过程。
nn.SmoothL1Loss()grad_accum_steps=8)。3e-4 配合 ReduceLROnPlateau。0.2 (高衰减对正则化至关重要)。# 阶段 2 调度器配置
CosineLRScheduler(
lr_min=1e-6, # 目标最小学习率
warmup_t=3, # 关键的 3 轮预热
warmup_lr_init=1e-7, # 从接近零开始
cycle_limit=1, # 单周期 (无重启)
t_in_epochs=True
)
我使用了 Albumentations 迫使模型学习不变特征, specifically 使用 RandomShadow 和 RandomGamma 来处理光照变化。
A.Compose([
A.HorizontalFlip(p=0.5),
A.VerticalFlip(p=0.5),
A.RandomRotate90(p=0.5),
A.ColorJitter(brightness=0.2, contrast=0.1, saturation=0.2, p=0.5),
A.RandomGamma(gamma_limit=(80, 120), p=0.3),
A.RandomShadow(num_shadows_limit=(1, 3), shadow_dimension=5, p=0.5),
A.Resize(self.img_size, self.img_size),
A.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
ToTensorV2()
])
我最初尝试使用 sampling_date 进行 GroupKFold,但这导致折间分布方差很高,某些模型未能学习足够的数据变化。这并没有改善公共榜单。
因此,我决定接受交叉验证 (CV) 与公共榜单之间的差异,并使用基于分箱和物种的分层方法最大化 CV 分数。
# 创建结合总生物量分箱和物种的分层键
df['strat_key'] = df['total_bin'].astype(int) * 100 + df['species_id'].astype(int)
skf = StratifiedKFold(
n_splits=self.config.n_folds,
shuffle=True,
random_state=self.config.random_state
)
为了在推理期间有效利用物种元数据(其中元数据可能不可用或不可靠):
dinov3_large 模型(相同头部结构)来从图像分类物种。虽然骨干网络提供了 power,但 Diptyajit 关于目标和分辨率的实验提供了私有榜单 (Private LB) 所需的稳定性和泛化能力。
我们没有直接预测标准目标,而是重构了回归问题以更好地 align 生物成分。
Dry_Green_g, GDM_g, Dry_Total_gDry_Clover_g, GDM_g, Dry_Total_g我 experimented 在阶段 1 中添加辅助 NDVI 回归头 alongside 物种分类。这将 vit_large 模型提升至 0.73,但对 vit_huge_plus 模型的分数影响 negligible。
虽然 768px 提供了最佳公共榜单,但 Diptyajit 的实验显示 640px 提供了 superior 泛化能力,并产生了我们最高的单模型私有榜单 (0.657),但由于公共榜单较低 (0.75),我们无法在最终评估中选择此项。
集成中的权重: 0.5
此 pipeline 解决了训练集和测试集之间的域偏移,而无需昂贵的重新训练。我们没有使用标准微调,而是使用显著子空间对齐 (SSA) 作为轻量级测试时适配 (TTA) 技术。
nn.Sequential(
nn.Linear(input_dim, 512), # 隐藏层 1
nn.BatchNorm1d(512),
nn.ReLU(),
nn.Dropout(0.3),
nn.Linear(512, 256), # 隐藏层 2
nn.BatchNorm1d(256),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(256, 128), # 隐藏层 3
nn.BatchNorm1d(128),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(128, n_targets)
)
我在骨干网络和头部之间插入了一个可学习的线性适配器。在推理期间,我们冻结骨干网络并仅更新此适配器,以将测试图像特征与训练分布对齐(使用预计算的 PCA 统计量 mu_s 和 U)。更多细节见:https://arxiv.org/pdf/2410.03263
这对公共榜单的变化 negligible,但我信任这种方法,它将私有榜单分数从 0.646 提高到 0.652 :)
集成中的权重: 0.3
vit_large_patch16_dinov3 分类 15 个物种。vit_huge_plus_patch16_dinov3。Dry_Clover_g 和 GDM_g 以重构总量。集成中的权重: 0.2
为了捕捉不同的语义粒度,我们融合了两个 state-of-the-art 视觉模型的特征。
vit_so400m_patch16_siglip_512 (512px) - 擅长语义理解。# 特征融合逻辑
feat_dino = dino_backbone(img_768) # DINOv3 特征
feat_siglip = siglip_backbone(img_512) # SigLIP 特征
# 连接:[Backbone_L, Backbone_R, SigLIP_L, SigLIP_R]
combined_features = torch.cat([feat_dino, feat_siglip], dim=1)
我们的最终提交是三个 pipeline 的加权平均。对 SSA 模型 (0.5) 的高权重反映了其对私有测试集中分布偏移的鲁棒性。最终集成帮助获得了最后的几位小数提升。
# 最终集成逻辑
final_submission = (
0.5 * prediction_ssa + # Pipeline A (鲁棒性)
0.3 * prediction_species + # Pipeline B (元数据上下文)
0.2 * prediction_siglip # Pipeline C (特征多样性)
)
我们使用了 StratifiedKFold (5 折),通过 total_biomass_bin * species_id 的复合键进行分层,以确保每个折都能看到具有代表性的物种和重量类别分布。