作为一个萌新来说,这是我在kaggle上的首战(铜牌 top6%)。由于参加比赛的时候时间已经过了一半以及实验室资源有限,没有拿到银牌,呜呜呜~~~~
下面我将把在这次比赛中的感受和心得分享给大家。
一. 比赛背景及任务介绍
参考这篇博客。
补充: 训练集含有ship的与不含ship的样本比例大约为1:2.6 (29070 : 75000),而且含有ship的图像中所包含ship的count也大大不均衡 (ship_count: 1~15)。整体如下图所示:
二. 数据预处理
由上面可知,该比赛数据集严重不均衡,除此之外,ship的尺寸也远远小于图像整体的尺寸 (正负像素个数比例约为1:1000),因此这会导致非常不均衡的训练。如果使用没有ship的图像,不但会进一步将训练的难度增大,而且需要在每个epoch处理更多的图像,导致训练时间增加了4倍多。基于上面分析,我们做出了以下几方面处理:
- 在分割训练 (下面会介绍) 这一步时,直接简单粗暴的剔除掉训练集中不含ship的图像,但缺点是使得训练样本大大减小,有可能会影响最终的精度。比赛结束后在discussion区看了别人的方案:a) 为每个batch内 non-empty / empty images 设置不同的比例 [link] ,b) 使用Online-Hard-Example-Mining来选取top k个作为batch [link];
- 数据增强:-20~20度随机旋转 (p = 0.75), 随机水平翻转(p = 0.5), 随机调整亮度 (p = 0.05, limit = 0.05);
三. 模型选择
在这个比赛中,我们可以把整个数据集分成两大类:含ship和不含ship。因此我们的设计方案是先训练一个分类网络,这样便于将测试集中含ship与不含ship的图像分隔开;然后在训练一个分割网络,便于对包含ship的图像的船只进行定位。具体方案如下:
- 分类训练:使用全部的训练集训练一个分类网络;
- 分割训练:使用仅含有ship的训练集训练一个分割网络。
由于在分割训练中我们只用了仅含有ship的训练集,为了防止过拟合,就不能选取复杂度大的模型,因此我们在分类训练和分割训练分别选择的backbone是resnet34和Unet34。
四. 训练
无论是训练分类网络还是训练分割网络,所采用的数据增强方法是一样的;同时也都采用了multi image size (256, 384, 768) 的训练方式。
(1). 训练分类网络-resnet34
- 训练image size 256*256:使用imagenet预训练权重
- 训练image size 384*384:使用训练好的256 * 256的模型权重作为新的预训练权重
- 训练image size 768*768:使用训练好的384 * 384的模型权重作为新的预训练权重
- loss function: bce loss
- optimizer: Adam
(2). 训练分割网络-Unet34
- 训练image size 256*256:在encoder部分使用imagenet预训练权重
- 训练image size 384*384:使用训练好的256 * 256的模型权重作为新的预训练权重
- 训练image size 768*768:使用训练好的384 * 384的模型权重作为新的预训练权重
- loss function: mixed loss (dice loss + focal loss)
class MixedLoss(nn.Module):
def __init__(self, alpha, gamma):
super().__init__()
self.alpha = alpha
self.focal = FocalLoss(gamma)
def forward(self, input, target):
loss = self.alpha*self.focal(input, target) - torch.log(dice_loss(input, target))
return loss.mean()
- optimizer: Adam
(3). 框架-fastai
在kaggle上打竞赛的话,强烈推荐fastai,底层是用pytorch实现的。不仅代码量少,而且融合了很多好的train tricks.
- 学习文档:英文文档和中文文档
- 从fastai学习到的十大技巧
五. 测试
- 使用分类网络resnet34对test dataset进行预测,这样会对每张图像预测出一个概率值,大于0.5的代表图像中包含ship,反之则没有;
- 使用分割网络Unet34 + TTA 对第一步预测出包含ship的图像进行分割,对分割后的mask进行decode得到相应的EncodedPixels.
六. attention机制的尝试
加入attention机制,具体的来说将 SE block加入到分类和分割网络中,但提升效果不太明显。
七. 没有完成的尝试
由于自身水平和时间原因,下面的想法没有完成。
- k folds, ensemble strategy, mask-rcnn + Unet
八. 心得
- 选择合适的baseline模型!!! 一个好的baseline可以进入前top20%;
- 多了解一些训练技巧。可以参考我之前的博客。
- 多了解一些简单实用的package。可以参考我之前的博客。
- 善用模型融合!!!
- 相信自己本地的CV验证集。每天在kaggle的提交次数是有限的,因此要设置好离线验证集,不断探索好的参数,不要过分相信kaggle的线上得分。