687. CSIRO - Image2Biomass Prediction | csiro-biomass
我们的解决方案是三个模型变体的加权集成,所有模型均基于带有 LocalMamba 融合块的 DINOv3 ViT-Huge 骨干网络构建。关键的成功因素是通过基于比率的预测和多头架构变体来解决具有挑战性的 Dry_Dead_g 目标。
最终集成:3 种模型架构 × 4 折交叉验证。
所有模型共享以下核心架构:
输入:图像 (2000×1000) → 分割为 左 (1000×1000) + 右 (1000×1000)
↓
DINOv3 ViT-Huge 骨干网络 (vit_huge_plus_patch16_dinov3.lvd1689m)
- 来自 timm 的预训练权重
- 启用梯度检查点以提高内存效率
- global_pool='' 以保留 patch tokens
↓
特征拼接:[Left Tokens, Right Tokens] → (B, 2N, D)
↓
LocalMamba 融合 (2 个块)
- LayerNorm → Gated Linear → DepthwiseConv1d → Projection
- 残差连接
↓
自适应平均池化 → (B, D)
↓
多头回归,带有 Softplus 激活函数 (非负输出)
关键创新: 将 Dry_Dead_g 预测为 Dry_Total_g 的比率
| 头 (Head) | 输出 | 激活函数 |
|---|---|---|
head_green |
Dry_Green_g | Softplus |
head_clover |
Dry_Clover_g | Softplus |
head_total |
Dry_Total_g | Softplus |
head_dead_ratio |
Dead/Total 比率 | Sigmoid [0,1] |
| 推导: |
Dry_Dead_g = head_dead_ratio × Dry_Total_gGDM_g = Dry_Green_g + Dry_Clover_g特殊处理:
训练配置:
架构: 直接预测与推导目标
| 头 (Head) | 预测 | 推导 |
|---|---|---|
head_green |
Dry_Green_g | - |
head_dead |
Dry_Dead_g | - |
head_clover |
Dry_Clover_g | - |
| - | GDM_g | Green + Clover |
| - | Dry_Total_g | GDM + Dead |
| 训练配置: |
关键区别: 直接预测 Total 和 GDM,推导 Dead
| 头 (Head) | 预测 | 推导 |
|---|---|---|
head_green |
Dry_Green_g | - |
head_clover |
Dry_Clover_g | - |
head_gdm |
GDM_g | - |
head_total |
Dry_Total_g | - |
| - | Dry_Dead_g | Total - GDM |
| 训练配置: |
图像分割: 全景图像 (2000×1000) 分割为左半部分 (0:mid) 和右半部分 (mid:end),分别通过骨干网络处理。
我们使用的 CV 策略是由讨论区中的某人建议的。我找不到那个帖子了,但感谢他。
我们使用了 StratifiedGroupKFold (4 折),并采用了精心设计的分层和分组方案:
分层标签: 基于具有挑战性目标的存在/不存在
stratify_col = f"{has_clover}_{has_dead}"
# 确保每折都有平衡的代表性:
# - 含有 Clover 的样本 (Dry_Clover_g > 0)
# - 含有 Dead 的样本 (Dry_Dead_g > 0)
分组键: 通过对同一收集会话的样本进行分组来防止数据泄露
group_key = f"{day}/{month}_{state}"
# 示例:"15/3_NSW", "22/6_WA", "8/11_Vic"
# 确保同一天在同一州收集的样本保持在同一折中
为什么这很重要:
Dry_Clover_g 通常为零(稀疏),而 Dry_Dead_g 具有高方差。分层确保每折都能看到这些挑战性目标的相似分布。sgkf = StratifiedGroupKFold(n_splits=4, shuffle=True, random_state=42)
for fold, (_, val_idx) in enumerate(
sgkf.split(df, df['stratify_col'], groups=df['group_key'])
):
df.loc[val_idx, 'fold'] = fold
A.Resize(IMG_SIZE, IMG_SIZE)
A.HorizontalFlip(p=0.5)
A.VerticalFlip(p=0.5)
A.RandomRotate90(p=0.5)
A.Rotate(limit=(-15, 15), p=0.3, border_mode=REFLECT)
A.ColorJitter(brightness=0.15, contrast=0.15, saturation=0.15, hue=0.05, p=0.5)
A.GaussNoise(var_limit=(5.0, 20.0), p=0.2)
A.Normalize(ImageNet stats)
| 参数 | 值 |
|---|---|
| Batch Size | 2 |
| 梯度累积 | 8 (有效 batch = 16) |
| Epochs | 100 (早停) |
| 冻结 Epochs | 10 |
| Warmup Epochs | 3 |
| LR Backbone | 1e-5 |
| LR Head | 1e-4 |
| Weight Decay | 1e-2 |
| EMA Decay | 0.998 |
| Patience | 15 |
| 梯度裁剪 | 1.0 |
| 混合精度 | FP16 |
加权 Huber 损失 (β=5.0):
loss = Σ(weight_i × SmoothL1Loss(pred_i, target_i, beta=5.0))
模型 1 额外损失:
验证期间进行 4 路 TTA:
带有特定折权重的加权平均:
weight = {
fold_0: 1.25,
fold_1: 0.75,
fold_2: 1.25,
fold_3: 0.75
}
ensemble = Σ(weight × fold_predictions) / Σ(weights)
if target_name == "Dry_Clover_g":
prediction *= 0.8
elif target_name == "Dry_Dead_g":
if prediction > 20:
prediction *= 1.1
elif prediction < 10:
prediction *= 0.9
Dry_Dead_g 具有最高的方差和与其他特征最低的相关性。基于比率的预测 (Dead/Total) 显著提高了稳定性。| 模型 / 集成 | 公榜分数 | 私榜分数 |
|---|---|---|
| 模型 1:基于比率的 Dead | 0.76760 | 0.65329 |
| 模型 2:标准多头 | 0.77157 | 0.64714 |
| 模型 3:4 头 (Total 优先) | 0.76685 | 0.64803 |
| 集成 (带折权重 + 后处理) | 0.77142 | 0.65179 |
| 集成 (无折权重,无后处理) | 0.76772 | 0.64855 |