返回列表

[29th Place Notes] how to train a single deberta model of 0.972 on public LB

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

开始: 2024-01-17 结束: 2024-04-23 数据安全与隐私 数据算法赛

第29名笔记:如何在公共LB上训练一个达到0.972的单一DeBERTa模型

作者:Yannan Chen
排名:第29名
比赛:PII检测与去除(教育数据)

我真的是一名机器学习新手,这次能够进入银牌区感到非常谦虚。非常感谢所有热心分享想法和代码的人们,包括:@nbroad@valentinweber@thedrcat@emiz6413(tokenization、metric、训练管道),@mpware(高质量外部数据生成),@nischaydnk(Longformer和H2O的替代方案),以及无数讨论帖给我带来的灵感与新思路。

我很感激能成为这次旅程的一部分,并学到很多知识。希望以后能够贡献更多。

▶ 训练参数

  • 学习率:2e‑4 ~ 2.5e‑5
  • 累计批次大小:8 ~ 16
  • 训练轮数:3 ~ 5
  • 对无PII文章的采样率:0.4
  • O类权重:0.2
  • 训练最大长度:3072
  • 训练截断步幅:512
  • 优化器:AdamW
  • 学习率调度:Cosine Annealing

▶ 训练技巧

  1. 仔细手动划分交叉验证折,使每个折的标签分布几乎相同。
    我没有使用 document%4 的方式,而是手动将数据分配到4折,以实现几乎相同的标签分布。特别注意那些同时包含多种稀有标签的文章。
    (我的数据划分Notebook:https://www.kaggle.com/code/yannan90/pii-df-fold
  2. 去掉 B-/I- 前缀,仅训练 8 个标签。(这是最重要的技巧!!)
    使用 13 标签训练的模型在公共 LB 上从未超过 0.96,无论如何调参。检查错误预测时,我发现模型无法理解分配 “B-” 或 “I-” 前缀的逻辑,尤其是人名。于是我去掉标签中的 B-/I- 信息,改用 8 标签训练(在后续处理中再添加 B-/I- 前缀)。此后模型性能显著提升,公共 LB 分数在 0.966 到 0.972 之间,CV 与 LB 的对齐也更好了。该调整还有助于识别过拟合,因为 CV 高(0.98~0.99)的模型往往在 LB 上表现较低(0.95~0.96)。

▶ 后处理(不多)

  1. 使用阈值 0.9。
  2. 添加安全 URL 白名单。
  3. 处理当 “/n” 位于已标记为 ADDRESS 的 token 之间时可能被误标为 ADDRESS 的特殊情况。
  4. 如上所述添加前缀 “B-” 和 “I-”。

从他人方案中学到但未使用的后处理技巧:

  • 删除所有不符合首字母大写、长度为1、包含数字或在黑名单中的 NAME_STUDENT 预测(Mr., Ms., Dr., …)。
  • 如果一篇文档中某名字出现多次且其中一次被标记为 PII,则将所有该名字标记为 PII(非常有效)。
  • 如果预测的 NAME_STUDENT 前有冠词,除非后面跟着 “'s”,否则删除。
  • 将包含 9 位或更多数字的 PHONE_NUM 预测转换为 ID_NUM。
  • 使用正则表达式匹配电话号码。
  • 删除 “:” 和 “-” 对应的 “B-ID_NUM” 预测。

▶ 最终提交推理策略

  1. 组合 3 个在不同折上训练的 DeBERTa‑v3‑large 模型,给予在公共 LB 上得分最高(0.972)的模型最大权重。
  2. 由于训练时使用了不同的 tokenizer,spaCy 的一个 token 不可避免地会被拆分成多个推理 token,从而产生多个预测。在这种情况下,我尝试了三种策略来选择最佳预测:a. 选取第一个预测;b. 选取 O 概率最小的预测;c. 选取正类概率最大的预测。最终选择了策略 c。

(我的提交 Notebook:https://www.kaggle.com/code/yannan90/pii-infer-ensemble-ignorebi

▶ 经验教训 & 进一步提升

  • 使用 llama‑3 70b / mixtral‑8x‑7b 生成外部数据。 提示模型在训练数据中加入针对性内容(链接)。
  • 使用改写工具对误报样本进行改写并加入训练集。Dipper Paraphraser XXL
  • 清洗并重新标注训练数据中的错误标签。
  • 在分类器前加入 BiLSTM 层: 有助于多样性并使训练曲线更平滑。
  • 知识蒸馏: 使用在不同数据集上训练的模型作为教师,对同一验证折的学生进行蒸馏。
  • 数据增强: 交换或更改某些文章中的名字。
  • 为 tokenizer 添加换行符 token: tokenizer.add_tokens(["\n", "\n\n"], special_tokens=True)
  • 在损失函数中对外部数据使用较低的权重: 训练数据样本权重为 1.0,额外数据样本权重为 0.5。
  • 在硬预测时对 O 类概率进行缩放后再取 argmax, 而不是使用 O 概率阈值。
  • 通过观察错误 OOF 预测的模式进行更多后处理。
  • 多元化模型进行集成:
    • a. 使用不同模型类型,尤其是使用不同 tokenizer 的模型。
    • b. 训练/推理时带前缀和不带前缀的模型混合。
    • c. 训练/推理时使用不同 max_length 的模型组合。
    PS:我只提交了 DeBERTa‑v3‑large 的集成,因为它们在 CV 和 LB 上表现最好。现在我知道我的另一个集成(DeBERTa‑v3‑large + Longformer)在私有 LB 上取得了 0.9662(金牌区),但由于 Longformer 在 CV 和 LB 上表现不佳,我没有提交。真是遗憾 LOL!
  • 加速集成推理的技巧:
    • a. 使用 FP16 进行推理。
    • b. 使用 ONNX(链接)。
    • c. 动态填充(链接)。
    • d. 根据不同 token 长度采用不同的批次大小。

方案参考链接

同比赛其他方案