363. Bengali.AI Handwritten Grapheme Classification | bengaliai-cv19
我的模型主干很简单,基于 seresnext50,使用随机分割的4折交叉验证(CV)进行训练,没有使用分层抽样。不过,我有两个额外的损失头,我发现它们对正则化模型非常有帮助——1292类别的字素头交叉熵损失和字素头的 Arcface 损失。
然而,1292头是建立在具有二进制映射的3个任务头的组合之上的——
self.logit_to_1292 = nn.Linear(168+11+7, 1292, bias=None)
out_1292 = self.logit_to_1292(out_3tasks)
在这里,我用一个冻结的二进制权重初始化 self.logit_to_1292 层,其维度为 (168+11+7, 1292),它正确地将 的每一种三种组合映射到其对应的字素。不过,我不训练这一层。
在反向传播过程中,我对3个任务头和 arcface 头使用了非常低的权重(0.02),但对字素头使用了非常高的权重(1),这相当反直觉。
我使用了75%概率的 CutMix(基于样本)。此外,随着训练的进行,我逐渐加入 grid mask,但我使用了“grid-mix”代替——所以不是移除那些网格,而是在每张图像内随机打乱它们,这样与从图像中裁剪掉那些网格相比,每张图像的统计数据不会改变。我发现这样做稍微更有帮助。
对于基于样本的 cut mix(这是最有帮助的数据增强)——每张图像将在 pytorch 的数据加载函数期间随机绘制一个二进制 cutmix 掩码,在训练期间,我只使用这个预先计算的掩码在每个批次内打乱并配对图像。
我还加入了5%由 XingJian Lyu 提出的增强方法。
总的来说,cutmix 是最有用的部分。
我想说这部分是帮助我的模型很好地泛化到测试集的关键。我在比赛的最后一周才在论坛的外部数据披露帖子上发现了 Ekush 外部数据集。
基本上,我下载了这30万张未标记的图像并调整了大小,使用我训练得最好的4折模型为字素(1292)和3个任务头(168+11+7)生成软目标。然后结合原始训练数据,我用软目标作为标签重新训练上述模型4折。在每一折中,我结合整个30万外部数据加上训练折来训练每个模型,并这样做4次。
这种方法类似于论坛早些时候分享的 Noisy Students 自训练论文的想法,我生成没有噪声的软目标,并用噪声重新训练模型。学生模型和教师模型与上述完全相同。
关键在于如何对这些未标记的数据集进行采样——效果最好方法是首先为字素生成硬标签,然后结合我们的训练数据集,使用 Heng 的平衡采样器基于所有字素进行采样。其他采样策略根本不起作用。
这最终将我的模型在本地从 994 推到了 996,在 LB(排行榜)上从 985 提高到 990,其中4折的集成进一步将其提升到我目前的 916 分(均基于公开分数)。