Kaggle自动写作评估 2.0 Top方案汇总。



↑↑↑关注后"星标"kaggle竞赛宝典
  kaggle竞赛宝典  作者:Coggle

Kaggle赛题总结:自动写作评估 2.0

  • 比赛名称:Learning Agency Lab - Automated Essay Scoring 2.0
  • 比赛类型:自然语言处理
  • 比赛任务:改进论文评分算法,以提高学生的学习成果

https://www.kaggle.com/competitions/learning-agency-lab-automated-essay-scoring-2

unsetunset比赛背景unsetunset

论文写作是评估学生学习和表现的重要方法。但对教育者来说,手工评分非常耗时。自动写作评估(AWE)系统可以评分文章,作为教育者其他努力的补充。AWE还允许学生及时获得关于他们写作的定期反馈。 然而,由于成本较高,许多该领域的先进技术并不普及到学生和教育者手中。有必要开发开源解决方案来评估学生的写作,以便将这些重要的教育工具普及到每个社区。

先前开发的开源AWE努力受到了小型数据集的限制,这些数据集在国家范围内缺乏多样性,并且侧重于常见的文章格式。第一次自动评分竞赛评分学生的简答回答,但这种写作任务在课堂上并不经常使用。为了改进先前的努力,需要一个更广泛的数据集,其中包含高质量、现实的课堂写作样本。此外,为了扩大影响力,数据集应包含不同经济和地理背景的样本,以减少算法偏见的可能性。

比赛主办方范德堡大学是位于田纳西州纳什维尔的一所私立研究型大学。对于此次比赛,范德堡大学与The Learning Agency Lab合作,后者是一家位于亚利桑那州的独立非营利组织,致力于为社会福祉开发基于学习科学的工具和项目。

unsetunset比赛任务unsetunset

在过去的十二年里,自动化评分技术已经取得了显著的进步,特别是在处理学生写作文章评分方面。最初的自动化评分比赛标志着这一领域的开端,但在随后的岁月里,通过更新数据集、引入新的想法和技术,我们已经取得了长足的进步。

这项比赛的目标是训练一个模型来评分学生的文章。我们希望通过您的努力,减少手工评分所需的高昂费用和时间。 可靠的自动化评分技术可以使文章评分成为可能,这是目前由于评分难度而普遍避免的测试中的重要组成部分。

unsetunset评价指标unsetunset

提交的论文将根据二次加权kappa进行评分,该指标衡量了两个结果之间的一致性。这个度量通常从0(随机一致性)到1(完全一致性)变化。如果一致性低于预期的随机一致性,那么该度量可能会低于0。二次加权kappa的计算如下。首先,构建一个N x N的直方图矩阵O,使得对应于收到预测值的论文ID (实际值)的数量。

unsetunset提交格式unsetunset

对于测试集中的每个essay_id,您必须预测相应的分数(在数据页面上描述)。文件应包含一个标题,并具有以下格式:

essay_id,score
000d118,3
000fe60,3
001ab80,4
...

unsetunset数据集介绍unsetunset

竞赛数据集包含约24000篇学生撰写的议论性文章。每篇文章的得分在1到6的范围内(链接到整体评分标准)。您的目标是根据文本预测文章的得分。

文件和字段信息:

train.csv - 作为训练数据使用的文章和得分。

  • essay_id - 文章的唯一ID
  • full_text - 完整的文章内容
  • score - 文章的整体得分,范围为1到6

test.csv - 作为测试数据使用的文章。包含与train.csv相同的字段,除了排除了score。

sample_submission.csv - 符合正确格式的提交文件。

  • essay_id - 文章的唯一ID
  • score - 文章的预测整体得分,范围为1到6

unsetunset优胜方案分享unsetunset

第1名

https://www.kaggle.com/competitions/learning-agency-lab-automated-essay-scoring-2/discussion/516791

这个一等方案展示了作者如何通过仔细的数据分析、模型训练和伪标签(pseudo-labelling)技术来提高自动评分算法的性能。以下是方案的详细介绍:

