基于Python的自然语言处理任务(文本分类、文本匹配、语义理解和序列标注)

资源下载地址:https://download.csdn.net/download/sheziqiong/88308584
资源下载地址:https://download.csdn.net/download/sheziqiong/88308584

1. 依赖环境

  • Python >= 3.6

  • torch >= 1.1

  • argparse

  • json

  • loguru

  • numpy

  • packaging

  • re

2. 文本分类

本项目展示了以 BERT 为代表的预训练模型如何 Finetune 完成文本分类任务。我们以中文情感分类公开数据集 ChnSentiCorp 为例,运行如下的命令,基于 DistributedDataParallel 进行单机多卡分布式训练,在训练集 (train.tsv) 上进行模型训练,并在验证集 (dev.tsv) 上进行评估:

CUDA_VISIBLE_DEVICES=0,1 python -m torch.distributed.launch --nproc_per_node=2 run_classifier.py --train_data_file ./data/ChnSentiCorp/train.tsv --dev_data_file ./data/ChnSentiCorp/dev.tsv --label_file ./data/ChnSentiCorp/labels.txt --save_best_model --epochs 3 --batch_size 32

可支持的配置参数:

usage: run_classifier.py [-h] [--local_rank LOCAL_RANK]
                         [--pretrained_model_name_or_path PRETRAINED_MODEL_NAME_OR_PATH]
                         [--init_from_ckpt INIT_FROM_CKPT] --train_data_file
                         TRAIN_DATA_FILE [--dev_data_file DEV_DATA_FILE]
                         --label_file LABEL_FILE [--batch_size BATCH_SIZE]
                         [--scheduler {linear,cosine,cosine_with_restarts,polynomial,constant,constant_with_warmup}]
                         [--learning_rate LEARNING_RATE]
                         [--warmup_proportion WARMUP_PROPORTION] [--seed SEED]
                         [--save_steps SAVE_STEPS]
                         [--logging_steps LOGGING_STEPS]
                         [--weight_decay WEIGHT_DECAY] [--epochs EPOCHS]
                         [--max_seq_length MAX_SEQ_LENGTH]
                         [--saved_dir SAVED_DIR]
                         [--max_grad_norm MAX_GRAD_NORM] [--save_best_model]
                         [--is_text_pair]
  • local_rank: 可选,分布式训练的节点编号,默认为 -1。

  • pretrained_model_name_or_path: 可选,huggingface 中的预训练模型名称或路径,默认为 bert-base-chinese。

  • train_data_file: 必选,训练集数据文件路径。

  • dev_data_file: 可选,验证集数据文件路径,默认为 None。

  • label_file: 必选,类别标签文件路径。

  • batch_size: 可选,批处理大小,请结合显存情况进行调整,若出现显存不足,请适当调低这一参数。默认为 32。

  • init_from_ckpt: 可选,要加载的模型参数路径,热启动模型训练。默认为None。

  • scheduler: 可选,优化器学习率变化策略,默认为 linear。

  • learning_rate: 可选,优化器的最大学习率,默认为 5e-5。

  • warmup_proportion: 可选,学习率 warmup 策略的比例,如果为 0.1,则学习率会在前 10% 训练 step 的过程中从 0 慢慢增长到 learning_rate,而后再缓慢衰减。默认为 0。

  • weight_decay: 可选,控制正则项力度的参数,用于防止过拟合,默认为 0.0。

  • seed: 可选,随机种子,默认为1000。

  • logging_steps: 可选,日志打印的间隔 steps,默认为 20。

  • save_steps: 可选,保存模型参数的间隔 steps,默认为 100。

  • epochs: 可选,训练轮次,默认为 3。

  • max_seq_length: 可选,输入到预训练模型中的最大序列长度,最大不能超过 512,默认为 128。

  • saved_dir: 可选,保存训练模型的文件夹路径,默认保存在当前目录的 checkpoint 文件夹下。

  • max_grad_norm: 可选,训练过程中梯度裁剪的 max_norm 参数,默认为 1.0。

  • save_best_model: 可选,是否在最佳验证集指标上保存模型,当训练命令中加入

    –save_best_model 时,save_best_model 为 True,否则为 False。

  • is_text_pair: 可选,是否进行文本对分类,当训练命令中加入 --is_text_pair 时,进行文本对的分类,否则进行普通文本分类。

模型训练的中间日志如下:

