返回列表

16th Place Solution

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

开始: 2019-11-22 结束: 2020-02-10 自然语言处理 数据算法赛
第16名方案

第16名方案

作者: yuval reina (Grandmaster)
队友: @abhishek, @atsunorifujita, @pvduy23

首先,我要感谢我的队友 @abhishek@atsunorifujita@pvduy23 ,我们进行了非常愉快的团队合作。

方案亮点

预处理

我们没有对文本进行太多的预处理。我们尝试过一些清洗方法,特别是为了让包含代码的部分更具可读性(更短),但这并没有带来什么改变。

损失函数

我很惊讶在获胜者的帖子中没有看到更多关于这方面的提及,但在这里我们用了一个小技巧。我们没有直接使用目标列,而是先对它们进行排名并归一化到 [0,1] 范围,然后将它们作为目标,类似于:

> target = scipy.stats.rankdata(target,'average')
target = (target-target.min())/ (target.max()-target.min())

(我看到 CV 提高了大约 0.05 - 0.01)。至于损失函数本身,我使用了 MSE,其他一些队友使用了 MSE+BCE。

模型

我们使用的模型包括 RoBERTa-Large、XLNet、BERT-base-uncased。我们也尝试了其他一些模型,如 BERT-large、RoBERTa-base、XLMRoBERTa 等。(没有选择 XLMRoBERTa 是个失误——稍后会讨论)。我们还尝试在 Stack Exchange 语料库上预训练和微调 bert-base,但似乎并没有提高 CV 分数。

为了处理长文本,我使用了完整的 question-title + 来自 question-bodyanswer 的等长部分,通过截取开头和结尾来实现。

我们对每个模型使用了 5 折交叉验证。

数据增强

我尝试了几种增强方法:

  • 用 [PAD] 或其他 token 替换随机 token —— 20% 的 [PAD] 替换率似乎效果不错。
  • 翻译成德语再翻译回来 —— 没用(俄语也没用)。
  • 当文本太长时截取随机部分 —— 没有任何区别。

后处理

由于斯皮尔曼相关性(Spearman correlation)的特殊性,后处理在这次比赛中非常重要。

斯皮尔曼相关性

我们最终对一些输出列进行了截断。我们截断的列是那些大部分目标值为 0 或大部分为 1 的列。截断阈值的选择是为了保持测试集中非零值的数量与训练集中相同。这种方法使 CV 和 LB 提高了约 0.03-0.04。

Question-Type-Spelling

由于该类别的非零样本数量非常少,我们明白没有机器学习模型能在这里做出可靠的预测。所以我们尝试了一些启发式方法——我们最终将所有 host 为 'english.stackexchange.com' 或 'ell.stackexchange.com' 的问题设置为 1。我们也尝试了一个更复杂的技巧,通过选择不同的关键词,但这在 Private LB 上不起作用。

模型融合

我们尝试了不同类型的堆叠和平均。最后看来,简单的平均和其他方法一样有效。

我们在哪里失误了?

  • 模型数量不足 —— 我们对每个模型都使用了 5 折,这限制了我们在 2 小时内可以运行的不同模型的数量。因此,我们(其实是我!)忽略了一些好模型,比如 XLMRoBERTa,它给出了不错的结果,但当时看起来并不比其他模型好。最佳做法可能是使用更多样化的模型,并减少每个模型的折数。
  • 交叉验证 (CV) —— 可能是因为斯皮尔曼指标,或者是因为训练集对于 30 个类别来说太小了,或者是我们做错了什么,但 CV 对我们来说不够可靠(相比于它自身、Public LB 和 Private LB),这意味着我们在选择模型和参数时没有做出正确的选择。

最后的观察

在比赛的某些时刻,这似乎不是一场关于 NLP 的比赛,而是关于技巧的比赛。这是一个误区。这场比赛是关于 NLP 的,最终技巧只是全貌中的一小部分,获胜的队伍是拥有最佳模型的队伍。

像往常一样,我要感谢 Kaggle 和竞赛团队组织了一场井井有条的比赛。

同比赛其他方案