关键步骤

  1. 数据分析 + 实验,发现新的数据评分模式并获得CV-LB相关性。
  2. 训练反映这些分数的Deberta集成模型。
  3. 进行两轮伪标签以获得带有新分数的旧数据。
  4. 通过阈值处理将浮点预测转换为整数。
  5. 在不过拟合的情况下进行集成。

交叉验证稳定性

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

通过比较新旧数据,发现评分标准存在明显差异。旧数据中有两个题目在新数据中没有出现,而相同题目的评分分布也有很大不同。所有文章似乎都是同时写的(12-13年前),因为即使是“新”文章也没有提到最近的事件、政治人物或亿万富翁。

为了测试这些差异,我训练了只使用旧数据或新数据的模型,并在另一组数据上评估它们。使用Deberta集成模型对文本进行排名,并计算“作弊”分数,该分数使用测试数据的确切标签分布将排名转换为预测。这有助于缩小差距,但仍然存在相当大的差异,这让我相信评分标准确实存在差异。

由于新数据显然使用了略有不同的评分标准,我设置了分阶段的训练过程:在旧数据上预训练,然后在新数据上微调。这使得公共LB的得分至少提高了0.015,并使CV-LB相关性大大改善。每个阶段我都使用了分层的5折交叉验证。

训练Deberta

通过两阶段方法,训练Deberta相对简单:首先找到一个不错的基线,使用Deberta base,然后找到适用于Deberta large的超参数,并生成一组可以用于创建集成模型的多样化模型。所有模型都使用回归,我主要评估MSE,因为我希望它们仅用于伪标签。

最佳参数:

参数
基础模型 Deberta large, base
损失函数 MSE, BinaryCrossEntropy (将目标缩放到[0, 1])
池化 CLS, Gem
上下文长度 1024
批量大小 8
学习率(躯干) 1e-5, 5e-6 (预训练 / 微调)
学习率(头) 2e-5, 1e-5
训练轮数 2
预热比例 15%
衰减 余弦
梯度裁剪 10
权重衰减 0.01
随机失活 0
增加的标记 "\n", " " (由@cdeotte分享)
初始化 normal_(mean=0.0, std=0.02), bias=0

为了创建具有多样性的集成模型,我主要改变了池化方式、损失函数、上下文长度,很少改变学习率。较短的上下文长度有时也被选择,但权重是负的… 但有时也选择了Deberta base。

微调数据集仅包含约4.5k样本。分布在五个提示下有六个可能的分数,这意味着数据非常稀缺。不同种子的模型性能差异很大,尤其是在使用阈值处理获得整数预测时。为了解决这个问题,我将所有内容进行了3种子平均。这显著提高了可预测性。训练三倍数量的模型成本很高,但我发现只重新进行微调阶段几乎没有任何性能差异,节省了大量时间。即便如此,模型文件夹大约有2TB。

伪标签

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

这里有些混乱,第一轮显著提高了CV,但LB只略有提升。第二轮进一步提高了CV,但LB却下降了。CV似乎没有很好地相关——我担心有漏掉的地方(我没有改变微调阶段,只使用了原始标签),所以没有多用第二轮。然而,一个“坏”模型在私有LB上得分0.839(单模型,单种子),可能我应该更相信CV。

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

很多人发现使用自定义值(1.67而不是1.5)进行舍入可以显著提高结果。通过我的测试,它似乎做了几件事:

  1. 过拟合目标
  2. 修正由于不平衡的标签造成的错误
  3. 优化二次加权科恩的卡帕(QWK)。

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

尾部数据非常稀缺,不同模型种子的舍入阈值差异很大。我总是使用三个种子计算阈值,没有这个太像赌博了。

所有我的提交都是全数据训练的(使用所有数据训练模型),这意味着它们总是与OOF有些不同,即使使用相同的种子。平均可能有助于这一点。

为了找到阈值,我使用了scikit.optimize中的minimize,优化目标是1 - qwk。结果似乎比Optuna等猜测方法更可靠、更快。找到的阈值基于优化起点有所不同,我平均了15个不同的起点。