2022-05-25 07:22:29.403 | INFO     | __main__:train:301 - global step: 20, epoch: 1, batch: 20, loss: 0.23227, accuracy: 0.87500, speed: 2.12 step/s
2022-05-25 07:22:39.131 | INFO     | __main__:train:301 - global step: 40, epoch: 1, batch: 40, loss: 0.30054, accuracy: 0.87500, speed: 2.06 step/s
2022-05-25 07:22:49.010 | INFO     | __main__:train:301 - global step: 60, epoch: 1, batch: 60, loss: 0.23514, accuracy: 0.93750, speed: 2.02 step/s
2022-05-25 07:22:58.909 | INFO     | __main__:train:301 - global step: 80, epoch: 1, batch: 80, loss: 0.12026, accuracy: 0.96875, speed: 2.02 step/s
2022-05-25 07:23:08.804 | INFO     | __main__:train:301 - global step: 100, epoch: 1, batch: 100, loss: 0.21955, accuracy: 0.90625, speed: 2.02 step/s
2022-05-25 07:23:13.534 | INFO     | __main__:train:307 - eval loss: 0.22564, accuracy: 0.91750
2022-05-25 07:23:25.222 | INFO     | __main__:train:301 - global step: 120, epoch: 1, batch: 120, loss: 0.32157, accuracy: 0.90625, speed: 2.03 step/s
2022-05-25 07:23:35.104 | INFO     | __main__:train:301 - global step: 140, epoch: 1, batch: 140, loss: 0.20107, accuracy: 0.87500, speed: 2.02 step/s
2022-05-25 07:23:44.978 | INFO     | __main__:train:301 - global step: 160, epoch: 2, batch: 10, loss: 0.08750, accuracy: 0.96875, speed: 2.03 step/s
2022-05-25 07:23:54.869 | INFO     | __main__:train:301 - global step: 180, epoch: 2, batch: 30, loss: 0.08308, accuracy: 1.00000, speed: 2.02 step/s
2022-05-25 07:24:04.754 | INFO     | __main__:train:301 - global step: 200, epoch: 2, batch: 50, loss: 0.10256, accuracy: 0.93750, speed: 2.02 step/s
2022-05-25 07:24:09.480 | INFO     | __main__:train:307 - eval loss: 0.22497, accuracy: 0.93083
2022-05-25 07:24:21.020 | INFO     | __main__:train:301 - global step: 220, epoch: 2, batch: 70, loss: 0.23989, accuracy: 0.93750, speed: 2.03 step/s
2022-05-25 07:24:30.919 | INFO     | __main__:train:301 - global step: 240, epoch: 2, batch: 90, loss: 0.00897, accuracy: 1.00000, speed: 2.02 step/s
2022-05-25 07:24:40.777 | INFO     | __main__:train:301 - global step: 260, epoch: 2, batch: 110, loss: 0.13605, accuracy: 0.93750, speed: 2.03 step/s
2022-05-25 07:24:50.640 | INFO     | __main__:train:301 - global step: 280, epoch: 2, batch: 130, loss: 0.14508, accuracy: 0.93750, speed: 2.03 step/s
2022-05-25 07:25:00.529 | INFO     | __main__:train:301 - global step: 300, epoch: 2, batch: 150, loss: 0.04770, accuracy: 0.96875, speed: 2.02 step/s
2022-05-25 07:25:05.256 | INFO     | __main__:train:307 - eval loss: 0.23039, accuracy: 0.93500
2022-05-25 07:25:16.818 | INFO     | __main__:train:301 - global step: 320, epoch: 3, batch: 20, loss: 0.04312, accuracy: 0.96875, speed: 2.04 step/s
2022-05-25 07:25:26.700 | INFO     | __main__:train:301 - global step: 340, epoch: 3, batch: 40, loss: 0.05103, accuracy: 0.96875, speed: 2.02 step/s
2022-05-25 07:25:36.588 | INFO     | __main__:train:301 - global step: 360, epoch: 3, batch: 60, loss: 0.12114, accuracy: 0.87500, speed: 2.02 step/s
2022-05-25 07:25:46.443 | INFO     | __main__:train:301 - global step: 380, epoch: 3, batch: 80, loss: 0.01080, accuracy: 1.00000, speed: 2.03 step/s
2022-05-25 07:25:56.228 | INFO     | __main__:train:301 - global step: 400, epoch: 3, batch: 100, loss: 0.14839, accuracy: 0.96875, speed: 2.04 step/s
2022-05-25 07:26:00.953 | INFO     | __main__:train:307 - eval loss: 0.22589, accuracy: 0.94083
2022-05-25 07:26:12.483 | INFO     | __main__:train:301 - global step: 420, epoch: 3, batch: 120, loss: 0.14986, accuracy: 0.96875, speed: 2.05 step/s
2022-05-25 07:26:22.289 | INFO     | __main__:train:301 - global step: 440, epoch: 3, batch: 140, loss: 0.00687, accuracy: 1.00000, speed: 2.04 step/s

