返回列表

1st place solution - Ensemble of diverse Deberta architectures and postprocessing

604. The Learning Agency Lab - PII Data Detection | pii-detection-removal-from-educational-data

开始: 2024-01-17 结束: 2024-04-23 数据安全与隐私 数据算法赛
第一名方案 - 多样化 Deberta 架构集成与后处理

第一名方案 - 多样化 Deberta 架构集成与后处理

作者:Geremie Yeo 等

发布日期:2024-04-24

首先,感谢 Kaggle 和 The Learning Agency Lab 举办的这场比赛,既有趣又非常贴近实际应用!

感谢 @gauravbrills@ympaik@drpatrickchan@evgeniimaslov2 的精彩合作!

背景

业务背景:Kaggle PII 检测与去除

数据背景:数据说明

方法概览

方法概览图

数据集

以下是我们使用的数据集:

建模

每个实验使用 4 折训练(document % 4),随后进行 1 或 2 次全量拟合。

  • 所有训练统一使用 13 个标签。
  • 模型在最大长度 1600‑2048 上训练 3‑4 个 epoch。
  • 学习率 1e‑5。
  • 不对没有 PII 的文章进行下采样。
  • o_weight = 0.05。

我们尝试了多种模型和架构。由于 Deberta 在推理速度快且在 LB 与 CV 上表现优秀,我们将多种 Deberta 变体加入集成。主要尝试包括:

多采样 Dropout 自定义模型

帮助训练曲线更平滑,减少普通模型训练时出现的尖峰。

BiLSTM 层自定义模型

在分类器之前加入 BiLSTM 层,已在公开笔记本中使用。此举提升了多样性,训练更平稳,分数与 LB、CV 关联良好。训练时若出现 NaN 损失,初始化该层并使用 save_safetensors=False 保存可解决问题。

知识蒸馏

由于部分模型在不同的数据集上训练,我们尝试使用这些模型作为教师,对在另一数据集上训练的学生模型进行蒸馏,使用相同的验证折。此方法显著提升了 CV 与 LB,提升幅度约 0.005‑0.01。我们也曾尝试使用多个教师模型,但时间不足未能完成。

数据增强

我们尝试在部分作文中进行姓名交换后再训练(例如文档 7779 中 “Leroy” 既是 B‑NAME_STUDENT 又是 I‑NAME_STUDENT),以此作为集成的一个实验。

感谢 @gauravbrills 提出的第 2、3 点,提升了我们集成的多样性。

知识蒸馏损失函数

class CustomTrainer(Trainer):
    def __init__(self, *args, class_weights=None, teacher_model=None, **kwargs):
        super().__init__(*args, **kwargs)
        self.class_weights = class_weights
        self.teacher_model = teacher_model.to(self.args.device)
        self.temperature = 3
        self.alpha = 0.5

    def compute_loss(self, model, inputs, return_outputs=False):
        labels = inputs.pop("labels").to(self.args.device)
        inputs = {name: tensor.to(self.args.device) for name, tensor in inputs.items()}
        outputs = model(**inputs)

        with torch.no_grad():
            teacher_outputs = self.teacher_model(**inputs)

        teacher_logits = teacher_outputs.logits
        logits = outputs.logits
        loss_fct = torch.nn.CrossEntropyLoss(weight=self.class_weights.to(self.args.device))

        loss_student = loss_fct(logits.view(-1, self.model.config.num_labels), labels.view(-1))
        distillation_loss = torch.nn.KLDivLoss()(F.log_softmax(logits / self.temperature, dim=-1),
                                                F.softmax(teacher_logits / self.temperature, dim=-1)) * self.temperature ** 2
        loss = loss_student * self.alpha + distillation_loss * (1 - self.alpha)

        return (loss, outputs) if return_outputs else loss

后处理

后处理是提升 CV 与 LB 的关键。我们根据 OOF 预测中的错误模式采用了以下步骤:

  • 对每个 PII 标签使用不同的阈值,而不是对全部 13 个标签使用统一阈值。
  • 删除所有不符合首字母大写或包含数字/下划线的 NAME_STUDENT 预测。
  • 如果文档中某个词 X 被预测为 NAME_STUDENT,则该文档中所有 X 均转为 NAME_STUDENT(如文档 2722 中的 “Saman”)。
  • 若存在 9 位或以上的 PHONE_NUM 预测,则将其改为 ID_NUM。
  • 修复 STREET_ADDRESS 中遗漏的 “\n” 换行符。
  • 若连续 3 个 token 被预测为 B‑USERNAME,且第二个 token 是连字符或句点,则将第 2、3 个 token 改为 I‑USERNAME。
  • 删除长度小于 4 或大于 25 的 ID_NUM 预测。
  • 删除长度小于 10 的 URL_PERSONAL 预测。
  • 删除不包含 “@” 符号的 EMAIL 预测。
  • 完成上述所有步骤后,修复 NAME_STUDENT 与 ID_NUM 的跨度,并在模型遗漏时使用正则表达式补充预测。

提交细节

  • 采用加权投票集成方法,使用 7 组共 10 个模型。各组权重与投票阈值通过在交叉验证上使用 Optuna 调优。
  • 每组包含 1‑2 个模型,并使用折叠/全拟合模型以提升多样性。
  • 全部 3 个提交均为集成,且使用不同的模型与权重。我们选用了 2 个完整后处理的提交以及 1 个更保守的后处理提交,以防止后处理过拟合。

哪些方法没有成功

  • MLM 预训练
  • 冻结层
  • 尝试修复 I‑URL_PERSONAL 预测
  • CausalLM 推理,速度太慢
  • 使用 Stride 的训练/推理
  • Longformer / LLM 模型
  • 针对单一标签的模型(例如仅训练 NAME_STUDENT,其他 PII 标签设为 O)
  • 使用稀有/多国姓名进行数据增强
  • 对测试数据进行伪标签

团队成员

  • Geremie Yeo(领队)
  • Gaurav Rawat
  • YoungPaik
  • Patrick Chan
  • Yevhenii Maslov
同比赛其他方案