返回列表

1st place solution with code

362. Google QUEST Q&A Labeling | google-quest-challenge

开始: 2019-11-22 结束: 2020-02-10 自然语言处理 数据算法赛
第一名解决方案(含代码)

第一名解决方案(含代码)

作者: Oleg Yaroshevskiy, Dmitriy Danevskiy, Yury Kashnitsky, Dmitriy Abulkhanov
发布时间: 2020-02-11

祝贺所有团队,尤其是勇敢的个人参赛者!同样感谢主办方!

这对整个团队来说都是一种极好的感觉。我曾两次在 NLP 比赛中以一名之差无缘金牌区,而这次终于做到了。在下面的几篇帖子中,我写下了“尊重你的努力,而不是结果”,你就会成功的。这种励志名言总是有空间的。我不知道是与自己竞争更难,还是与这些伟大的头脑竞争更难。感谢团队( @ddanevskiy , @kashnitsky , @dmitriyab )带来的这场惊心动魄的比赛。也感谢整个社区提供的想法、批评和幽默感。

编辑

社区似乎在等待我们的“杀手锏”。我认为我们没有单一的秘密武器。我们的解决方案由三个基石组成:

  • 预训练语言模型
  • 伪标签
  • 后处理(是的,我们做了一个)

基本流程

不到三周前,刚结束 TF Q&A 比赛,我们就投入到了这场比赛中。哦是的,排行榜上已经有很多优秀的 NLP 高手了。我们从一个公共 PyTorch 基线 [(0.377 I guess)](https://www.kaggle.com/phoenix9032/pytorch-bert-plain)(感谢 @phoenix9032)开始,并通过几个技巧有效地更新了它(BERT-base 为 0.396,BERT-large 为 0.402):

  • 使用 question_title 组进行 GroupKFold
  • Multi-Sample Dropout 以加速训练和更好的泛化,论文链接
  • 为编码器和解码头设置不同的学习率(这值得写篇论文 @ddanevskyi)
  • 使用 BERT 所有层的 CLS 输出,而不是仅使用最后一层。我们通过使用这些输出的加权和来实现这一点,其中权重是可学习的,并被约束为正数且总和为 1

我们尝试了针对不同目标的单独权重和各种损失函数,但最终坚持使用简单的 BCE 损失。

预训练语言模型

当 @dmitriyab 加入我们的团队时,他引入了在 StackExchange (SE) 上预训练的语言模型,该模型拥有包含代码和其他领域标记的 11 万个词汇的字典。除了常见的 MLM 任务外,该模型还通过池化 LM 输出之上的线性层预测 6 个辅助目标(question_score, question_view_count, question_favorite_count, answer_score, answers_count, is_answer_accepted)。这看起来非常有益,足以让我放弃代码替换实验,并使用巨大的预训练嵌入层更新现有的 bert 流程 -> 0.414。最后,@dmitriyab 和 @kashnitsky 使用全词掩码在 7M SE 数据上训练了几个 LM(bert-large, roberta, roberta-large),但最初的模型仍然是最好的。

伪标签

伪标签是 Kaggle 社区内众所周知的半监督学习技术,有时我想知道他们是如何在学术论文中重新发明这些东西的,比如这篇(顺便说一句,结果很棒)。所以我们使用三个基本的 bert 模型标记了额外的 10 万个样本。第一次伪标签实验显示 SE 预训练 bert 有巨大提升(0.414 -> 0.445)。这非常巨大。但排行榜并不同意。

以前,我和队友使用所有折的模型来创建伪标签。这种策略在许多情况下效果很好,包括最近的 Recursion 比赛(我的团队获得第 6 名)。@ddanevskyi 在 Freesound 比赛中获得第 3 名也使用了同样的方法。这种创建伪标签的方式给出了相当准确的预测,因为你使用的是折集成,但有一个不明显的陷阱。如果伪标签集包含许多与训练集相似的样本,你可以预期一些实际的训练标签可能会通过这些样本泄漏,即使没有“直接”的目标泄漏。

想象一下,你在训练集上训练了一个 5 折模型,然后使用这 5 折在一些外部数据集上创建伪标签。然后你将这些伪标签添加到 5 折中每一折的训练部分。你很可能会在验证部分看到过于乐观的分数,因为用于生成伪标签的 5 个模型中有 4 个已经通过其训练过程“看”到了当前的验证集。

我们可以预期 SO&SE 数据中有很多非常相似的问题/答案,所以我们显然不能依赖那种伪标签。为了解决这个问题,我们生成了 5 组不同的伪标签,其中对于每个训练/验证拆分,我们只使用那些仅使用当前训练集训练的模型。这给出的伪标签准确性要低得多,但消除了任何可能的目标泄漏源。

正如预期的那样,与“泄漏”方法相比,它没有带来那么大的改进(0.414 -> 0.422),但在解决过拟合方面这是一个明智

同比赛其他方案