返回列表

1st Place Solution - Trust CV (and LB a bit)

615. Learning Agency Lab - Automated Essay Scoring 2.0 | learning-agency-lab-automated-essay-scoring-2

开始: 2024-04-03 结束: 2024-07-02 智能评测 数据算法赛
1st Place Solution - Trust CV (and LB a bit)

第一名解决方案 - 信任 CV(以及一点 LB)

作者: flg (Grandmaster)

排名: 第 1 名

发布时间: 2024-07-03

比赛: Learning Agency Lab - Automated Essay Scoring 2

非常感谢 Kaggle 和主办方举办这场精彩的比赛!虽然直到最后都紧张得出汗,但整个过程非常有趣。

祝贺 @syhens@dsohonosom,你们大部分时间都处于领先地位!直到最后我还在想,你们这么高的分数是不是过拟合了公共 LB —— 但看来你们只是有一些非常好的解决方案!

感谢 @cdeotte 从一开始就支撑着这次比赛并分享了这么多资源。感谢 @cpmpml 分享了更快的 QWK 计算方法。

太长不看版 (TLDR):

  1. 数据分析 + 实验,以发现“新”数据的评分模式并获得 CV-LB 相关性。
  2. 训练反映这些分数的 Deberta 集成模型。
  3. 两轮伪标签(Pseudo labelling),为“旧”数据获取“新”分数。
  4. 通过阈值处理将浮点预测转换为整数。
  5. 集成而不发生过拟合。

获取 CV-LB 相关性

数据集包含大约 12 年前 8-12 年级学生写的文章。比赛使用了依赖文本的文章,但大部分数据取自 Persuade 语料库,其中包括额外的独立写作任务。比赛数据中有约 13k 篇 Persuade 文章(“旧”)和 4.5k 篇未见过的(“新”)文章。

比较新数据和旧数据时,很明显存在相当大的分歧:有两个提示(prompts)仅存在于“旧”数据中,且相同提示的分数分布非常不同。
所有文本似乎都是在同一时间(12-13 年前)编写的,因为即使是“较新”的文本在写关于探索金星/火星和自动驾驶汽车时,也没有提到任何最近的事件、政治家或亿万富翁。

Persuade 中的一些文本是由不同年级的学生编写的,这可以解释分数的差异(也许他们只是写得更差?!)。为了测试这一点(以及评分阈值的其它细微变化),我仅在旧数据或新数据上训练模型,并在另一方数据上进行评估。我使用 Deberta 集成模型对文本进行排名,并计算了一个“作弊”分数,该分数使用测试数据的确切标签分布将排名转换为预测。这有助于缩小差距,但仍存在相当大的差异。
这让我相信评分者使用的标准实际上存在差异。

由于新数据显然使用了略微不同的评分标准,我将训练设置为一个预训练 -> 微调的两阶段过程。在旧数据(+ 可能的辅助数据)上预训练,并在新数据上微调。这在公共 LB 上带来了至少 0.015 的提升,并使 CV-LB 相关性变得更好。
在每个阶段内,我使用 prompt_id+score 作为标签进行了分层 5 折分割。

训练 Deberta

采用两阶段方法训练 Deberta 相当直接:使用 Deberta base 找到合理的基线,为 Deberta large 找到一组有效的超参数,然后生成一组多样的模型用于创建集成。所有模型都使用回归,我主要评估初始模型的 MSE,因为我只想将它们用于伪标签(PL)。

最佳参数:

参数
基础模型 Deberta large, base
损失函数 MSE, BinaryCrossEntropy (将目标缩放到 [0, 1])
池化 CLS, Gem
上下文长度 1024
Batch size 8
LR torso 1e-5, 5e-6 (预训练 / 微调)
LR head 2e-5, 1e-5
Epochs 2
Warmup 预训练的 15%
Decay cosine
Grad clip 10
Weight decay 0.01
Dropout 0
添加 token "\\n", " " (如 @cdeotte 所分享)
初始化 normal_(mean=0.0, std=0.02), bias=0

为了创建具有多样性的集成,我主要改变了池化、损失、上下文长度,很少改变 LR。据我所知,较短的上下文长度只有在权重为负时才会被选入集成……但有时也会选择 Deberta base。

微调数据集仅包含约 4.5k 个样本。分布在五个提示和六个可能的分数上,意味着数据相当稀缺。模型性能在不同种子之间差异很大,尤其是在使用阈值处理获取整数预测时。为了抵消这一点,我对所有内容进行了 3 种子平均。这对可预测性产生了很大影响。
训练三倍数量的模型非常昂贵,但我发现仅使用不同种子重做微调阶段对性能几乎没有影响,并且节省了大量时间。尽管如此,模型文件夹仍有约 2TB。

伪标签 (Pseudo labelling)

由于评分标准似乎不同,我使用在新数据上微调的集成模型为旧数据获取更好的分数。我做了两轮:第一轮使用 mean(score, ensemble_pred),第二轮仅使用预测(在使用第一轮数据重新训练集成之后)。我总是使用精确的浮点预测,不进行四舍五入。