当需要进行文本对分类时,仅需设置 is_text_pair 为 True。以 CLUEbenchmark 中的 AFQMC 蚂蚁金融语义相似度数据集为例,可以运行如下的命令进行训练:

CUDA_VISIBLE_DEVICES=0,1 python -m torch.distributed.launch --nproc_per_node=2 run_classifier.py --train_data_file ./data/AFQMC/train.txt --dev_data_file ./data/AFQMC/dev.txt --label_file ./data/AFQMC/labels.txt --is_text_pair --save_best_model --epochs 3 --batch_size 32

在不同数据集上进行训练,验证集上的效果如下:

Task ChnSentiCorp AFQMC TNEWS
dev-acc 0.94083 0.74305 0.56990

TNEWS 为 CLUEbenchmark 中的今日头条新闻分类数据集。

CLUEbenchmark 数据集链接: https://github.com/CLUEbenchmark/CLUE

3. 文本匹配

本项目展示了如何基于 Sentence-BERT 结构 Finetune 完成中文文本匹配任务。Sentence BERT 采用了双塔 (Siamese) 的网络结构。Query 和 Title 分别输入到两个共享参数的 bert encoder 中,得到各自的 token embedding 特征。然后对 token embedding 进行 pooling (论文中使用 mean pooling 操作),输出分别记作 u 和 v。最后将三个向量 (u,v,|u-v|) 拼接起来输入到线性分类器中进行分类。

当使用 NLI 数据进行训练时,需要加入 --is_nli 选项和 --label_file LABEL_FILE,训练命令如下:

CUDA_VISIBLE_DEVICES=0,1 python -m torch.distributed.launch --nproc_per_node=2 run_sentencebert.py --train_data_file ./data/CMNLI/train.txt --dev_data_file ./data/CMNLI/dev.txt --label_file ./data/CMNLI/labels.txt --is_nli --save_best_model --epochs 3 --batch_size 32

在不同数据集上进行训练,验证集上的效果如下:

Task LCQMC Chinese-MNLI Chinese-SNLI
dev-acc 0.86730 0.71105 0.80567

Chinese-MNLI 和 Chinese-SNLI 链接: https://github.com/zejunwang1/CSTS

4. 语义理解

4.1 SimCSE

SimCSE 模型适合缺乏监督数据,但是又有大量无监督数据的匹配和检索场景。本项目实现了 SimCSE 无监督方法,并在中文维基百科句子数据上进行句向量表示模型的训练。

更多关于 SimCSE 的信息可以参考论文: https://arxiv.org/abs/2104.08821

