567. Google Research - Identify Contrails to Reduce Global Warming | google-research-identify-contrails-reduce-global-warming
业务背景:https://www.kaggle.com/competitions/google-research-identify-contrails-reduce-global-warming/overview
数据背景:https://www.kaggle.com/competitions/google-research-identify-contrails-reduce-global-warming/data
我的方法是作者论文[1]中3D模型的简化版本:
首先,我假设早期层的特征对最终预测贡献不大,因为凝结尾在帧与帧之间漂移。因此我想到只在特征图的较深层应用时序调制。
我尝试了一些在早期层应用时序调制的实验,发现只在最后一层应用效果最佳。注意其余特征图仅通过当前时间帧(T=4)进行切片。

为了加快加载速度并节省磁盘空间,我将伪彩色图像量化为uint8格式。
我这样做基于一个假设:"如果人类在uint8分辨率下标注,那么在该分辨率下训练AI模型就足够了"。
正如其他参与者公开讨论的,任何几何增强都无法提升模型性能(比赛结束后发现是因为标签错位)。
因此我只应用了轻量级增强:RandomResizedCrop和HorizontalFlip。
cfg.geometric_transform = A.Compose(
[
A.RandomResizedCrop(height=256, width=256, scale=(0.75, 1.0), p=0.6),
A.HorizontalFlip(p=0.5),
]
)
我的CV策略非常简单。我只用training帧的图像进行训练,在validation图像上评估。
在最终提交中,本应使用所有图像训练或取各折平均值,但考虑到比赛剩余时间,这不现实,所以我放弃了。
集成策略如下:
hflip(x2)我测试了多个骨干网络,包括近期发布的模型,发现EfficientNet和PVTv2作为集成种子在训练时间和性能之间有良好权衡。
最终提交共包含24个模型。
| 骨干网络 | 使用的时间帧 | 输入分辨率 | TTA | 随机种子 |
|---|---|---|---|---|
| efficientnet_b3 | [1, 2, 3, 4] | 768 | hflip (x2) | x4 |
| pvt_v2_b3 | [1, 2, 3, 4] | 640 | hflip (x2) | x4 |
| pvt_v2_b5 | [1, 2, 3, 4] | 512 | hflip (x2) | x4 |
验证集上的CV分数为0.692,Private LB分数为0.700。
在我中等配置的机器环境(RTX 3090 Ti x1)中,更高分辨率训练容易出现CUDA内存溢出错误,或导致批次大小过小。因此我使用梯度检查点和FP16训练来克服这个问题。
通过元数据,我发现训练集和验证集中凝结尾的几何分布差异很大。
正如作者在论文[1]中所述,我认为存在一些仅在训练数据中出现而验证集中没有的地理观测点。我也基于地理分布实现了折叠划分,但未能有效利用这一信息。
为了进一步增加数据集中正样本的数量,我们还包含了在美国某些地点的GOES-16 ABI图像,这些地点的Google街景天空图像中包含凝结尾。

感谢举办这场比赛。除了应对有趣的挑战外,我还得以回顾和复习了之前在计算机视觉比赛中使用的所有方法。
在后期提交中,我测试了标签错位对分数的影响,也测试了软标签的效果(一些参与者认为有效)。
为降低训练成本,我简单地测试了基础2D U-Net架构,仅使用当前帧,没有时序特征调制器。
其他设置如下:
| 参数 | 值 |
|---|---|
| backend | efficientnet_b3 |
| crop_size | 512x512 |
| loss | BCE(pos_weight=8) + Dice |
| augmentation | ShiftScaleRotate(p=0.6), hflip |
| ensemble | 4x种子集成 |
| TTA | hflip |
由于标签错位了(0.5, 0.5)像素,我将输入图像放大2倍,并平移(1, 1)像素。这比在训练时校正标签并在推理时逆变换更简单。
校正通过以下算法实现。注意变换矩阵中额外添加了(0.5, 0.5)的平移系数,这是解决OpenCV的warpAffine函数[2]问题的临时方案。
M = np.array([[2, 0, 1 + 0.5], [0, 2, 1 + 0.5]], dtype=np.float32)
img = cv2.warpAffine(
img, M, (2 * W, 2 * H), flags=cv2.INTER_LINEAR, borderMode=cv2.BORDER_CONSTANT
)
软标签从human_individual_masks.npy生成。由于比赛页面的数据标签说明:
当超过50%的标注者将其标记为凝结尾时,该像素被视为凝结尾。训练数据中包含个体标注(
human_individual_masks.npy)以及聚合的真实标注(human_pixel_masks.npy)。
我通过以下处理创建软标签:
human_pixel_mask = np.clip(individual_pixel_mask.mean(-1) * 2, 0, 1)
我训练了三种模型,并在验证数据(CV)和排行榜(Public和Private)上测试:
结果显示,MC和SL在Private LB上分别独立带来0.59%和0.70%的正向提升。
| 描述 | 集成种子 | crop_size | CV | Public | Private | 增益 |
|---|---|---|---|---|---|---|
| 基线模型 | 4x | 512 | 0.6672 | 0.67818 | 0.67669 | - |
| +MC | 4x | 512 | 0.6708 | 0.68131 | 0.68259 | 0.59% |
| +MC +SL | 4x | 512 | 0.6766 | 0.69623 | 0.68956 | 1.29% |
