小样本学习在文心 ERNIE3.0 多分类工作利用(提醒学习)
我的项目链接:
https://aistudio.baidu.com/aistudio/projectdetail/4438610?contributionType=1
0. 小样本学习简介
二分类 / 多分类工作在商品分类、网页分类、新闻分类、医疗文本分类等事实场景中有着广泛应用。现有的支流解决方案是在大规模预训练语言模型进行微调,因为上游工作和预训练任务训练指标不同,想要获得较好的分类成果往往须要大量标注数据,因而学界和业界开始钻研如何在小样本学习(Few-shot Learning)场景下获得更好的学习效果。
提醒学习(Prompt Learning) 的次要思维是通过工作转换使得上游工作和预训练任务尽可能类似,充分利用预训练语言模型学习到的特色,从而升高样本需求量。除此之外,咱们往往还须要在原有的输出文本上拼接一段“提醒”,来疏导预训练模型输入冀望的后果。
咱们以 Ernie 为例,回顾一下这类预训练语言模型的训练任务。与考试中的完形填空类似,给定一句文本,遮蔽掉其中的局部字词,要求语言模型预测出这些遮蔽地位本来的字词。
因而,咱们也将多分类工作转换为与完形填空类似的模式。例如影评情感分类工作,标签分为 1 - 正向,0- 负向两类。
- 在经典的微调形式中,须要学习的参数是以 [CLS] 向量为输出,以负向 / 正向为输入的随机初始化的分类器。
- 在提醒学习中,咱们通过结构提醒,将原有的分类工作转化为完形填空。如下图所示,通过提醒我 [MASK] 喜爱。,原有 1 - 正向,0- 负向的标签被转化为了预测空格是很还是不。此时的分类器也不再是随机初始化,而是利用了这两个字的预训练向量来初始化,充分利用了预训练模型学习到的参数。
对于标注样本短缺的场景能够间接应用预训练模型微调实现文本多分类,对于尚无标注或者标注样本较少的工作场景咱们举荐应用小样本学习,以获得比微调办法更好的成果。
下边通过新闻分类的例子展现如何应用小样本学习来进行文本分类。
0.1 环境要求
python >= 3.6
paddlepaddle >= 2.3
paddlenlp >= 2.4.0【预计 9 月份上线】
0.1.1 提前尝鲜获取最新版本
!pip install git+
pip 从 git 源码仓库间接 install。要求是这个 github 仓库内要有 setup.py 文件
查看 url:
装置 git 仓库中的包
pip install git+<git 仓库地址 >
pip install git+<git 仓库地址 >@< 分支名称 >
用到它的场景就是比方你有一个代码曾经上传到 github 了,要分发给他人用,你就懒得再下载下来再导出成 tar.gz 或者 whl 文件,是能够间接让他从 github 网址装置
pip install git+http://127.0.0.1/xxx/demo.git --user
pip install git+https://github.com/shadowsocks/[email protected]
等价于:
# 两步走的装置(装置完还须要本人删除 git 文件)git clone http://127.0.0.1/XXX/demo.git
#change dir
cd demo
# install
python setup.py install --user
# windows 环境下加 --user 不然容易报错
# 间接 pip git 无奈装置胜利,那就采纳第二种计划
# !pip install git+https://github.com/PaddlePaddle/[email protected]
先把 paddlenlp develop 分支下下载到本地,进行压缩上传到 aistudio。
$ git clone https://github.com/PaddlePaddle/PaddleNLP.git
Cloning into 'PaddleNLP'...
remote: Enumerating objects: 27619, done.
remote: Counting objects: 100% (125/125), done.
remote: Compressing objects: 100% (106/106), done.
remote: Total 27619 (delta 46), reused 78 (delta 18), pack-reused 27494
Receiving objects: 100% (27619/27619), 73.69 MiB | 3.03 MiB/s, done.
Resolving deltas: 100% (18182/18182), done.
Updating files: 100% (3115/3115), done.
取得的 paddlenl 文件夹在 C:\Users\admin 门路下,而后进行压缩上传到 aistudio
win10 压缩参考上面链接:(或者间接用压缩软件压缩)
https://blog.csdn.net/sinat_3…
zip -q -r paddlenlp.zip PaddleNLP
# !unzip paddlenlp.zip
#这里采纳先装老库再笼罩的计划,确保依赖都装置时,不然间接解压执行 setup.py 会卡主
!pip install --upgrade paddlenlp
%cd PaddleNLP
!python setup.py install --user
%cd ..
0.2 数据集格局要求
# 获取数据
# !wget https://paddlenlp.bj.bcebos.com/datasets/few-shot/tnews.tar.gz
!tar zxvf tnews.tar.gz
!mv tnews data
数据集格局
对于训练 / 验证 / 测试数据集文件,每行数据表示一条样本,包含文本和标签两局部,由 tab 符 \t 分隔。格局如下
文登区这些公路及危桥将进入关闭施工,请留神绕行!news_car
普洱茶要如何醒茶?news_culture
...
对于待预测数据文件,每行蕴含一条待预测样本,无标签。格局如下
互联网时代如何爱护个人信息
清秋暮雨读柳词:忍把浮名,换了浅斟低唱丨周末读诗
...
对于分类标签集文件,存储了数据集中所有的标签汇合,每行为一个标签名。如果须要自定义标签映射用于分类器初始化,则每行须要包含标签名和相应的映射词,由 == 分隔。格局如下
news_car'==' 汽车
news_culture'==' 文化
...
Note 这里的标签映射词定义遵循的规定是,不同映射词尽可能长度统一,映射词和提醒须要尽可能形成通顺的语句。越靠近天然语句,小样本下模型训练成果越好。如果原标签名曾经能够形成通顺语句,也能够不结构映射词,每行一个标签即可。
1. 模型训练与预测
这里提醒一下:
如果运行程序报错:
Traceback (most recent call last):
File "train.py", line 23, in <module>
from paddlenlp.prompt import (ModuleNotFoundError: No module named 'paddlenlp.prompt'
是因为 paddlenlp.prompt 在 2.4.0 版本才会有,请查看下面步骤是否有脱漏,
!export CUDA_VISIBLE_DEVICES=0
!python train.py \
--data_dir ./data/tnews \
--output_dir ./checkpoints/ \
--prompt "这条新闻标题的主题是" \
--max_seq_length 128 \
--learning_rate 3e-5 \
--ppt_learning_rate 3e-4 \
--do_train \
--do_eval \
--max_steps 1000 \
--eval_steps 100 \
--logging_steps 10 \
--per_device_eval_batch_size 32 \
--per_device_train_batch_size 32
后果局部展现:
Training Configuration Arguments
[2022-08-18 11:42:58,983] [INFO] - paddle commit id :3cc6ae69ed93388b2648bcc819d593130dede752
[2022-08-18 11:42:58,983] [INFO] - _no_sync_in_gradient_accumulation:True
[2022-08-18 11:42:58,983] [INFO] - adam_beta1 :0.9
[2022-08-18 11:42:58,983] [INFO] - adam_beta2 :0.999
[2022-08-18 11:42:58,983] [INFO] - adam_epsilon :1e-08
[2022-08-18 11:42:58,983] [INFO] - alpha_rdrop :5.0
[2022-08-18 11:42:58,983] [INFO] - alpha_rgl :0.5
[2022-08-18 11:42:58,983] [INFO] - current_device :gpu:0
[2022-08-18 11:42:58,984] [INFO] - dataloader_drop_last :False
[2022-08-18 11:42:58,984] [INFO] - dataloader_num_workers :0
[2022-08-18 11:42:58,984] [INFO] - device :gpu
[2022-08-18 11:42:58,984] [INFO] - disable_tqdm :False
[2022-08-18 11:42:58,984] [INFO] - do_eval :True
[2022-08-18 11:42:58,984] [INFO] - do_export :False
[2022-08-18 11:42:58,984] [INFO] - do_predict :False
[2022-08-18 11:42:58,984] [INFO] - do_train :True
[2022-08-18 11:42:58,984] [INFO] - eval_batch_size :32
[2022-08-18 11:42:58,984] [INFO] - eval_steps :100
[2022-08-18 11:42:58,984] [INFO] - evaluation_strategy :IntervalStrategy.STEPS
[2022-08-18 11:42:58,984] [INFO] - first_max_length :None
[2022-08-18 11:42:58,984] [INFO] - fp16 :False
[2022-08-18 11:42:58,984] [INFO] - fp16_opt_level :O1
[2022-08-18 11:42:58,984] [INFO] - freeze_dropout :False
[2022-08-18 11:42:58,984] [INFO] - freeze_plm :False
[2022-08-18 11:42:58,984] [INFO] - gradient_accumulation_steps :1
[2022-08-18 11:42:58,984] [INFO] - greater_is_better :None
[2022-08-18 11:42:58,984] [INFO] - ignore_data_skip :False
[2022-08-18 11:42:58,984] [INFO] - label_names :None
[2022-08-18 11:42:58,984] [INFO] - learning_rate :3e-05
[2022-08-18 11:42:58,984] [INFO] - load_best_model_at_end :False
[2022-08-18 11:42:58,984] [INFO] - local_process_index :0
[2022-08-18 11:42:58,984] [INFO] - local_rank :-1
[2022-08-18 11:42:58,984] [INFO] - log_level :-1
[2022-08-18 11:42:58,984] [INFO] - log_level_replica :-1
[2022-08-18 11:42:58,985] [INFO] - log_on_each_node :True
[2022-08-18 11:42:58,985] [INFO] - logging_dir :./checkpoints/runs/Aug18_11-42-56_jupyter-691158-4438610
[2022-08-18 11:42:58,985] [INFO] - logging_first_step :False
[2022-08-18 11:42:58,985] [INFO] - logging_steps :10
[2022-08-18 11:42:58,985] [INFO] - logging_strategy :IntervalStrategy.STEPS
[2022-08-18 11:42:58,985] [INFO] - lr_scheduler_type :SchedulerType.LINEAR
[2022-08-18 11:42:58,985] [INFO] - max_grad_norm :1.0
[2022-08-18 11:42:58,985] [INFO] - max_seq_length :128
[2022-08-18 11:42:58,985] [INFO] - max_steps :5000
[2022-08-18 11:42:58,985] [INFO] - metric_for_best_model :None
[2022-08-18 11:42:58,985] [INFO] - minimum_eval_times :None
[2022-08-18 11:42:58,985] [INFO] - no_cuda :False
[2022-08-18 11:42:58,985] [INFO] - num_train_epochs :3.0
[2022-08-18 11:42:58,985] [INFO] - optim :OptimizerNames.ADAMW
[2022-08-18 11:42:58,985] [INFO] - other_max_length :None
[2022-08-18 11:42:58,985] [INFO] - output_dir :./checkpoints/
[2022-08-18 11:42:58,985] [INFO] - overwrite_output_dir :False
[2022-08-18 11:42:58,985] [INFO] - past_index :-1
[2022-08-18 11:42:58,985] [INFO] - per_device_eval_batch_size :32
[2022-08-18 11:42:58,985] [INFO] - per_device_train_batch_size :32
[2022-08-18 11:42:58,985] [INFO] - ppt_adam_beta1 :0.9
[2022-08-18 11:42:58,985] [INFO] - ppt_adam_beta2 :0.999
[2022-08-18 11:42:58,985] [INFO] - ppt_adam_epsilon :1e-08
[2022-08-18 11:42:58,985] [INFO] - ppt_learning_rate :0.0003
[2022-08-18 11:42:58,985] [INFO] - ppt_weight_decay :0.0
[2022-08-18 11:42:58,985] [INFO] - prediction_loss_only :False
[2022-08-18 11:42:58,985] [INFO] - process_index :0
[2022-08-18 11:42:58,986] [INFO] - remove_unused_columns :True
[2022-08-18 11:42:58,986] [INFO] - report_to :['visualdl']
[2022-08-18 11:42:58,986] [INFO] - resume_from_checkpoint :None
[2022-08-18 11:42:58,986] [INFO] - run_name :./checkpoints/
[2022-08-18 11:42:58,986] [INFO] - save_on_each_node :False
[2022-08-18 11:42:58,986] [INFO] - save_steps :500
[2022-08-18 11:42:58,986] [INFO] - save_strategy :IntervalStrategy.STEPS
[2022-08-18 11:42:58,986] [INFO] - save_total_limit :None
[2022-08-18 11:42:58,986] [INFO] - scale_loss :32768
[2022-08-18 11:42:58,986] [INFO] - seed :42
[2022-08-18 11:42:58,986] [INFO] - should_log :True
[2022-08-18 11:42:58,986] [INFO] - should_save :True
[2022-08-18 11:42:58,986] [INFO] - task_type :multi-class
[2022-08-18 11:42:58,986] [INFO] - train_batch_size :32
[2022-08-18 11:42:58,986] [INFO] - truncate_mode :tail
[2022-08-18 11:42:58,986] [INFO] - use_rdrop :False
[2022-08-18 11:42:58,986] [INFO] - use_rgl :False
[2022-08-18 11:42:58,986] [INFO] - warmup_ratio :0.0
[2022-08-18 11:42:58,986] [INFO] - warmup_steps :0
[2022-08-18 11:42:58,986] [INFO] - weight_decay :0.0
[2022-08-18 11:42:58,986] [INFO] - world_size :1
[2022-08-18 11:42:58,989] [INFO] - ***** Running training *****
[2022-08-18 11:42:58,989] [INFO] - Num examples = 240
[2022-08-18 11:42:58,989] [INFO] - Num Epochs = 625
[2022-08-18 11:42:58,989] [INFO] - Instantaneous batch size per device = 32
[2022-08-18 11:42:58,989] [INFO] - Total train batch size (w. parallel, distributed & accumulation) = 32
[2022-08-18 11:42:58,989] [INFO] - Gradient Accumulation steps = 1
[2022-08-18 11:42:58,989] [INFO] - Total optimization steps = 5000
[2022-08-18 11:42:58,989] [INFO] - Total num train samples = 160000
模型保留,以及指标性能
eval_loss: 3.820039987564087, eval_accuracy: 0.5625, eval_runtime: 3.6311, eval_samples_per_second: 66.095, eval_steps_per_second: 2.203, epoch: 125.0
20%|███████▊ | 1000/5000 [08:21<22:29, 2.96it/s]
100%|█████████████████████████████████████████████| 8/8 [00:01<00:00, 7.33it/s]
[2022-08-18 11:51:20,044] [INFO] - Saving model checkpoint to ./checkpoints/checkpoint-1000
[2022-08-18 11:51:20,045] [INFO] - Trainer.model is not a `PretrainedModel`, only saving its state dict.
[2022-08-18 11:51:26,610] [INFO] - tokenizer config file saved in ./checkpoints/checkpoint-1000/tokenizer_config.json
[2022-08-18 11:51:26,610] [INFO] - Special tokens file saved in ./checkpoints/checkpoint-1000/special_tokens_map.json
# 多卡训练
# !unset CUDA_VISIBLE_DEVICES
# !python -u -m paddle.distributed.launch --gpus 0,1,2,3 train.py \
# --data_dir ./data \
# --output_dir ./checkpoints/ \
# --prompt "这条新闻标题的主题是" \
# --max_seq_length 128 \
# --learning_rate 3e-5 \
# --ppt_learning_rate 3e-4 \
# --do_train \
# --do_eval \
# --max_steps 1000 \
# --eval_steps 100 \
# --logging_steps 10 \
# --per_device_eval_batch_size 32 \
# --per_device_train_batch_size 8 \
# --do_predict \
# --do_export
1.2 预测
在模型训练时开启 –do_predict,训练完结后间接进行预测,也能够在训练完结后,通过运行以下命令加载模型参数进行预测:
可配置参数阐明:
data_dir: 测试数据门路。数据格式要求详见数据筹备,数据应寄存在该目录下 test.txt 文件中,每行一条待预测文本。
output_dir: 日志的保留目录。
resume_from_checkpoint: 训练时模型参数的保留目录,用于加载模型参数。
do_predict: 是否进行预测。
max_seq_length: 最大句子长度,超过该长度的文本将被截断,有余的以 Pad 补全。提醒文本不会被截断。
!python train.py --do_predict --data_dir ./data/tnews --output_dir ./predict_ckpt --resume_from_checkpoint ./checkpoints --max_seq_length 128
[2022-08-18 13:04:45,520] [INFO] - ***** Running Prediction *****
[2022-08-18 13:04:45,520] [INFO] - Num examples = 2010
[2022-08-18 13:04:45,520] [INFO] - Pre device batch size = 8
[2022-08-18 13:04:45,520] [INFO] - Total Batch size = 8
[2022-08-18 13:04:45,520] [INFO] - Total prediction steps = 252
99%|████████████████████████████████████████▋| 250/252 [00:15<00:00, 16.99it/s]***** test metrics *****
test_accuracy = 0.5468
test_loss = 3.4095
test_runtime = 0:00:16.65
test_samples_per_second = 120.664
test_steps_per_second = 15.128
100%|█████████████████████████████████████████| 252/252 [00:15<00:00, 16.44it/s]
2. 模型导出与部署
2.1 导出
在训练完结后,须要将动态图模型导出为动态图参数用于部署推理。能够在模型训练时开启 –do_export 在训练完结后间接导出,也能够运行以下命令加载并导出训练后的模型参数,默认导出到在 output_dir 指定的目录下。
python train.py --do_predict --data_dir ./data --output_dir ./predict_ckpt --resume_from_checkpoint ./ckpt/ --max_seq_length 128
可配置参数阐明:
data_dir: 标签数据门路。数据格式要求详见数据筹备。
output_dir: 动态图模型参数和日志的保留目录。
resume_from_checkpoint: 训练时模型参数的保留目录,用于加载模型参数。
do_export: 是否将模型导出为动态图,保留门路为 output_dir/export。
2.2 模型部署
模型转换与 ONNXRuntime 预测部署依赖 Paddle2ONNX 和 ONNXRuntime,Paddle2ONNX 反对将 Paddle 动态图模型转化为 ONNX 模型格局,算子目前稳固反对导出 ONNX Opset 7~15,更多细节可参考:Paddle2ONNX。
https://github.com/PaddlePadd…
如果基于 GPU 部署,请先确保机器已正确装置 NVIDIA 相关驱动和根底软件,确保 CUDA >= 11.2,CuDNN >= 8.2,并应用以下命令装置所需依赖:
pip install paddle2onnx==1.0.0rc3
python -m pip install onnxruntime-gpu onnx onnxconverter-common
如果基于 CPU 部署,请应用如下命令装置所需依赖:
pip install paddle2onnx==1.0.0rc3
python -m pip install onnxruntime
CPU 端推理样例
python infer.py --model_path_prefix ckpt/export/model --data_dir ./data --batch_size 32 --device cpu
GPU 端推理样例
python infer.py --model_path_prefix ckpt/export/model --data_dir ./data --batch_size 32 --device gpu --device_id 0
可配置参数阐明:
model_path_prefix: 导出的动态图模型门路及文件前缀。
model_name_or_path: 内置预训练模型名,或者模型参数配置目录门路,用于加载 tokenizer。默认为 ernie-3.0-base-zh。
data_dir: 待推理数据所在门路,数据应寄存在该目录下的 data.txt 文件。
max_seq_length: 最大句子长度,超过该长度的文本将被截断,有余的以 Pad 补全。提醒文本不会被截断。
batch_size: 每次预测的样本数量。
device: 抉择推理设施,包含 cpu 和 gpu。默认为 gpu。
device_id: 指定 GPU 设施 ID。
num_threads: 设置 CPU 应用的线程数。默认为机器上的物理内核数。
3. 总结
预训练语言模型的参数空间比拟大,如果在上游工作上间接对这些模型进行微调,为了达到较好的模型泛化性,须要较多的训练数据。在理论业务场景中,特地是垂直畛域、特定行业中,训练样本数量有余的问题宽泛存在,极大地影响这些模型在上游工作的准确度,因而,预训练语言模型学习到的大量常识无奈充沛地施展进去。本我的项目实现基于预训练语言模型的小样本数据调优,从而解决大模型与小训练集不相匹配的问题。
小样本学习是机器学习畛域将来很有前景的一个倒退方向,它要解决的问题很有挑战性、也很有意义。小样本学习中最重要的一点就是先验常识的利用,如果咱们妥善解决了先验常识的利用,可能做到很好的迁移性,想必那时咱们间隔通用 AI 也不远了。
最初也能够看出目前在新闻数据做的小样本 demo 性能后果上还有所欠缺,后续将进行改良。
瞻望: 后续将实现模型交融环节晋升性能,并做可解释性剖析。