从中文维基百科中抽取 15 万条句子数据,保存于 data/zhwiki/ 文件夹下的 wiki_sents.txt 文件中,运行下面的命令,基于腾讯 uer 开源的预训练语言模型 uer/chinese_roberta_L-6_H-128 (https://huggingface.co/uer/chinese_roberta_L-6_H-128) ,使用 SimCSE 无监督方法进行训练,并在 Chinese-STS-B 验证集 ( https://github.com/zejunwang1/CSTS ) 上进行评估:

CUDA_VISIBLE_DEVICES=0,1 python -m torch.distributed.launch --nproc_per_node=2 run_simcse.py --pretrained_model_name_or_path uer/chinese_roberta_L-6_H-128 --train_data_file ./data/zhwiki/wiki_sents.txt --dev_data_file ./data/STS-B/sts-b-dev.txt --learning_rate 5e-5 --epochs 1 --dropout 0.1 --margin 0.2 --scale 20 --batch_size 32

隐藏层数 num_hidden_layers=6,维度 hidden_size=128 的 SimCSE 句向量预训练模型 simcse_tiny_chinese_wiki 可以从如下链接获取:

model_name link
WangZeJun/simcse-tiny-chinese-wiki https://huggingface.co/WangZeJun/simcse-tiny-chinese-wiki

4.2 In-Batch Negatives

从哈工大 LCQMC 数据集、谷歌 PAWS-X 数据集、北大文本复述 PKU-Paraphrase-Bank 数据集 (https://github.com/zejunwang1/CSTS) 中抽取出所有语义相似的文本 Pair 作为训练集,保存于:data/batchneg/paraphrase_lcqmc_semantic_pairs.txt

运行下面的命令,基于腾讯 uer 开源的预训练语言模型 uer/chinese_roberta_L-6_H-128,采用 In-batch negatives 策略,在 GPU 0,1,2,3 四张卡上训练句向量表示模型,并在 Chinese-STS-B 验证集上进行评估:

CUDA_VISIBLE_DEVICES=0,1,2,3 python -m torch.distributed.launch --nproc_per_node=4 run_batchneg.py --pretrained_model_name_or_path uer/chinese_roberta_L-6_H-128 --train_data_file ./data/batchneg/paraphrase_lcqmc_semantic_pairs.txt --dev_data_file ./data/STS-B/sts-b-dev.txt --learning_rate 5e-5 --epochs 3 --margin 0.2 --scale 20 --batch_size 64 --mean_loss

以上面得到的模型为热启,在句子数据集 data/batchneg/domain_finetune.txt 上继续进行 In-batch negatives 训练:

CUDA_VISIBLE_DEVICES=0,1 python -m torch.distributed.launch --nproc_per_node=2 run_batchneg.py --pretrained_model_name_or_path uer/chinese_roberta_L-6_H-128 --init_from_ckpt ./checkpoint/pytorch_model.bin --train_data_file ./data/batchneg/domain_finetune.txt --dev_data_file ./data/STS-B/sts-b-dev.txt --learning_rate 1e-5 --epochs 1 --margin 0.2 --scale 20 --batch_size 32 --mean_loss

可以得到隐藏层数 num_hidden_layers=6,维度 hidden_size=128 的句向量预训练模型:

model_name link
WangZeJun/batchneg-tiny-chinese https://huggingface.co/WangZeJun/batchneg-tiny-chinese

5. 序列标注

本项目展示了以 BERT 为代表的预训练模型如何 Finetune 完成序列标注任务。以中文命名实体识别任务为例,分别在 msra、ontonote4、resume 和 weibo 四个数据集上进行训练和测试。每个数据集的训练集和验证集均被预处理为如下的格式,每一行为文本和标签组成的 json 字符串。

{
    
    "text": ["我", "们", "的", "藏", "品", "中", "有", "几", "十", "册", "为", "北", "京", "图", "书", "馆", "等", "国", "家", "级", "藏", "馆", "所", "未", "藏", "。"], "label": ["O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "B-NS", "I-NS", "I-NS", "I-NS", "I-NS", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O"]}
{
    
    "text": ["由", "于", "这", "一", "时", "期", "战", "争", "频", "繁", ",", "条", "件", "艰", "苦", ",", "又", "遭", "国", "民", "党", "毁", "禁", ",", "传", "世", "量", "稀", "少", ",", "购", "藏", "不", "易", "。"], "label": ["O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "B-NT", "I-NT", "I-NT", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O"]}

运行下面的命令,在 msra 数据集上使用 BERT+Linear 结构进行单机多卡分布式训练,并在验证集上进行评估:

大部分参数与文本分类中介绍的相同,如下为特有的参数:

  • tag: 可选,实体标记方法,支持 bios 和 bio 的标注方法,默认为 bios。

  • use_crf: 可选,是否使用 CRF 结构,当训练命令中加入 --use_crf 时,使用 BERT+CRF 模型结构;否则使用 BERT+Linear 模型结构。

  • crf_learning_rate: 可选,CRF 模型参数的初始学习率,默认为 5e-5。

当使用 BERT+CRF 结构进行训练时,运行下面的命令:

CUDA_VISIBLE_DEVICES=0,1 python -m torch.distributed.launch --nproc_per_node=2 run_ner.py --train_data_file ./data/ner/msra/train.json --dev_data_file ./data/ner/msra/dev.json --label_file ./data/ner/msra/labels.txt --tag bios --learning_rate 5e-5 --save_best_model --batch_size 32 --use_crf --crf_learning_rate 1e-4

模型在不同验证集上的 F1 指标:

模型 Msra Resume Ontonote Weibo
BERT+Linear 0.94179 0.95643 0.80206 0.70588
BERT+CRF 0.94265 0.95818 0.80257 0.72215

其中 Msra、Resume 和 Ontonote 训练了 3 个 epochs,Weibo 训练了 5 个 epochs,Resume、Ontonote 和 Weibo 的 logging_steps 和 save_steps 均设置为 10,所有数据集的 BERT 参数初始学习率设置为 5e-5,CRF 参数初始学习率设置为 1e-4,batch_size 设置为 32。

资源下载地址:https://download.csdn.net/download/sheziqiong/88308584
资源下载地址:https://download.csdn.net/download/sheziqiong/88308584

猜你喜欢

转载自blog.csdn.net/newlw/article/details/132729673