返回列表

47th Place Solution Write-Up (Ensembling)

361. TensorFlow 2.0 Question Answering | tensorflow2-question-answering

开始: 2019-10-28 结束: 2020-01-22 自然语言处理 数据算法赛
第47名方案分享(模型融合)

第47名方案分享(模型融合)

作者:Ram Ramrakhya (axel81) | 比赛排名:第47名

感谢 Kaggle 和 Kaggle 社区举办了这场精彩的比赛。我学到了很多东西。在最后一周,我们尝试了很多 PyTorch 的新东西,虽然没能成功运行起来,但过程非常有趣。

我们的方案

我们目前的方案是基于 @yihdarshieh 的这个优秀内核 https://www.kaggle.com/yihdarshieh/inference-use-hugging-face-models 构建的 TF 2.0 解决方案。起初,我尝试对官方的 BERT joint 基线进行微调,但效果提升不明显。在接下来的几周里,我完成了比赛的 TPU 环境搭建,并准备好了在开发集上进行训练和验证的流程。

所有的实验都是在 Google Colab 的免费 TPU 上进行的。这是我第一次认真使用 TPU,不得不说,感觉太棒了。因为它们非常快。使用 TPU 大大缩短了我的实验时间。

我们的方案是以下 2 个模型的简单融合:

  1. BERT-joint-large 公开 LB 分数 0.6
  2. BERT-joint-base 公开 LB 分数 0.58
  3. DistillBERT-joint 公开 LB 分数 0.54
  4. 我们的最终方案是 1 和 2 的融合,加上一些后处理改进,在公开 LB 上得分为 0.64(在私有 LB 上也得分为 0.64,但我们没有选择最佳方案作为最终提交,因为新的后处理在公开 LB 上得分较低)

这是我们的融合代码,我们使用了简单的加权平均融合。

        nq_logits = bert_nq(nq_inputs, training=False)
        base_nq_logits = base_bert_nq(nq_inputs, training=False)

        (start_pos_logits, end_pos_logits, answer_type_logits) = nq_logits
        (base_start_pos_logits, base_end_pos_logits, baseanswer_type_logits) = base_nq_logits
        
        start_pos_logits = (0.2 * start_pos_logits + 0.8 * base_start_pos_logits)
        end_pos_logits = (0.2 * end_pos_logits + 0.8 * base_end_pos_logits)
        answer_type_logits = (0.2 * answer_type_logits + 0.8 * baseanswer_type_logits)

后处理

在尝试了多个单一模型后,我开始专注于后处理以提高模型性能。最初,我使用了 @prvi 的这个优秀内核 https://www.kaggle.com/prokaj/bert-joint-baseline-notebook 提供的后处理方法,这帮助我的单一模型得分达到了 0.56-0.58 的范围。为了进一步提高,我深入研究了模型的预测和真实值。在这里我发现我们的模型预测了重复的答案跨度。因此,我在后处理中添加了去重逻辑,这帮助公开 LB 分数提高了 0.01,开发集提高了 0.02。我还观察到,如果我的模型不预测任何“YES/NO”答案,分数会有所提高,因此在我的最终方案中,我的模型实际上只输出了答案跨度和空答案。

确定阈值是预测有效答案的重要事项之一,但我没有过多地调整答案阈值。最初,我在验证集上使用 5 个不同的答案阈值 [1.5, 3.0, 4.5, 6.0, 7.5] 运行推理,发现长答案为 1.5 和短答案为 3.0 的组合验证分数最高,我在最终方案中保持了这个设置。

后处理的新增内容

来自 @prvi 内核的后处理只查看当前的 512 序列来选择开始和结束索引,但由于我们使用长度为 128 的步幅,每 2 个连续序列之间存在重叠。所以我决定从每 2 个连续序列中追加前 k 个开始和结束索引来选择一对开始和结束索引。在这种情况下,对于重叠的开始和结束索引,我得到了 4 个可能的分数值,其中我只保留最大分数值并丢弃其余 3 个。这种后处理并没有提升我们当前最佳模型在公开 LB 上的表现,但对于一个较弱的模型,它帮助提升了 0.17。