第2名

https://www.kaggle.com/competitions/learning-agency-lab-automated-essay-scoring-2/discussion/516582

所有模型的训练方法

  1. 两阶段训练:首先在Kaggle-Persuade上训练,然后加载权重并在Kaggle-Only上用相同的损失函数进行训练。
  2. 在整个训练集上进行10个epoch的MLM。
  3. 交叉验证:4折分层K折交叉验证。在Kaggle-Persuade和Kaggle-Only数据上验证。
  4. 保存最后一个epoch的检查点(在第一阶段和第二阶段)。
  5. 随机种子。

为什么需要两阶段训练? 在我看来,如果我们使用整个训练集训练,模型会更多地学习Kaggle-Persuade的分布(可能因为其数据量较大?我想),这会导致在Kaggle-Only集上表现不佳。因此,使用两阶段训练让模型先从Kaggle-Persuade中学习知识,然后在Kaggle-Only上微调以学习Kaggle-Only的分布,这更类似于我们的隐藏测试集。

阈值搜索

我使用OptimizedRounder 此处 为每个单模型和混合模型搜索最佳阈值。经过一些实验,我发现5和6的最后一个阈值是次优的。因此,我创建了一个for循环来搜索最佳的最后一个阈值,这提升了CV、LB和PB。

一个简单的想法是仅在Kaggle-Only数据集上搜索阈值,因为这些文本更类似于测试集。尽管这给了很好的CV,但LB下降了很多,因此我假设隐藏测试集的分数分布与我们的完整训练集相似。然后我仅在整个训练集上进行阈值搜索,结果是好的LB/PB。

第3名

vhttps://www.kaggle.com/competitions/learning-agency-lab-automated-essay-scoring-2/discussion/517014

阶段1:初始训练

  • 使用数据:结合 Data A(来自 Persuade Corpus 2.0)和 Data B(来自其他来源)。
  • 目标:使用两个数据集训练模型,并基于 Data B 进行评估,在每个 epoch 保存模型。

阶段2:微调

  • 使用数据:Data B。

  • 目标:加载阶段1的权重,仅在 Data B 上进行训练,同时在 Data A 上进行评估以防止过拟合。

  • 结果:该策略显著提高了 CV 和私人排行榜(LB)分数,特别是对 Data B,表明该方法的有效性。

  • 换行符的特殊标记:DeBERTa 模型忽略换行符("\n"),因此将其转换为 "[BR]" 并在 tokenizer 中设为特殊标记。这一步预处理步骤遵循了先前 FeedbackPrize 竞赛中使用的方法。

交叉验证策略

最初,方案基于提示名称使用分组 k 折交叉验证(group k-fold),这导致了高排行榜分数但存在显著的折间变异和数据不平衡。随后,策略转变为基于提示名称和分数的多标签分层 k 折交叉验证(Multilabel Stratified K-Fold),分别应用于 Data A 和 Data B。

主干和训练稳定性

  • 主干:DeBERTa-v3 系列,选择原因是 token 大小通常超过 512。
  • 训练稳定性:利用掩码语言建模(MLM)预训练和层冻结(DeBERTa-v3-base/xsmall 冻结 9 层,DeBERTa-v3-large 冻结 6 层)。
  • 损失函数:选择回归与二元交叉熵(BCE)损失,这比分类更稳定。

第二阶段中的软标签

  • 在第二阶段训练中,基于第一阶段的 out-of-fold 预测使用软标签。这种方法提高了 CV 和公共排行榜分数。

最终集成

最终集成使用 Nelder-Mead 优化方法,关注以下模型配置:

  • 主干:DeBERTa-v3-base 和 DeBERTa-v3-large。
  • 最大长度:1024 和 1536。
  • 层冻结:base 模型冻结 9 层,large 模型冻结 6 层。
  • 池化方法:MeanPooling 与 LayerNorm,AttentionPooling 和 LSTMPooling。

第4名

