615. Learning Agency Lab - Automated Essay Scoring 2.0 | learning-agency-lab-automated-essay-scoring-2
非常感谢 Kaggle 和主办方举办这场精彩的比赛!虽然直到最后都紧张得出汗,但整个过程非常有趣。
祝贺 @syhens 和 @dsohonosom,你们大部分时间都处于领先地位!直到最后我还在想,你们这么高的分数是不是过拟合了公共 LB —— 但看来你们只是有一些非常好的解决方案!
感谢 @cdeotte 从一开始就支撑着这次比赛并分享了这么多资源。感谢 @cpmpml 分享了更快的 QWK 计算方法。
数据集包含大约 12 年前 8-12 年级学生写的文章。比赛使用了依赖文本的文章,但大部分数据取自 Persuade 语料库,其中包括额外的独立写作任务。比赛数据中有约 13k 篇 Persuade 文章(“旧”)和 4.5k 篇未见过的(“新”)文章。
比较新数据和旧数据时,很明显存在相当大的分歧:有两个提示(prompts)仅存在于“旧”数据中,且相同提示的分数分布非常不同。
所有文本似乎都是在同一时间(12-13 年前)编写的,因为即使是“较新”的文本在写关于探索金星/火星和自动驾驶汽车时,也没有提到任何最近的事件、政治家或亿万富翁。
Persuade 中的一些文本是由不同年级的学生编写的,这可以解释分数的差异(也许他们只是写得更差?!)。为了测试这一点(以及评分阈值的其它细微变化),我仅在旧数据或新数据上训练模型,并在另一方数据上进行评估。我使用 Deberta 集成模型对文本进行排名,并计算了一个“作弊”分数,该分数使用测试数据的确切标签分布将排名转换为预测。这有助于缩小差距,但仍存在相当大的差异。
这让我相信评分者使用的标准实际上存在差异。
由于新数据显然使用了略微不同的评分标准,我将训练设置为一个预训练 -> 微调的两阶段过程。在旧数据(+ 可能的辅助数据)上预训练,并在新数据上微调。这在公共 LB 上带来了至少 0.015 的提升,并使 CV-LB 相关性变得更好。
在每个阶段内,我使用 prompt_id+score 作为标签进行了分层 5 折分割。
采用两阶段方法训练 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。
由于评分标准似乎不同,我使用在新数据上微调的集成模型为旧数据获取更好的分数。我做了两轮:第一轮使用 mean(score, ensemble_pred),第二轮仅使用预测(在使用第一轮数据重新训练集成之后)。我总是使用精确的浮点预测,不进行四舍五入。
这里变得有点混乱,第一轮大大改善了 CV,但 LB 仅略有改善。然而,第二轮甚至进一步改善了 CV,实现了巨大的跳跃,但 LB 却下降了。CV 似乎相关性不是很好——我担心有我遗漏的泄漏(我没有改变微调阶段,只使用了原始标签),并且没有太多使用第二轮。然而,其中一个“坏”模型在私有 LB 上得分 0.839,单模型,单种子(它也是 CV 最好的模型)。也许我应该更多地信任 CV,但这似乎太冒险了。
许多人发现,在自定义值(1.67 而不是 1.5)处舍入可以大大改善结果。从我的测试来看,它似乎同时做了几件事:
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 个不同的起始点。
我从训练好的模型中通过简单平均、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 运气不好 ¯\\_(ツ)_/¯