目录
PaddleNLP 联合 PaddleSlim 通过模型蒸馏、剪裁、量化等级联模型压缩技术发布中文特色小模型 PP-MiniLM(6L768H) 及压缩方案,保证模型精度的同时模型推理速度达 BERT(12L768H) 的 4.2 倍,参数量相比减少 52%,模型精度在中文语言理解评测基准 CLUE 高 0.62。
PP-MiniLM 压缩方案以面向预训练模型的任务无关知识蒸馏(Task-agnostic Distillation)技术、裁剪(Pruning)技术、量化(Quantization)技术为核心,使得 PP-MiniLM 又快、又准、又小。
-
推理速度快: 依托 PaddleSlim 的裁剪、量化技术对 PP-MiniLM 小模型进行压缩、加速, 使得 PP-MiniLM 量化后模型 GPU 推理速度相比 BERT base 加速比高达 4.2;
-
精度高: 我们以 MiniLMv2 提出的 Multi-Head Self-Attention Relation Distillation 技术为基础,通过引入样本间关系知识蒸馏做了进一步算法优化,6 层 PP-MiniLM 模型在 CLUE 数据集上比 12 层
bert-base-chinese高 0.62%,比同等规模的 TinyBERT、UER-py RoBERTa 分别高 2.57%、2.24%; -
参数规模小:依托 Task-agnostic Distillation 技术和 PaddleSlim 裁剪技术,模型参数量相比 BERT 减少 52%。
整体效果
| Model | #Params | #FLOPs | Speedup | AFQMC | TNEWS | IFLYTEK | CMNLI | OCNLI | CLUEWSC2020 | CSL | CLUE 平均值 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| BERTbase | 102.3M | 10.87B | 1.00x | 74.14 | 56.81 | 61.10 | 81.19 | 74.85 | 79.93 | 81.47 | 72.78 |
| TinyBERT6 | 59.7M | 5.44B | 1.66x | 72.59 | 55.70 | 57.64 | 79.57 | 73.97 | 76.32 | 80.00 | 70.83 |
| UER-py RoBERTa L6- H768 | 59.7M | 5.44B | 1.66x | 69.62 | 66.45 | 59.91 | 76.89 | 71.36 | 71.05 | 82.87 | 71.16 |
| RBT6, Chinese | 59.7M | 5.44B | 1.66x | 73.93 | 56.63 | 59.79 | 79.28 | 73.12 | 77.30 | 80.80 | 71.55 |
| ERNIE-Tiny | 90.7M | 4.83B | 1.89x | 71.55 | 58.34 | 61.41 | 76.81 | 71.46 | 72.04 | 79.13 | 70.11 |
| PP-MiniLM 6L-768H | 59.7M | 5.44B | 1.66x | 74.14 | 57.43 | 61.75 | 81.01 | 76.17 | 86.18 | 79.17 | 73.69 |
| PP-MiniLM 裁剪后 | 49.1M | 4.08B | 2.00x | 73.91 | 57.44 | 61.64 | 81.10 | 75.59 | 85.86 | 78.53 | 73.44 |
| PP-MiniLM 量化后 | 49.2M | - | 4.15x | 74.00 | 57.37 | 61.33 | 81.09 | 75.56 | 85.85 | 78.57 | 73.40 |
NOTE:
1.上表所有模型的精度测试均是基于下方超参数范围进行的 Grid Search 超参寻优。在每个配置下训练时,每隔 100 个 steps 在验证集上评估一次,取验证集上最佳准确率作为当前超参数配置下的准确率;
- batch sizes: 16, 32, 64;
- learning rates: 3e-5, 5e-5, 1e-4
2.量化后比量化前模型参数量多了 0.1M 是因为保存了 scale 值。
方案流程
如上流程图所示,完整的中文小模型方案分为:导入 PP-MiniLM 中文预训练小模型、下游任务微调、裁剪、离线量化、预测部署五大步。下面会对这里的每一个步骤进行介绍。除了下游任务微调步骤,其余步骤均可以省略,但我们建议保留下面的每一个步骤。
以下是本范例模型的简要目录结构及说明:
.
├── general_distill # 任务无关知识蒸馏目录
│ └── general_distill.py # 任务无关知识蒸馏脚本
│ └── run.sh # 任务无关知识蒸馏启动脚本
│ └── README.md # 任务无关知识蒸馏文档
├── finetuning # 下游任务训练目录
│ └── run_clue.py # CLUE 上的微调脚本
│ └── run_clue.sh # CLUE 上的微调启动脚本
│ └── run_one_search.sh # 单数据集下精调脚本
│ └── run_all_search.sh # CLUE数据集下精调脚本
│ └── export_model.py # 导出 fine-tuned 部署模型脚本
├── pruning # 裁剪、蒸馏目录
│ └── prune.py # 裁剪、蒸馏脚本
│ └── prune.sh # 裁剪、蒸馏启动脚本
│ └── export_model.py # 导出裁剪训练得到的子模型(动、静态图模型)
├── quantization # 离线量化目录
│ └── quant_post.py # 离线量化脚本
│ └── quant.sh # 离线量化启动脚本
├── inference # 预测目录
│ └── infer.py # 预测脚本
│ └── infer_all.sh # 批量预测量化模型启动脚本
│ └── infer_perf.py # 量化模型性能测试脚本
│ └── infer_perf.sh # 量化模型性能测试启动脚本
├── data.py # 数据处理脚本
├── pp-minilm.png # PP-MiniLM 方案流程图
└── README.md # 文档,本文件
PP-MiniLM 是使用任务无关蒸馏方法,以 roberta-wwm-ext-large 做教师模型蒸馏产出的含 6 层 Transformer Encoder Layer、Hidden Size 为 768 的预训练小模型,在 CLUE 上 7 个分类任务上的模型精度超过 BERTbase、TinyBERT6、UER-py RoBERTa L6-H768、RBT6。
可以这样导入 PP-MiniLM:
from paddlenlp.transformers import PPMiniLMModel, PPMiniLMForSequenceClassification
model = PPMiniLMModel.from_pretrained('ppminilm-6l-768h')
model = PPMiniLMForSequenceClassification.from_pretrained('ppminilm-6l-768h') # 用于分类任务PP-MiniLM 是一个 6 层的预训练模型,使用 from_pretrained导入 PP-MiniLM 之后,就可以在自己的数据集上进行 fine-tuning。接下来会介绍如何用下游任务数据在导入的 PP-MiniLM 上进行微调、进一步压缩及推理部署。
NOTE: 如果对 PP-MiniLM 的训练过程感兴趣,可以查看任务无关蒸馏文档了解相关细节。
PP-MiniLM 预训练小模型在 CLUE 中的 7 个分类数据集的平均精度上比 12 层 bert-base-chinese 高 0.62%,比同等规模的 TinyBERT、UER-py RoBERTa 分别高 2.57%、2.24%,因此我们推荐将 PP-MiniLM 运用在中文下游任务上。当然,如果想对已有模型进一步压缩,也可以参考这里的压缩方案,因为压缩方案是通用的。
本案例中会以 CLUE 中 7 个分类数据集为例介绍如何在下游任务上使用 PP-MiniLM。首先用 CLUE 中的数据集对预训练小模型 PP-MiniLM 进行微调,然后提供了一套压缩方案,即借助 PaddleSlim 进行裁剪和量化,进一步对模型规模进行压缩,最终使用基于 TensorRT 的 Paddle Inference 预测库对量化后的模型进行预测部署。裁剪、量化前,6 层 PP-MiniLM 的推理速度达 bert-base-chinese 的 1.7 倍,在下游任务上压缩完成后,模型推理速度高达bert-base-chinese的 4.2 倍。
本案例中下游任务使用的数据是 CLUE 中 7 个分类数据集,包括 AFQMC、TNEWS、IFLYTEK、OCNLI、CMNLI、CSL、CLUEWSC2020。在 Linux 环境下,运行 run_clue.py 这个 fine-tuning 脚本会将该数据集自动下载到~/.paddlenlp/datasets/Clue/目录下。
压缩方案依赖 PaddleSlim 提供的裁剪、量化功能,因此需要安装 paddleslim。PaddleSlim 是个专注于深度学习模型压缩的工具库,提供剪裁、量化、蒸馏、和模型结构搜索等模型压缩策略,帮助用户快速实现模型的小型化。
pip install -U paddleslim -i https://pypi.org/simple基于如下超参范围对 PP-MiniLM 在各个任务上进行 Grid Search 超参寻优:
- batch sizes: 16, 32, 64
- learning rates: 3e-5, 5e-5, 1e-4
cd finetuning
mkdir ppminilm-6l-768h
sh run_all_search.sh ppminilm-6l-768h如果只是在单个数据集上用特定 batch_size、learning_rate 微调,可以使用如下命令:
sh run_clue.sh CLUEWSC2020 1e-4 32 50 128 0 ppminilm-6l-768h
其中每个参数依次表示:CLUE 中的任务名称、学习率、batch size、epoch 数、最大序列长度、gpu id、模型名称(模型保存目录)。
经过超参寻优后,我们可以得到在 CLUE 每个任务上验证集上有最高准确率的模型,CLUE 上各个任务上的最高准确率如下表:
| AFQMC | TNEWS | IFLYTEK | CMNLI | OCNLI | WSC | CSL | CLUE 平均值 |
|---|---|---|---|---|---|---|---|
| 74.14 | 57.43 | 61.75 | 81.01 | 76.17 | 86.18 | 77.47 | 73.45 |
超参寻优完成后,保存下每个数据集下有最高准确率的模型,以及其对应的超参数,因裁剪、量化等后续步骤需要用到最好的模型和超参数。
如果模型经过了超参寻优,在这一步我们可以在每个任务上选择表现最好的模型进行导出。
假设待导出的模型的地址为 ppminilm-6l-768h/models/CLUEWSC2020/1e-4_32,可以运行下方命令将动态图模型导出为可用于部署的静态图模型:
python export_model.py --model_type ppminilm --model_path ppminilm-6l-768h/models/CLUEWSC2020/1e-4_32 --output_path fine_tuned_infer_model/float
cd ..这一步主要使用 PaddleSlim 对下游任务上的模型宽度进行裁剪,进一步压缩模型的大小。
该过程会以上一步的模型(即 fine-tuning 后得到的最好模型)当作教师模型,蒸馏宽度为 3/4 的学生模型。经过我们的实验,在 6L768H 条件下,模型宽度压缩为原来的 3/4,平均精度下降 0.25。
本方案采取的裁剪方法参考了 DynaBERT-Dynamic BERT with Adaptive Width and Depth 中的策略。首先对预训练模型和 Head 进行重要性排序,保证更重要的 Head 不容易被裁掉,然后用原模型作为蒸馏过程中的教师模型,宽度更小的(本案例是 3/4 宽度)模型作为学生模型,蒸馏得到的学生模型就是我们裁剪得到的模型。
假设需要对上一步 fine-tuned 模型 ../finetuning/ppminilm-6l-768h/models/CLUEWSC2020/1e-4_32 进行裁剪,其中 learning_rate、batch_size 可以继续使用 fine-tuning 时的参数,这里执行的是宽度 0.75 的裁剪,可以使用如下命令运行:
cd pruning
export FT_MODELS=../finetuning/ppminilm-6l-768h/models/CLUEWSC2020/1e-4_32
sh prune.sh CLUEWSC2020 1e-4 32 50 128 0 ${FT_MODELS} 0.75其中每个参数依次表示:CLUE 中的任务名称、学习率、batch size、epoch 数、最大序列长度、gpu id、学生模型的地址、裁剪后宽度比例列表。执行完成后,模型保存的路径位于 pruned_models/CLUEWSC2020/0.75/best_model/。
经过裁剪后,CLUE 上各个任务上的精度如下表所示。相比起裁剪前,CLUE 数据集上平均值下降 0.25。模型的参数量由 59.7M 下降到 49.1M。
| Model | AFQMC | TNEWS | IFLYTEK | CMNLI | OCNLI | CLUEWSC2020 | CSL | CLUE 平均值 |
|---|---|---|---|---|---|---|---|---|
| PP-MiniLM 裁剪后 | 73.91 | 57.44 | 61.64 | 81.10 | 75.59 | 85.86 | 78.53 | 73.44 |
这一步可以同时导出经过裁剪后特定宽度下模型的动、静态图的模型和参数等文件。
以 CLUEWSC2020 数据集为例,导出模型:
export MODEL_PATH=pruned_models
export TASK_NAME=CLUEWSC2020
sh export.sh ${MODEL_PATH} ${TASK_NAME}或者可以批量导出 CLUE 各个任务上的模型:
sh export_all.sh
cd ..导出的静态图模型、参数等文件位于 ${MODEL_PATH}/${TASK_NAME}/0.75/sub_static/ 目录下,有 float.pdmodel、float.pdiparams、float.pdiparams.info 三个文件。
导出的动态图参数等文件位于 ${MODEL_PATH}/${TASK_NAME}/0.75/sub/model_width_0.75000/ 目录下,有 model_state.pdparams 和 model_config.json 两个文件。需要注意的是,此动态图模型不能通过原始 Transformer API 将参数正确载入,因为裁剪后模型不再符合 Transformer 的组网,例如 q、k、v 的 weight 的 shape 是 [hidden_size, hidden_size * width_mul] ,不再是 [hidden_size, hidden_size]。
cd quantization这里的量化采用的是静态离线量化方法,即不需要训练,只使用少量校准数据计算量化因子,就可快速得到量化模型。这一步需要有训练好的预测(静态图)模型。因此,需要对前序步骤产出的模型进行导出(参考上方导出模型的运行方式)。
量化我们可以借助 PaddleSlim 提供的离线量化 API paddleslim.quant.quant_post_static 实现,我们这一步使用了 mse、avg、abs_max、hist 四种策略,并使用 4、8 两种校准集数量,对 matmul、matmul_v2 算子进行channel_wise_abs_max 类型的量化。
运行如下脚本可以得到静态离线量化后的模型:
export MODEL_DIR=../pruning/pruned_models/
python quant_post.py --task_name $TASK_NAME --input_dir ${MODEL_DIR}/${TASK_NAME}/0.75/sub_static可以批量对所有数据集下的 FP32 模型进行量化:
sh quant_all.sh
cd ..经过量化后,CLUE 上各个任务上的精度如下表,比上一步(裁剪后)精度几乎无损(-0.04):
| Model | AFQMC | TNEWS | IFLYTEK | CMNLI | OCNLI | CLUEWSC2020 | CSL | CLUE 平均值 |
|---|---|---|---|---|---|---|---|---|
| PP-MiniLM 量化后 | 74.00 | 57.37 | 61.33 | 81.09 | 75.56 | 85.85 | 78.57 | 73.40 |
最后,值得注意的是,PP-MiniLM 是基于 roberta-wwm-ext-large 做教师模型蒸馏得到的学生模型,如果你有更好的 24 层中文预训练模型,可以基于任务无关蒸馏文档中介绍的蒸馏过程,训练出一个比 PP-MiniLM 精度更高,在下游任务上表现更好的 6 层小模型。
预测部署借助 PaddlePaddle 安装包中自带的 Paddle Inference 进行预测。
这一步依赖安装有预测库的 PaddlePaddle 2.2.1。可以在 PaddlePaddle 官网 根据机器环境选择合适的 Python 预测库进行安装。
想要得到更明显的加速效果,推荐在 NVIDA Tensor Core GPU(如 T4、A10、A100)上进行测试,本案例基于 T4 测试。若在 V 系列 GPU 卡上测试,由于其不支持 Int8 Tensor Core,加速效果将达不到本文档表格中的效果。
本案例是在 NVIDIA Tesla T4 单卡上,使用 cuda 11.1、cudnn 8.1、TensorRT 7.2 进行预测。
这里使用了动态 shape 功能,因此需要设置获取 shape 的范围。Paddle Inference 提供了相应的接口,即首先通过离线输入数据来统计出所有临时 tensor 的 shape 范围,TRT 子图的 tensor 输入 shape 范围可直接根据上一步 tune 出来的结果来设置,即可完成自动 shape 范围设置。统计完成后,只需设置统计结果路径,即可启用 tuned_dynamic_shape 功能。在本案例中,只需要先设置 --collect_shape 参数,运行 infer.py,然后再取消传入这个参数,再次运行 infer.py。例如:
INT8 预测运行脚本:
cd inference
export task=tnews
export algo=mse
export bs=4
python infer.py --task_name ${task} --model_path ../quantization/${task}_quant_models/${algo}${bs}/int8 --int8 --use_trt --collect_shape # 生成shape range info文件
python infer.py --task_name ${task} --model_path ../quantization/${task}_quant_models/${algo}${bs}/int8 --int8 --use_trt # load shape range info文件进行预测如果想要批量对量化模型进行预测并输出不同量化策略产出模型的精度,可以使用如下的脚本批量预测:
sh infer_all.shFP32 预测运行脚本:
python infer.py --task_name ${task} --model_path $MODEL_PATH --use_trt --collect_shape
python infer.py --task_name ${task} --model_path $MODEL_PATH --use_trt测试性能环境同上。本案例测试采用的是 CLUE TNEWS 数据集下量化方法为 mse、校准集数量为 4 得到的量化模型,在 TNEWS 的验证集上统计 5 次端到端预测的总耗时(前 20 个 steps 作为 warmup steps 跳过)并求平均。其中 batch_size 为 32,max_seq_len 为 128。
启动性能测试需要对 infer.py 脚本传入参数 --perf,运行性能测试脚本可以得到 PP-MiniLM、PP-MiniLM 裁剪后、PP-MiniLM 量化后模型预测的耗时:
sh infer_perf.sh
cd ..下表后三行分别是微调后的模型、裁剪后的模型、量化后模型的总耗时情况。
取 5 个非 --collect_shape 阶段打印出的时长取平均,可以发现借助 PaddleSlim 裁剪、量化后的模型是原 BERTbase模型推理速度的 4.2 倍,其中裁剪后的模型是 BERTbase推理速度的 2.0 倍。
| 平均耗时 (s) | 加速比 | |
|---|---|---|
| BERTbase | 21.04 | - |
| PP-MiniLM | 12.64 | 1.66x |
| PP-MiniLM裁剪后 | 10.54 | 2.00x |
| PP-MiniLM量化后 | 5.07 | 4.15x |
1.Wang W, Bao H, Huang S, Dong L, Wei F. MiniLMv2: Multi-Head Self-Attention Relation Distillation for Compressing Pretrained Transformers[J]. arXiv preprint arXiv:2012.15828v2, 2021.
2.Hou L, Huang Z, Shang L, Jiang X, Chen X and Liu Q. DynaBERT: Dynamic BERT with Adaptive Width and Depth[J]. arXiv preprint arXiv:2004.04037, 2020.
3.Cai H, Gan C, Wang T, Zhang Z, and Han S. Once for all: Train one network and specialize it for efficient deployment[J]. arXiv preprint arXiv:1908.09791, 2020.
4.Wu H, Judd P, Zhang X, Isaev M and Micikevicius P. Integer Quantization for Deep Learning Inference: Principles and Empirical Evaluation[J]. arXiv preprint arXiv:2004.09602v1, 2020.