这里变得有点混乱,第一轮大大改善了 CV,但 LB 仅略有改善。然而,第二轮甚至进一步改善了 CV,实现了巨大的跳跃,但 LB 却下降了。CV 似乎相关性不是很好——我担心有我遗漏的泄漏(我没有改变微调阶段,只使用了原始标签),并且没有太多使用第二轮。然而,其中一个“坏”模型在私有 LB 上得分 0.839,单模型,单种子(它也是 CV 最好的模型)。也许我应该更多地信任 CV,但这似乎太冒险了。

阈值处理(浮点数 -> 整数)

许多人发现,在自定义值(1.67 而不是 1.5)处舍入可以大大改善结果。从我的测试来看,它似乎同时做了几件事:

  1. (过) 拟合目标
  2. 纠正由不平衡分数标签引起的错误
  3. 优化二次加权 Cohen Kappa (QWK)。

1 是显而易见的,2 是由回归损失和不平衡数据引起的——true_label==2 的错误总是偏向多数类 3 而不是 1,导致后者代表性不足。最后一点 3 很重要,因为即使降低了准确率/MSE,Cohen's Kappa 也通常可以通过移动预测(通常朝向少数类)来增加,参见示例。1/2 的典型阈值为 1.7,5/6 的甚至为 4.9(6 分非常少,有些提示甚至没有!)

尾部数据非常稀疏,舍入阈值在不同模型种子之间可能差异很大。我总是使用三个种子来计算阈值,如果没有这个,就太像赌博了。

我所有的提交都是全量拟合(在所有数据上训练模型),这意味着即使使用相同的种子,它们的行为也与 OOF 有所不同。平均可能也对此有所帮助。

为了找到阈值,我使用 scikit.optimize 中的 minimize 配合 "Powell" 方法,在 1 - qwk 上进行评估。结果似乎比 Optuna 等猜测方法更可靠且更快。发现的阈值根据优化的起始点略有不同,我平均了 15 个不同的起始点。

集成 (Ensemble)

我从训练好的模型中通过简单平均、Nelder-Mead 和爬山法(据我所知最早来自 @cdeotte)创建集成。有了 PL、阈值处理和拟合的集成权重,只有 4.5k 个样本,过拟合的机会很大。尤其是当独立拟合阈值和权重时,即使是小集成也会过度拟合数据。我通过预先单独计算每个模型的阈值(3 种子)并对阈值也使用集成权重来抵消这一点。

除此之外,许多提交是简单平均,再挤出 0.001 似乎不如防止过拟合重要。

提交与运气

几乎所有我提交的模型在推理时也是 3 种子平均。因此,我最大的选定集成是 7 个模型,每个模型 3 个种子(21 个 Deberta large)。

我的三个提交是:

模型 伪标签 权重
4 large, 1 base 无 PL 拟合,非负
7 large 第 1 轮 拟合,负值
4 large 第 1 + 2 轮 简单平均

只有最后一个(得分为 0.841)是根据最佳 CV 选择的,其他的是为了多样性而选择的(无模型重叠,不使用 PL ...)。它们的表现差得多:私有 LB 分别为 0.838 和 0.837。

一些最佳 CV 模型:

模型 伪标签 权重 CV 公共 LB 私有 LB
最佳集成,4x large 3x 第 1 轮,1x 第 2 轮 平均 0.832 0.824 0.841
仅来自最佳的第 1 轮 PL 模型,3x large 第 1 轮 平均 0.831 0.823 0.840
仅第 2 轮 PL 模型,1x large 第 2 轮 - 0.830 0.820 0.836
最佳单模型 第 2 轮 - 0.833 0.814 0.839

第二轮 PL 产生了一些像最后一个这样的模型,CV 非常好(像集成一样),但 LB 下降了。我担心有泄漏,但它们在私有 LB 上表现不错,所以也许只是公共 LB 运气不好 ¯\\_(ツ)_/¯

什么有效

有效(大致按重要性排序)

  1. 当你在第 619 名时,信任 CV
  2. 预训练 -> 在新数据上微调 (+0.015)
  3. 伪标签旧数据 (+0.004-0.007)
  4. 对所有内容进行 3 种子平均(主要减少方差,幸运的种子仍然可以工作得很好)
  5. 花大量时间分析分数分布和敏感性(特别是对于阈值处理)
  6. 限制集成中的过拟合(简单平均,不要后拟合阈值...)
  7. Deberta large(base 在公共 LB 上还可以,但 CV 和私有 LB 98% 是 large)

中性/不确定

  1. 额外数据(Persuade, Ellipse)- 非文本依赖文章似乎差别不大
  2. 差异 LR - 差异很小

无效

  1. GBDT,对我来说本身就是一个弱模型,第二阶段似乎没有在集成 + 阈值处理之上增加任何东西(虽然没花太多时间)。
  2. 将 prompt 添加到输入
  3. 回译 (Backtranslation)
  4. 使用 Deberta 进行分类
  5. 注意力池化 (Attention pooling)
  6. 在最后 48 小时匆忙完成效率解决方案 -> 即使是半层 xsmall ONNX 在这里也太慢了,而且这是我唯一能快速产生的东西
同比赛其他方案