项目介绍

  • 本项目为讯飞赛题:中文问题相似度挑战赛 paddle 版本 baseline。
  • 特点为:不用写代码,直接运行 PaddleNLP 提供的 demo 脚本,只需三分钟即可跑完训练并生成提交文件。
  • 提交分数为 0.88,在比赛初期(50支队伍时)确实能排名 top10,可为后面的优化提供必要的参考。

赛道介绍

赛道链接

点击直达

赛事背景

问答系统中包括三个主要的部分:问题理解,信息检索和答案抽取。而问题理解是问答系统的第一部分也是非常关键的一部分。问题理解有非常广泛的应用,如重复评论识别、相似问题识别等。

重复问题检测是一个常见的文本挖掘任务,在很多实际问答社区都有相应的应用。重复问题检测可以方便进行问题的答案聚合,以及问题答案推荐,自动QA等。由于中文词语的多样性和灵活性,本赛题需要选手构建一个重复问题识别算法。

赛事任务

本次赛题希望参赛选手对两个问题完成相似度打分。

  • 训练集:约5千条问题对和标签。若两个问题是相同的问题,标签为1;否则为0。
  • 测试集:约5千条问题对,需要选手预测标签。

评估指标

本次竞赛的评价标准采用准确率指标。

数据集说明

训练集给定问题对和标签,使用 \t 进行分隔。测试集给定问题对,使用 \t 进行分隔。

eg:世界上什么东西最恐怖 世界上最恐怖的东西是什么? 1

解析:“世界上什么东西最恐怖” 与 ”世界上最恐怖的东西是什么“ 问题相同,故是重复问题,标签为 1。

简单 EDA

  • 正样本:负样本为 2892:2108,相对比较平均
  • 文本平均长度为 21,最长文本为 83 个字符 (合并 texta 和 textb)

Baseline 思路

这是一道常规的中文文本匹配赛题。BERT 处理文本匹配任务是将其转换为二分类问题,流程如下:

  1. 输入的两个文本拼接为一个序列 (中间用特殊符号 “SEP” 分割)
  2. 经过多层 transformer 模块编码后,将输出层的字向量取平均或者取 “CLS” 位置的特征作为句向量
  3. 经 softmax 完整最终分类

我们使用 PaddleNLP 提供的 ernie_matching demo 脚本实现上述功能:https://github.com/PaddlePaddle/PaddleNLP/tree/develop/examples/text_matching/ernie_matching

在该项目提供的说明中,我们了解到:

我们基于预训练模型 ERNIE-Gram 给出了单塔文本匹配的 2 种训练范式: Point-wise 和 Pair-wise。其中单塔 Point-wise 匹配模型适合直接对文本对进行 2 分类的应用场景: 例如判断 2 个文本是否为语义相似;Pair-wise 匹配模型适合将文本对相似度作为特征之一输入到上层排序模块进行排序的应用场景。

因此我们直接采用 Point-wise 模式。

另外在该项目的效果对比中,ERNIE-Gram-Base 比 ERNIE-1.0-Base 效果要好,因此我们采用前者。

安装 PaddleNLP

!pip -q install -U paddlenlp==2.0.2

从 gitee 中拷贝 PaddleNLP 的代码 (直接从 github 克隆比较慢)

!git clone https://gitee.com/paddlepaddle/PaddleNLP.git

拷贝 ernie_matching 代码目录到当前目录

!cp -a PaddleNLP/examples/text_matching/ernie_matching .

比赛数据集

创建目录并拷贝划分训练集、验证集及测试集。

为了方便考虑,将原来训练集中的前 4200 条数据划为训练集,后 800 条数据划为验证集。

!mkdir -pv ernie_matching/datasets
!head -4200 data/data102210/train.csv > ernie_matching/datasets/train.tsv
!tail -800 data/data102210/train.csv > ernie_matching/datasets/dev.tsv
!cp -v data/data102210/test.csv ernie_matching/datasets/test.tsv

该比赛的数据集与 lcqmc 的格式一致,所以我们可以直接用 paddlenlp 里定义的 lcqmc 类。

但是需要修改代码 ernie_matching/train_pointwise.py 将 load_dataset 改为本地模式,增加参数如下:

data_files=("./datasets/train.tsv", "./datasets/dev.tsv"))
!sed -i 's#train_ds, dev_ds = load_dataset("lcqmc", splits=\["train", "dev"\])#train_ds, dev_ds = load_dataset("lcqmc", data_files=("./datasets/train.tsv", "./datasets/dev.tsv"))#' ernie_matching/train_pointwise.py

开始训练

一切准备就绪后,可以开始训练了,参数说明如下:

  • –device gpu 使用 GPU
  • –gpus “0” 指定 GPU
  • –save_dir ./checkpoints 模型保存的位置, 会自动创建目录
  • –save_step 300 多久保存一次, 这里需要注意,默认为 10000,而我们训练的轮次较小,所以会导致没有保存,这里 demo 脚本可以优化下,在训练完成后自动保存一个最终的状态
  • –max_seq_length 可选,默认为 128,这个比赛的文本比较短,最大长度为 49,因此先不改了
!cd ernie_matching && python -u -m paddle.distributed.launch --gpus "0" train_pointwise.py --device gpu --save_dir ./checkpoints --save_step 300 --batch_size 32 --learning_rate 2E-5

模型预测

执行脚本 predict_pointwise.py 进行模型预测

!cd ernie_matching && python -u -m paddle.distributed.launch --gpus "0" predict_pointwise.py --device gpu --params_path "./checkpoints/model_300/model_state.pdparams" --batch_size 128 --max_seq_length 64 --input_file 'datasets/test.tsv' > result.txt

生成提交文件

由于 predict 脚本输出的格式为

{'query': 'xxxxx', 'title': 'yyyyy', 'pred_label': 0}

所以我们还需要按照比赛的提交格式生成提交文件。

!echo 'label' > sub.txt
!/bin/grep -Po "(?<='pred_label': )\d+" ernie_matching/result.txt >> sub.txt

前十留念:

后续优化方向

  1. 多尝试不同的模型,以及调参;
  2. 多折交叉验证;
  3. 数据增强:同义词替换和回译;
  4. 融合或者 stacking

Logo

学大模型,用大模型上飞桨星河社区!每天8点V100G算力免费领!免费领取ERNIE 4.0 100w Token >>>

更多推荐