574. CommonLit - Evaluate Student Summaries | commonlit-evaluate-student-summaries
非常感谢组织这场精彩竞赛的主办方和Kaggle团队。
这场竞赛正如我们所期待的那样,我们非常高兴能够获得第四名。
非常感谢@kurokurob与我组队,以及每日的讨论和实验。祝贺你获得第四枚金牌奖章。
(而且我将成为竞赛Grand Master!!!)
我们是一个伟大的团队!
我们的最佳私有解决方案是1个全训练集 × 7个模型的集成。
这场竞赛的训练数据只有4个提示词,而测试数据有122个提示词,可以预想会有很大的波动。而且公共排行榜非常不稳定。这些都让我们认为鲁棒性很重要,不仅仅是为了交叉验证。
我一开始使用了4折交叉验证。特别是那些使用提示文本的模型,因为我必须增加最大长度来提高分数,这导致推理时间增加,无法集成更多模型(只能包含2-3个模型)。
就在这时,我和kuro合并了团队。我们将他一直在研究的全训练集想法融合进来。通过用1个全训练集替代4折交叉验证,我们想到了将4折的信息压缩到1个全训练集中并集成更多模型的方案。
我们想象通过这样做,可以防止私有测试数据中每个提示词上的分数变化和下降,总体上获得更好的分数。
结果,我们相信我们成功防止了排名下滑,并取得了这个名次!
| 提交 | 类型 | 模型 | CV | Public LB | Private LB | 排名 | 备注 |
|---|---|---|---|---|---|---|---|
| sub1 | 最佳LB | 1全训练 × 9模型 | 0.4679 | 0.41991 | 0.45785 | 11 | 使用GBDT和扩展推理长度 |
| sub2 | 最佳CV | 1全训练 × 7模型 | 0.4639 | 0.42979 | 0.45515 | 4 | 纯NLP结果(扩展推理长度) |
| sub3 | 保险方案 | 1全训练 × 8模型 | 0.4693 | 0.43855 | 0.45597 | 6 | 纯NLP结果 |
sub2中的最佳CV是我们的最佳私有方案,以下是主要说明。
我们在sub2中的每个模型如下表所示。
| 模型编号 | 推理编号 | 模型 | 训练最大长度 | 推理最大长度 | 冻结 | 逐层 | 输入 | 池化 | 第二损失 | 预处理 | 4折早停CV | ||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 原始提示词 | CLS | 原始提示词注意力 | 仅文本部分均值 | ||||||||||
| 1 | 91 | deberta-v3-large | 768 | 1500 | ✓ | ✓ | 0.4818 | ||||||
| 2 | 22 | deberta-v3-large | 1050 | 950 | ✓ | ✓ | ✓ | 0.4855 | |||||
| 3 | 63 | deberta-v3-large | 850 | 1500 | ✓ | ✓ | 0.4984 | ||||||
| 4 | 72 | deberta-v3-large | 868 | 1024 | ✓ | ✓ | Arcface | ✓ | 0.4919 | ||||
| 5 | 2,3 | deberta-v3-large | 868 | 868 | ✓ | ✓ | 0.4880 | ||||||
| 6 | 259 | deberta-v3-large-squad2 | 768 | 1500 | ✓ | ✓ | 0.4952 | ||||||
| 7 | 331 | deberta-v3-large-squad2 | 1050 | 950 | ✓ | ✓ | ✓ | 0.4993 |
下面详细描述各个模型。
这个模型是我们模型的典型基础。
首先,准备两个输入并将它们作为一对放入分词器中(数据集示例)。即使不将它们作为一对,也可以通过用[SEP]连接它们来获得相同的结果。
self.text = self.df["text"]
self.prompt = self.df["prompt_title"] + [SEP] + self.df["prompt_question"] + [SEP] + self.df["prompt_text"]
tokens = tokenizer.encode_plus(
self.text,
self.prompt,
...
)
现在所有我们要做的就是将其放入模型中,增加最大长度,并在全连接层输出CLS。
在这个模型中,创建了一个原始提示词并用作输入。
self.text = "Evaluating the summarized text and calculating content and wording score : " + self.df["text"].values
self.prompt = prompt_title + [SEP] + prompt_question + [SEP] + prompt_text
tokens = tokenizer.encode_plus(
self.text,
self.prompt,
・・・
)
然后,仅对原始提示词部分(Evaluating the summarized...)进行注意力池化(模型示例)。
## init
self.pool = AttentionPooling(self.config.hidden_size)
...
## forward
output = self.model(ids, mask, token_type_ids)
output = output[0][:,:12,:]
output = self.pool(output, mask[:,:12])
output = self.fc(output)
正如讨论和notebook中所讨论的,训练数据可以分为38种类型。我认为可以很好地利用这一点,所以加入了Arcface作为辅助损失。我尝试很好地利用最后的嵌入,但不可行。然而,它确实有助于集成模型的多样性。
另外,作为预处理,我确保在句点和逗号后包含一个空格;在进行EDA后,我注意到如果一个句子在句点或逗号后没有空格,分词器会将其分割得不同。不过,我认为这对分数影响不大。
通过将推理长度增加到超过训练长度,分数得到了显著改善。示例如下。以下模型训练时最大长度为850,但通过在推理时设置最大长度为1500,CV和公共榜分数提高了(可能对私有榜贡献不大)。
| 训练最大长度 | 推理最大长度 | 39c16e折0 | 814d6b折1 | ebad26折2 | 3b9047折3 | CV |
|---|---|---|---|---|---|---|
| 850 | 850 | 0.4505 | 0.5595 | 0.5051 | 0.5024 | 0.4984 |
| 850 | 1024 | 0.4524 | 0.5590 | 0.4836 | 0.5018 | 0.4927 |
| 850 | 1500 | 0.4527 | 0.5588 | 0.4614 | 0.5013 | 0.4867 |
然而,有些模型可能会退化。保险提交(sub3)只包含那些没有扩展推理最大长度的模型。结果,CV和公共榜受到影响,但私有榜几乎没有影响。
对于最佳CV提交,我们最初使用GBDT(LGBM + Catboost + XGboost)进行后处理,但最终,不使用GBDT的集成得到了更好的CV。产生最佳私有榜的提交没有使用GBDT后处理。我们也考虑了Nelder-Mead和Optuna,但因为担心它们肯定会过拟合而没有使用。所以我们使用简单的均值集成,采用爬山法(为了额外的推理时间,我们还添加了不同种子的全训练以进一步提高鲁棒性)。
最终CV(4折早停结果):0.46394,Public:0.42979,Private:0.45515 第4名
※ 此外,我们还准备了保险方案(sub3),其中推理最大长度与训练时相同。结果如下:
最终CV:0.4693,Public:0.43855,Private:0.45597 第6名
在这个结果中,CV和LB都很差,但私有榜很好,这说明了在这个竞赛中模型的鲁棒性有多重要。
我们无法独自取得这些成果。我们受到了过去合作过的人的很大影响,感谢他们的贡献。我们还要向那些通过以往竞赛分享知识和见解的人表示诚挚的感谢。非常感谢。
我们特别感谢以下人员在这次竞赛中的帮助!非常感谢。
全训练集:Team Hydrogen 参考1 参考2,Raja Biswas @conjuring92 参考3
冻结:Takamichi Toda @takamichitoda 参考4
37-38分类:MOTH @alejopaullier 参考5,Alexander Chervov @alexandervc 参考6
后处理:nogawanogawa @tsunotsuno 参考7