ERNIE 3.0 轻量级模型
目录
模型介绍
本次开源的模型是在文心大模型ERNIE 3.0 基础上通过在线蒸馏技术 得到的轻量级模型,模型结构与 ERNIE 2.0 保持一致,相比 ERNIE 2.0 具有更强的中文效果。
在线蒸馏技术
在线蒸馏技术在模型学习的过程中周期性地将知识信号传递给若干个学生模型同时训练,从而在蒸馏阶段一次性产出多种尺寸的学生模型。相对传统蒸馏技术,该技术极大节省了因大模型额外蒸馏计算以及多个学生的重复知识传递带来的算力消耗。
这种新颖的蒸馏方式利用了文心大模型的规模优势,在蒸馏完成后保证了学生模型的效果和尺寸丰富性,方便不同性能需求的应用场景使用。此外,由于文心大模型的模型尺寸与学生模型差距巨大,模型蒸馏难度极大甚至容易失效。为此,通过引入了助教模型进行蒸馏的技术,利用助教作为知识传递的桥梁以缩短学生模型和大模型表达空间相距过大的问题,从而促进蒸馏效率的提升。
更多技术细节可以参考论文:
image
模型效果
本项目开源 ERNIE 3.0 Base 、ERNIE 3.0 Medium 、 ERNIE 3.0 Mini 、 ERNIE 3.0 Micro 、 ERNIE 3.0 Nano 五个模型:
ERNIE 3.0-Base (12-layer, 768-hidden, 12-heads )
ERNIE 3.0-Medium (6-layer, 768-hidden, 12-heads )
ERNIE 3.0-Mini (6-layer, 384-hidden, 12-heads )
ERNIE 3.0-Micro (4-layer, 384-hidden, 12-heads )
ERNIE 3.0-Nano (4-layer, 312-hidden, 12-heads )
下面是 PaddleNLP 中轻量级中文模型的效果-时延图 。横坐标表示在 IFLYTEK 数据集 (最大序列长度设置为 128) 上测试的延迟(latency,单位:ms),纵坐标是 CLUE 10 个任务上的平均精度(包含文本分类、文本匹配、自然语言推理、代词消歧、阅读理解等任务),其中 CMRC2018 阅读理解任务的评价指标是 Exact Match(EM),其他任务的评价指标均是 Accuracy。图中越靠左上 的模型,精度和性能水平越高。
图中模型名下方标注了模型的参数量,测试环境见
性能测试 。
batch_size=32 时,CPU 下的效果-时延图(线程数 1 和 8):
batch_size=1 时,CPU 下的效果-时延图(线程数 1 和 8):
batch_size=32 和 1,预测精度为 FP16 时,GPU 下的效果-时延图:
从图上可看出,ERNIE 3.0 系列轻量级模型在精度和性能上的综合表现已全面领先于 UER-py、Huawei-Noah 以及 HFL 的中文模型。且当 batch_size=1、预测精度为 FP16 时,在 GPU 上宽且浅的模型的推理性能更有优势。
在 CLUE 验证集 上评测指标如下表所示:
Arch
Model
AVG
AFQMC
TNEWS
IFLYTEK
CMNLI
OCNLI
CLUEWSC2020
CSL
CMRC2018
CHID
C3
24L1024H
ERNIE 2.0-Large-zh
77.03
76.41
59.67
62.29
83.82
79.69
89.14
84.10
71.48/90.35
85.52
78.12
RoBERTa-wwm-ext-large
76.61
76.00
59.33
62.02
83.88
78.81
90.79
83.67
70.58/89.82
85.72
75.26
20L1024H
ERNIE 3.0-Xbase-zh
78.71
76.85
59.89
62.41
84.76
82.51
89.80
84.47
75.49/92.67
86.36
84.59
12L768H
ERNIE 3.0-Base-zh
76.05
75.93
58.26
61.56
83.02
80.10
86.18
82.63
70.71/90.41
84.26
77.88
ERNIE-Gram-zh
75.72
75.28
57.88
60.87
82.90
79.08
88.82
82.83
71.82/90.38
84.04
73.69
ERNIE 2.0-Base-zh
74.95
76.25
58.53
61.72
83.07
78.81
84.21
82.77
68.22/88.71
82.78
73.19
Langboat/Mengzi-BERT-Base
74.69
75.35
57.76
61.64
82.41
77.93
88.16
82.20
67.04/88.35
83.74
70.70
ERNIE 1.0-Base-zh
74.17
74.84
58.91
62.25
81.68
76.58
85.20
82.77
67.32/87.83
82.47
69.68
RoBERTa-wwm-ext
74.11
74.60
58.08
61.23
81.11
76.92
88.49
80.77
68.39/88.50
83.43
68.03
BERT-Base-Chinese
72.57
74.63
57.13
61.29
80.97
75.22
81.91
81.90
65.30/86.53
82.01
65.38
UER/Chinese-RoBERTa-Base
71.78
72.89
57.62
61.14
80.01
75.56
81.58
80.80
63.87/84.95
81.52
62.76
8L512H
UER/Chinese-RoBERTa-Medium
67.06
70.64
56.10
58.29
77.35
71.90
68.09
78.63
57.63/78.91
75.13
56.84
6L768H
ERNIE 3.0-Medium-zh
72.49
73.37
57.00
60.67
80.64
76.88
79.28
81.60
65.83/87.30
79.91
69.73
HLF/RBT6, Chinese
70.06
73.45
56.82
59.64
79.36
73.32
76.64
80.67
62.72/84.77
78.17
59.85
TinyBERT6 , Chinese
69.62
72.22
55.70
54.48
79.12
74.07
77.63
80.17
63.03/83.75
77.64
62.11
RoFormerV2 Small
68.52
72.47
56.53
60.72
76.37
72.95
75.00
81.07
62.97/83.64
67.66
59.41
UER/Chinese-RoBERTa-L6-H768
67.09
70.13
56.54
60.48
77.49
72.00
72.04
77.33
53.74/75.52
76.73
54.40
6L384H
ERNIE 3.0-Mini-zh
66.90
71.85
55.24
54.48
77.19
73.08
71.05
79.30
58.53/81.97
69.71
58.60
4L768H
HFL/RBT4, Chinese
67.42
72.41
56.50
58.95
77.34
70.78
71.05
78.23
59.30/81.93
73.18
56.45
4L512H
UER/Chinese-RoBERTa-Small
63.25
69.21
55.41
57.552
73.64
69.80
66.78
74.83
46.75/69.69
67.59
50.92
4L384H
ERNIE 3.0-Micro-zh
64.21
71.15
55.05
53.83
74.81
70.41
69.08
76.50
53.77/77.82
62.26
55.53
4L312H
ERNIE 3.0-Nano-zh
62.97
70.51
54.57
48.36
74.97
70.61
68.75
75.93
52.00/76.35
58.91
55.11
TinyBERT4 , Chinese
60.82
69.07
54.02
39.71
73.94
69.59
70.07
75.07
46.04/69.34
58.53
52.18
4L256H
UER/Chinese-RoBERTa-Mini
53.40
69.32
54.22
41.63
69.40
67.36
65.13
70.07
5.96/17.13
51.19
39.68
3L1024H
HFL/RBTL3, Chinese
66.63
71.11
56.14
59.56
76.41
71.29
69.74
76.93
58.50/80.90
71.03
55.56
3L768H
HFL/RBT3, Chinese
65.72
70.95
55.53
59.18
76.20
70.71
67.11
76.63
55.73/78.63
70.26
54.93
2L128H
UER/Chinese-RoBERTa-Tiny
44.45
69.02
51.47
20.28
59.95
57.73
63.82
67.43
3.08/14.33
23.57
28.12
以下是本项目目录结构及说明:
1 .
2 ├── run_seq_cls.py # 分类任务的微调脚本
3 ├── run_token_cls.py # 序列标注任务的微调脚本
4 ├── run_qa.py # 阅读理解任务的微调脚本
5 ├── compress_seq_cls.py # 分类任务的压缩脚本
6 ├── compress_token_cls.py # 序列标注任务的压缩脚本
7 ├── compress_qa.py # 阅读理解任务的压缩脚本
8 ├── config.yml # 压缩配置文件
9 ├── infer.py # 支持 CLUE 分类、CLUE CMRC2018、MSRA_NER 任务的预测脚本
10 ├── deploy # 部署目录
11 │ └── python
12 │ └── ernie_predictor.py
13 │ └── infer_cpu.py
14 │ └── infer_gpu.py
15 │ └── README.md
16 │ └── serving
17 │ └── seq_cls_rpc_client.py
18 │ └── seq_cls_service.py
19 │ └── seq_cls_config.yml
20 │ └── token_cls_rpc_client.py
21 │ └── token_cls_service.py
22 │ └── token_cls_config.yml
23 │ └── README.md
24 │ └── paddle2onnx
25 │ └── ernie_predictor.py
26 │ └── infer.py
27 │ └── README.md
28 └── README.md # 文档,本文件
29
微调
ERNIE 3.0 发布的预训练模型还不能直接在下游任务上直接使用,需要使用具体任务上的数据对预训练模型进行微调。
使用 PaddleNLP 只需要一行代码可以拿到 ERNIE 3.0 系列模型,之后可以在自己的下游数据下进行微调,从而获得具体任务上效果更好的模型。
1
2 from paddlenlp . transformers import *
3
4 tokenizer = AutoTokenizer . from_pretrained ( "ernie-3.0-medium-zh" )
5
6 # 用于分类任务
7 seq_cls_model = AutoModelForSequenceClassification . from_pretrained ( "ernie-3.0-medium-zh" )
8
9 # 用于序列标注任务
10 token_cls_model = AutoModelForTokenClassification . from_pretrained ( "ernie-3.0-medium-zh" )
11
12 # 用于阅读理解任务
13 qa_model = AutoModelForQuestionAnswering . from_pretrained ( "ernie-3.0-medium-zh" )
14
本项目提供了针对分类(包含文本分类、文本匹配、自然语言推理、代词消歧等任务)、序列标注、阅读理解三大场景下微调的示例脚本,可分别参考 run_seq_cls.py 、run_token_cls.py、run_qa.py 三个脚本,启动方式如下:
1 # 分类任务
2 python run_seq_cls.py --task_name tnews --model_name_or_path ernie-3.0-medium-zh --do_train
3
4 # 序列标注任务
5 python run_token_cls.py --task_name msra_ner --model_name_or_path ernie-3.0-medium-zh --do_train
6
7 # 阅读理解任务
8 python run_qa.py --model_name_or_path ernie-3.0-medium-zh --do_train
9
模型压缩
尽管 ERNIE 3.0 已提供了效果不错的 6 层、4 层轻量级模型可以微调后直接使用,但如果有模型部署上线的需求,则需要进一步压缩模型体积,可以使用这里提供的一套模型压缩方案及 API 对上一步微调后的模型进行压缩。
环境依赖
使用裁剪功能需要安装 paddleslim 包
模型压缩 API 使用
本项目基于 PaddleNLP 的 Trainer API 发布提供了模型压缩 API。压缩 API 支持用户对 ERNIE、BERT 等 Transformers 类下游任务微调模型进行裁剪、量化。用户只需要简单地调用 compress() 即可一键启动裁剪和量化,并自动保存压缩后的模型。
可以这样使用压缩 API (示例代码只提供了核心调用,如需跑通完整的例子可参考下方完整样例脚本):
1
2 trainer = Trainer (
3 model = model ,
4 args = training_args ,
5 data_collator = data_collator ,
6 train_dataset = train_dataset ,
7 eval_dataset = eval_dataset ,
8 tokenizer = tokenizer )
9
10 output_dir = os . path . join ( model_args . model_name_or_path , "compress" )
11
12 compress_config = CompressConfig ( quantization_config = PTQConfig (
13 algo_list = [ 'hist' , 'mse' ] , batch_size_list = [ 4 , 8 , 16 ] ) ,
14 DynabertConfig ( width_mul_ist = [ 3 / 4 ] ) )
15
16 trainer . compress (
17 output_dir ,
18 pruning = True , # 开启裁剪
19 quantization = True , # 开启量化
20 compress_config = compress_config )
由于压缩 API 基于 Trainer,所以首先需要初始化一个 Trainer 实例,对于模型压缩来说必要传入的参数如下:
model:ERNIE、BERT 等模型,是在下游任务中微调后的模型。以分类模型为例,可通过AutoModelForSequenceClassification.from_pretrained(model_name_or_path) 来获取
data_collator:三类任务均可使用 PaddleNLP 预定义好的DataCollator 类 ,data_collator 可对数据进行 Pad 等操作。使用方法参考本项目中代码即可
train_dataset:裁剪训练需要使用的训练集
eval_dataset:裁剪训练使用的评估集,也是量化使用的校准数据
tokenizer:模型model对应的 tokenizer,可使用 AutoTokenizer.from_pretrained(model_name_or_path) 来获取
然后可以直接调用 compress 启动压缩,其中 compress 的参数释义如下:
output_dir:裁剪、量化后的模型保存目录
pruning:是否裁剪,默认为True
quantization:是否量化,默认为 True
compress_config:压缩配置,需要分别传入裁剪和量化的配置实例。目前裁剪和量化分别仅支持DynabertConfig和PTQConfig类。当默认参数不满足需求时,可通过传入参数对压缩过程进行特殊配置:
其中,DynabertConfig中可以传的参数有:
width_mult_list:裁剪宽度保留的比例list,对 6 层模型推荐 3/4 ,对 12 层模型推荐 2/3,表示对 q、k、v 以及 ffn 权重宽度的保留比例。默认是 [3/4]
output_filename_prefix:裁剪导出模型的文件名前缀,默认是"float32"
PTQConfig中可以传的参数有:
algo_list:量化策略列表,目前支持 KL, abs_max, min_max, avg, hist和mse,不同的策略计算量化比例因子的方法不同。建议传入多种策略,可批量得到由多种策略产出的多个量化模型,从中选择最优模型。推荐hist, mse, KL,默认是["hist"]
batch_size_list:校准样本数,默认是 [4]。并非越大越好,也是一个超参数,建议传入多种校准样本数,可从多个量化模型中选择最优模型。
input_dir:待量化模型的目录。如果是 None,当不启用裁剪时,表示待量化的模型是 Trainer 初始化的模型;当启用裁剪时,表示待量化的模型是裁剪后导出的模型。默认是None
input_filename_prefix:待量化模型文件名前缀,默认是 "float32"
output_filename_prefix:导出的量化模型文件名后缀,默认是"int8"
本项目还提供了压缩 API 在分类(包含文本分类、文本匹配、自然语言推理、代词消歧等任务)、序列标注、阅读理解三大场景下的使用样例,可以分别参考 compress_seq_cls.py 、compress_token_cls.py、compress_qa.py,启动方式如下:
1 # --model_name_or_path 参数传入的是上面微调过程后得到的模型所在目录,压缩后的模型也会在该目录下
2 # 分类任务
3 python compress_seq_cls.py --dataset "clue tnews" --model_name_or_path best_models/TNEWS --output_dir ./
4
5 # 序列标注任务
6 python compress_token_cls.py --dataset "msra_ner" --model_name_or_path best_models/MSRA_NER --output_dir ./
7
8 # 阅读理解任务
9 python compress_seq_cls.py --dataset "clue cmrc2018" --model_name_or_path best_models/CMRC2018 --output_dir ./
一行代码验证上面模型压缩后模型的精度:
1 # 原模型
2 python infer.py --task_name tnews --model_path best_models/TNEWS/compress/inference/infer --use_trt
3 # 裁剪后
4 python infer.py --task_name tnews --model_path best_models/TNEWS/compress/0.75/float --use_trt
5 # 量化后
6 python infer.py --task_name tnews --model_path best_models/TNEWS/compress/0.75/hist16/int8 --use_trt --precision int8
7
其中 --model_path 参数需要传入静态图模型的路径和前缀名。
压缩 API 使用 TIPS:
模型压缩主要用于加速推理部署,因此压缩后的模型都是静态图模型,不能再通过 from_pretrained() API 导入继续训练。
压缩 API compress() 默认会启动裁剪和量化,但用户也可以通过在 compress() 中设置 pruning=False 或者 quantization=False 来关掉裁剪或者量化过程。目前裁剪策略有额外的训练的过程,需要下游任务的数据,其训练时间视下游任务数据量而定,且和微调的训练时间是一个量级。量化则不需要额外的训练,更快,量化的加速比比裁剪更明显,但是单独量化精度下降可能也更多;
裁剪类似蒸馏过程,方便起见,可以直接使用微调时的超参。如果想要进一步提升精度,可以对 batch_size、learning_rate、epoch 等超参进行 Grid Search;
压缩效果
精度测试
本案例中我们对 ERNIE 3.0-Medium 模型在三类任务上微调后的模型使用压缩 API 进行压缩。压缩后精度如下:
Model AVG AFQMC TNEWS IFLYTEK CMNLI OCNLI CLUEWSC2020 CSL CMRC2018 MSRA_NER ERNIE 3.0-Medium 74.87 75.35 57.45 60.18 81.16 77.19 80.59 81.93 66.95/87.15 92.65/93.43/93.04 ERNIE 3.0-Medium+FP16 74.87 75.32 57.45 60.22 81.16 77.22 80.59 81.90 66.95/87.16 92.65/93.45/93.05 ERNIE 3.0-Medium+裁剪+FP32 74.70 75.14 57.31 60.29 81.25 77.46 79.93 81.70 65.92/86.43 93.10/93.43/93.27 ERNIE 3.0-Medium+裁剪+FP16 74.71 75.21 57.27 60.29 81.24 77.56 79.93 81.73 65.89/86.44 93.10/93.43/93.27 ERNIE 3.0-Medium+裁剪+量化+INT8 74.44 75.02 57.26 60.37 81.03 77.25 77.96 81.67 66.17/86.55 93.17/93.23/93.20 ERNIE 3.0-Medium+量化+INT8 74.10 74.67 56.99 59.91 81.03 75.05 78.62 81.60 66.32/86.82 93.10/92.90/92.70
评价指标说明: 其中 CLUE 分类任务(AFQMC 语义相似度、TNEWS 文本分类、IFLYTEK 长文本分类、CMNLI 自然语言推理、OCNLI 自然语言推理、CLUEWSC2020 代词消歧、CSL 论文关键词识别)的评价指标是 Accuracy,阅读理解任务 CLUE CMRC2018 的评价指标是 EM (Exact Match) / F1-Score,计算平均值时取 EM,序列标注任务 MSRA_NER 的评价指标是 Precision/Recall/F1-Score,计算平均值时取 F1-Score。
由表可知,ERNIE 3.0-Medium 模型经过裁剪和量化后,精度平均下降 0.46,其中裁剪后下降了 0.17,单独量化精度平均下降 0.77。
性能测试
性能测试的配置如下:
数据集:TNEWS(文本分类)、MSRA_NER(序列标注)、CLUE CMRC2018(阅读理解)
计算卡:T4、CUDA11.2、CuDNN8.2
CPU 信息:Intel(R) Xeon(R) Gold 6271C CPU
PaddlePaddle 版本:2.3
PaddleNLP 版本:2.3
性能数据单位是 QPS。QPS 测试方法:固定 batch size 为 32,测试运行时间 total_time,计算 QPS = total_samples / total_time
精度数据单位:文本分类是 Accuracy,序列标注是 F1-Score,阅读理解是 EM (Exact Match)
CPU 性能
测试环境及说明如上,测试 CPU 性能时,线程数设置为12。
TNEWS 性能 TNEWS 精度 MSRA_NER 性能 MSRA_NER 精度 CMRC2018 性能 CMRC2018 精度 ERNIE 3.0-Medium+FP32 311.95(1.0X) 57.45 90.91(1.0x) 93.04 33.74(1.0x) 66.95 ERNIE 3.0-Medium+INT8 600.35(1.9x) 56.57(-0.88) 141.00(1.6x) 92.64(-0.40) 56.51(1.7x) 66.23(-0.72) ERNIE 3.0-Medium+裁剪+FP32 408.65(1.3x) 57.31(-0.14) 122.13(1.3x) 93.27(+0.23) 48.47(1.4x) 65.55(-1.40) ERNIE 3.0-Medium+裁剪+INT8 704.42(2.3x) 56.69(-0.76) 215.58(2.4x) 92.39(-0.65) 75.23(2.2x) 63.47(-3.48)
三类任务(分类、序列标注、阅读理解)经过相同压缩过程后,加速比达到 2.3 左右。
GPU 性能
TNEWS 性能 TNEWS 精度 MSRA_NER 性能 MSRA_NER 精度 CMRC2018 性能 CMRC2018 精度 ERNIE 3.0-Medium+FP32 1123.85(1.0x) 57.45 366.75(1.0x) 93.04 146.84(1.0x) 66.95 ERNIE 3.0-Medium+FP16 2672.41(2.4x) 57.45(0.00) 840.11(2.3x) 93.05(0.01) 303.43(2.1x) 66.95(0.00) ERNIE 3.0-Medium+INT8 3226.26(2.9x) 56.99(-0.46) 889.33(2.4x) 92.70(-0.34) 348.84(2.4x) 66.32(-0.63 ERNIE 3.0-Medium+裁剪+FP32 1424.01(1.3x) 57.31(-0.14) 454.27(1.2x) 93.27(+0.23) 183.77(1.3x) 65.92(-1.03) ERNIE 3.0-Medium+裁剪+FP16 3577.62(3.2x) 57.27(-0.18) 1138.77(3.1x) 93.27(+0.23) 445.71(3.0x) 65.89(-1.06) ERNIE 3.0-Medium+裁剪+INT8 3635.48(3.2x) 57.26(-0.19) 1105.26(3.0x) 93.20(+0.16) 444.27(3.0x) 66.17(-0.78)
三类任务(分类、序列标注、阅读理解)经过裁剪 + 量化后加速比均达到 3 倍左右,所有任务上平均精度损失可控制在 0.5 以内(0.46)。
使用 FasterTokenizer 加速
FasterTokenizer 是飞桨提供的速度领先的文本处理算子库,集成了 Google 于 2021 年底发布的 LinMaxMatch 算法,该算法引入 Aho-Corasick 将 WordPiece 的时间复杂度从 O(N2 ) 优化到 O(N),已在 Google 搜索业务中大规模上线。FasterTokenizer 速度显著领先,且呈现 batch_size 越大,优势越突出。例如,设置 batch_size = 64 时,FasterTokenizer 切词速度比 HuggingFace 快 28 倍。
在 ERNIE 3.0 轻量级模型裁剪、量化基础上,当设置切词线程数为 4 时,使用 FasterTokenizer 在 NVIDIA Tesla T4 环境下在 IFLYTEK (长文本分类数据集,最大序列长度为 128)数据集上性能提升了 2.39 倍,相比 BERT-Base 性能提升了 7.09 倍,在 Intel(R) Xeon(R) Gold 6271C CPU @ 2.60GHz、线程数为 8 的情况下性能提升了 1.27 倍,相比 BERT-Base 性能提升了 5.13 倍。加速效果如下图所示:
使用 FasterTokenizer 的方式非常简单,在安装 faster_tokenizer 包之后,仅需在 tokenizer 实例化时直接传入 use_faster=True 即可。目前已在 Linux 系统下支持 BERT、ERNIE、TinyBERT 等模型。
安装 faster_tokenizer 包的命令:
pip install faster_tokenizer
如需设置切词线程数,需要运行前先设置环境变量 OMP_NUM_THREADS :
1 # 设置切词线程数为 4
2 export OMP_NUM_THREADS = 4
调用 from_pretrained 时只需轻松传入一个参数 use_faster=True:
1 from paddlenlp . transformers import AutoTokenizer
2 AutoTokenizer . from_pretrained ( "ernie-3.0-medium-zh" , use_faster = True )
部署
我们为 ERNIE 3.0 提供了多种部署方案,可以满足不同场景下的部署需求,请根据实际情况进行选择。
image
Python 部署
服务化部署
Paddle2ONNX 部署
ONNX 导出及 ONNXRuntime 部署请参考:
ONNX导出及ONNXRuntime部署指南
Paddle Lite 移动端部署
即将支持,敬请期待
Notebook教程
参考文献
Sun Y, Wang S, Feng S, et al. ERNIE 3.0: Large-scale Knowledge Enhanced Pre-training for Language Understanding and Generation[J]. arXiv preprint arXiv:2107.02137, 2021.
Su W, Chen X, Feng S, et al. ERNIE-Tiny: A Progressive Distillation Framework for Pretrained Transformer Compression[J]. arXiv preprint arXiv:2106.02241, 2021.
Wang S, Sun Y, Xiang Y, et al. ERNIE 3.0 Titan: Exploring Larger-scale Knowledge Enhanced Pre-training for Language Understanding and Generation[J]. arXiv preprint arXiv:2112.12731, 2021.