https://www.kaggle.com/competitions/learning-agency-lab-automated-essay-scoring-2/discussion/516639

竞赛的一个关键挑战在于训练和测试数据集的组成。在 train.csv 中,有 12,875 个样本来自 Persuade 数据集,而 4,432 个样本来自非 Persuade 数据集。

在 DeBERTa-v3-large 基线训练中,不同 epoch 的 QWK 结果如下:

Epoch 1: QWK: 0.8289 (0.7896, 0.8403)
Epoch 2: QWK: 0.8370 (0.7946, 0.8491)
Epoch 3: QWK: 0.8347 (0.7838, 0.8493)
Epoch 4: QWK: 0.8260 (0.7742, 0.8409)
Epoch 5: QWK: 0.8229 (0.7703, 0.8381)

如果将数据源标签添加到 full_text,如 '[A] {full_text}' 表示非 Persuade 数据,'[B] {full_text}' 表示 Persuade 数据,结果如下:

Epoch 1: QWK: 0.8282 (0.7953, 0.8371)
Epoch 2: QWK: 0.8401 (0.8082, 0.8487)
Epoch 3: QWK: 0.8446 (0.8093, 0.8541)
Epoch 4: QWK: 0.8424 (0.8033, 0.8528)
Epoch 5: QWK: 0.8395 (0.8022, 0.8496)

基于实验结果,我假设这两种数据源的评分方式不同,混合训练会影响模型的拟合能力。

训练期间

  1. 为输入添加标签以区分数据源。
  2. 添加一个数据源分类头,以确保模型的输出特征可以区分数据源。
  3. 对一些模型使用不同的数据源分类头。
  4. 基于非 Persuade 样本的评分进行早停。

我的最终提交是一个大型集成(平均 45 个预测):

  1. 3 个模型:microsoft/deberta-largemicrosoft/deberta-v3-largeQwen/Qwen2-1.5B-Instruct
  2. 5 折交叉验证
  3. 3 次运行(不同随机种子)

由于文本长度不固定,为减少填充的影响,我将一个批次拆分为总 token 数限制的微批次。这使得训练更快,内存使用更稳定。梯度累积训练循环如下:

for batch in dataloader:
    optimizer.zero_grad()
    total_batch_size = sum(micro_batch["batch_size"for micro_batch in batch)
    for micro_batch in batch:
        micro_batch = to_gpu(micro_batch)
        loss = model(micro_batch)
        scale = micro_batch["batch_size"] / total_batch_size
        (loss * scale).backward()
    optimizer.step()


相关推荐

  • 不管你信不信,面试官让我使用 JS 计算 LocalStorage 的容量!
  • 混沌工程&FMEA——可用性隐患分析治理最佳拍档
  • 李飞飞最终还是选择创业了
  • 字符串的 intern 机制是怎么一回事?
  • 开源日历 Cal.com 项目:自定义你的时间管理(Github项目分享)
  • 如何用 JavaScript 模拟点击事件,简单实现 x, y 坐标点击?
  • SpringBoot + RabbitMQ:轻松实现邮件大批量异步推送!
  • CCL2024·第二十三届中国计算语言大会讲习班公布
  • 会议开幕倒计时三天!CCAC 2024 主要报告介绍
  • 大模型集体失智!9.11和9.9哪个大,几乎全翻车了
  • [开源]一款MES系统基础上进行二次开发的ERP系统,高效智能的运营
  • Meta开发System 2蒸馏技术,Llama 2对话模型任务准确率接近100%
  • ECCV 2024 | 模型逆向攻击高性能新范式,人脸隐私安全问题新思考
  • 对齐全量微调!这是我看过最精彩的LoRA改进
  • 多人同时导出 Excel 干崩服务器?大佬给出的解决方案太优雅了!
  • 6个强大且流行的Python爬虫库,强烈推荐!
  • Spring Cloud Eureka快读入门Demo
  • 菊花开!!!带您深入菊花链
  • 6步!!!用 Electron开发一个记事本
  • 113K Star微软甄选!!!用这个框架开发百万人爱的VSCode