compression.md 23.7 KB
Newer Older
yuguo-Jack's avatar
yuguo-Jack committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
# PaddleNLP 模型压缩 API

 **目录**
   * [模型压缩 API 功能简介](#模型压缩API功简介)
   * [三大场景快速启动模型压缩示例](#三大场景快速启动模型压缩示例)
   * [四步启动模型压缩](#四步启动模型压缩)
       * [Step1:获取模型压缩参数 compression_args](#获取模型压缩参数compression_args)
       * [Step2:实例化 Trainer 并调用 compress()](#实例化Trainer并调用compress())
           * [Trainer 实例化参数介绍](#Trainer实例化参数介绍)
       * [Step3:实现自定义评估函数(按需可选)](#实现自定义评估函数(按需可选))
       * [Step4:传参并运行压缩脚本](#传参并运行压缩脚本)
           * [CompressionArguments 参数介绍](#CompressionArguments参数介绍)
   * [模型评估与部署](#模型评估与部署)
   * [FAQ](#FAQ)
   * [参考文献](#References)


<a name="模型压缩API功能简介"></a>

## 模型压缩 API 功能简介

PaddleNLP 模型压缩 API 功能支持对 ERNIE 类下游任务上微调后的模型进行裁剪、量化,以缩小模型体积、减少内存占用、减少计算、提升推理速度从而减少部署难度。模型压缩 API 效果好,且简洁易用。目前裁剪功能现在支持 DynaBERT 中的宽度自适应裁剪策略;量化现在支持静态离线量化方法(PTQ)、量化训练(QAT)和 Embedding 量化。PTQ 无需训练,只需少量校准数据,即可导出量化模型,QAT 类似 FP32 模型的训练过程,也基本能够做到精度无损,Embedding 量化过程较为简单,不需要训练也不需要校准数据即可完成。

- **效果好**:目前已经在分类(包含文本分类、文本匹配、自然语言推理、代词消歧、阅读理解等任务)、序列标注、抽取式阅读理解任务上进行过验证,基本达到精度无损。例如,对于 12L768H 和 6L768H 结构的模型,进行宽度保留比例为 2/3 的裁剪基本可以达到精度无损,模型裁剪后推理速度能够达到原先的 1-2 倍;6L768H 结构的模型量化后推理速度能够达到量化前的 2-3 倍。

- **简洁易用**:只需要简单几步即可开展模型压缩任务

##### ERNIE 3.0 压缩效果
如下表所示,ERNIE 3.0-Medium (6-layer, 384-hidden, 12-heads) 模型在三类任务(文本分类、序列标注、抽取式阅读理解)经过裁剪 + 量化后加速比均达到 3 倍左右,所有任务上平均精度损失可控制在 0.5 以内(0.46)。

|                            | 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+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+裁剪+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)  |

(以上数据来自 [ERNIE 3.0 性能测试文档](../model_zoo/ernie-3.0/#性能测试),文档包含测试环境介绍)

##### UIE 压缩效果

以报销工单信息抽取任务为例,使用 `uie-base` 进行微调,先得到原始 FP32 模型,然后使用 QAT 策略进一步量化。量化后的模型比原始 FP32 模型的 F1 值高 2.19。

| Models         | F1           |
| -------------  |:------------:|
| uie-base+微调+FP32   | 91.93        |
| uie-base+微调+量化+INT8 | 94.12        |


<a name="三大场景快速启动模型压缩示例"></a>

### 三大场景快速启动模型压缩示例

本项目提供了压缩 API 在分类(包含文本分类、文本匹配、自然语言推理、代词消歧等任务)、序列标注、抽取式阅读理解三大场景下的使用样例,可以分别参考 [ERNIE 3.0](../model_zoo/ernie-3.0/) 目录下的 [compress_seq_cls.py](../model_zoo/ernie-3.0/compress_seq_cls.py)[compress_token_cls.py](../model_zoo/ernie-3.0/compress_token_cls.py)[compress_qa.py](../model_zoo/ernie-3.0/compress_qa.py) 脚本,启动方式如下:

```shell
# 分类任务
# 该脚本共支持 CLUE 中 7 个分类任务,超参不全相同,因此分类任务中的超参配置利用 config.yml 配置
python compress_seq_cls.py \
    --dataset "clue tnews"  \
    --model_name_or_path best_models/TNEWS  \
    --output_dir ./

# 序列标注任务
python compress_token_cls.py \
    --dataset "msra_ner"  \
    --model_name_or_path best_models/MSRA_NER \
    --output_dir ./ \
    --max_seq_length 128 \
    --per_device_train_batch_size 32 \
    --per_device_eval_batch_size 32 \
    --learning_rate 0.00005 \
    --remove_unused_columns False \
    --num_train_epochs 3

# 阅读理解任务
python compress_qa.py \
    --dataset "clue cmrc2018" \
    --model_name_or_path best_models/CMRC2018  \
    --output_dir ./ \
    --max_seq_length 512 \
    --learning_rate 0.00003 \
    --num_train_epochs 8 \
    --per_device_train_batch_size 24 \
    --per_device_eval_batch_size 24 \
    --max_answer_length 50 \

```

示例代码中压缩使用的是 datasets 内置的数据集,若想要使用自定义数据集压缩,可参考 [datasets 加载自定义数据集文档](https://huggingface.co/docs/datasets/loading)


<a name="四步启动模型压缩"></a>

## 四步启动模型压缩

### 环境依赖

- paddlepaddle-gpu >=2.4.1
- paddlenlp >= 2.5
- paddleslim >= 2.4.0

模型压缩 API 中的压缩功能依赖最新的 `paddleslim` 包。可运行以下命令安装:

```shell
pip install paddleslim -i https://pypi.tuna.tsinghua.edu.cn/simple
```

模型压缩 API 的使用大致分为四步:

- Step 1: 使用 `PdArgumentParser` 解析从命令行传入的超参数,以获取压缩参数 `compression_args`
- Step 2: 实例化 Trainer 并调用 `compress()` 压缩 API
- Step 3: 实现自定义评估函数和 loss 计算函数(按需可选),以适配自定义压缩任务
- Step 4:传参并运行压缩脚本

**示例代码**

```python
from paddlenlp.trainer import PdArgumentParser, CompressionArguments

# Step1: 使用 `PdArgumentParser` 解析从命令行传入的超参数,以获取压缩参数 `compression_args`;
parser = PdArgumentParser(CompressionArguments)
compression_args = parser.parse_args_into_dataclasses()

# Step2: 实例化 Trainer 并调用 compress()
trainer = Trainer(
    model=model,
    args=compression_args,
    data_collator=data_collator,
    train_dataset=train_dataset,
    eval_dataset=eval_dataset,
    criterion=criterion)

# Step 3: 使用内置模型和评估方法,则不需要实现自定义评估函数和 loss 计算函数
trainer.compress()
```

```shell
# Step4: 传参并运行压缩脚本
python compress.py \
    --output_dir ./compress_models  \
    --per_device_train_batch_size 32 \
    --per_device_eval_batch_size 32 \
    --num_train_epochs 4 \
    --width_mult_list 0.75 \
    --batch_size_list 4 8 16 \
    --batch_num_list 1 \

```


<a name="获取模型压缩参数compression_args"></a>

### Step 1:获取模型压缩参数 compression_args

使用 `PdArgumentParser` 对象解析从命令行得到的超参数,从而得到 `compression_args`,并将 `compression_args` 传给 `Trainer` 对象。获取 `compression_args` 的方法通常如下:

```python
from paddlenlp.trainer import PdArgumentParser, CompressionArguments

# Step1: 使用 `PdArgumentParser` 解析从命令行传入的超参数,以获取压缩参数 `compression_args`;
parser = PdArgumentParser(CompressionArguments)
compression_args = parser.parse_args_into_dataclasses()
```

<a name="实例化Trainer并调用compress()"></a>

### Step 2:实例化 Trainer 并调用 compress

<a name="Trainer实例化参数介绍"></a>

#### Trainer 实例化参数介绍

- **--model** 待压缩的模型,目前支持 ERNIE、BERT、RoBERTa、ERNIE-M、ELECTRA、ERNIE-Gram、PP-MiniLM、TinyBERT 等结构相似的模型,是在下游任务中微调后的模型,当预训练模型选择 ERNIE 时,需要继承 `ErniePretrainedModel`。以分类任务为例,可通过`AutoModelForSequenceClassification.from_pretrained(model_name_or_path)` 等方式来获取,这种情况下,`model_name_or_path`目录下需要有 model_config.json, model_state.pdparams 文件;
- **--data_collator** 三类任务均可使用 PaddleNLP 预定义好的 [DataCollator 类](../paddlenlp/data/data_collator.py)`data_collator` 可对数据进行 `Pad` 等操作。使用方法参考 [示例代码](../model_zoo/ernie-3.0/compress_seq_cls.py) 即可;
- **--train_dataset** 裁剪训练需要使用的训练集,是任务相关的数据。自定义数据集的加载可参考 [文档](https://huggingface.co/docs/datasets/loading)。不启动裁剪时,可以为 None;
- **--eval_dataset** 裁剪训练使用的评估集,也是量化使用的校准数据,是任务相关的数据。自定义数据集的加载可参考 [文档](https://huggingface.co/docs/datasets/loading)。是 Trainer 的必选参数;
- **--tokenizer** 模型 `model` 对应的 `tokenizer`,可使用 `AutoTokenizer.from_pretrained(model_name_or_path)` 来获取。
- **--criterion** 模型的 loss 计算方法,可以是一个 nn.Layer 对象,也可以是一个函数,用于在 ofa_utils.py 计算模型的 loss 用于计算梯度从而确定神经元重要程度。

其中,`criterion` 函数定义示例:

```python
# 支持的形式一:
def criterion(logits, labels):
    loss_fct = paddle.nn.BCELoss()
    start_ids, end_ids = labels
    start_prob, end_prob = outputs
    start_ids = paddle.cast(start_ids, 'float32')
    end_ids = paddle.cast(end_ids, 'float32')
    loss_start = loss_fct(start_prob, start_ids)
    loss_end = loss_fct(end_prob, end_ids)
    loss = (loss_start + loss_end) / 2.0
    return loss

# 支持的形式二:
class CrossEntropyLossForSQuAD(paddle.nn.Layer):

    def __init__(self):
        super(CrossEntropyLossForSQuAD, self).__init__()

    def forward(self, y, label):
        start_logits, end_logits = y
        start_position, end_position = label
        start_position = paddle.unsqueeze(start_position, axis=-1)
        end_position = paddle.unsqueeze(end_position, axis=-1)
        start_loss = paddle.nn.functional.cross_entropy(input=start_logits,
                                                        label=start_position)
        end_loss = paddle.nn.functional.cross_entropy(input=end_logits,
                                                      label=end_position)
        loss = (start_loss + end_loss) / 2
        return loss
```

用以上参数实例化 Trainer 对象,之后直接调用 `compress()``compress()` 会根据选择的策略进入不同的分支,以进行裁剪或者量化的过程。

**示例代码**

```python
from paddlenlp.trainer import PdArgumentParser, CompressionArguments

# Step1: 使用 `PdArgumentParser` 解析从命令行传入的超参数,以获取压缩参数 `compression_args`;
parser = PdArgumentParser(CompressionArguments)
compression_args = parser.parse_args_into_dataclasses()

# Step2: 实例化 Trainer 并调用 compress()
trainer = Trainer(
    model=model,
    args=compression_args,
    data_collator=data_collator,
    train_dataset=train_dataset,
    eval_dataset=eval_dataset,
    criterion=criterion)

trainer.compress()
```

<a name="实现自定义评估函数(按需可选)"></a>

### Step3:实现自定义评估函数,以适配自定义压缩任务

当使用 DynaBERT 裁剪功能时,如果模型、Metrics 不符合下表的情况,那么模型压缩 API 中评估函数需要自定义。

目前 DynaBERT 裁剪功能只支持 SequenceClassification 等三类 PaddleNLP 内置 class,并且内置评估器对应为 Accuracy、F1、Squad。

| Model class name |  SequenceClassification   | TokenClassification   | QuestionAnswering |
| ---------------- | ------------------------- | --------------------- | ----------------- |
|      Metrics     |          Accuracy         |           F1          |        Squad      |

需要注意以下三个条件:

- 如果模型是自定义模型,需要继承 `XXXPretrainedModel`,例如当预训练模型选择 ERNIE 时,继承 `ErniePretrainedModel`,模型需要支持调用 `from_pretrained()` 导入模型,且只含 `pretrained_model_name_or_path` 一个必选参数,`forward` 函数返回 `logits` 或者 `tuple of logits`

- 如果模型是自定义模型,或者数据集比较特殊,压缩 API 中 loss 的计算不符合使用要求,需要自定义 `custom_evaluate` 评估函数,需要同时支持 `paddleslim.nas.ofa.OFA` 模型和 `paddle.nn.layer` 模型。可参考下方示例代码。
    - 输入`model``dataloader`,返回模型的评价指标(单个 float 值)。
    - 将该函数传入 `compress()` 中的 `custom_evaluate` 参数;

`custom_evaluate()` 函数定义示例:

```python
    import paddle
    from paddle.metric import Accuracy

    @paddle.no_grad()
    def evaluate_seq_cls(self, model, data_loader):
        metric = Accuracy()
        model.eval()
        metric.reset()
        for batch in data_loader:
            logits = model(input_ids=batch['input_ids'],
                           token_type_ids=batch['token_type_ids'])
            # Supports paddleslim.nas.ofa.OFA model and nn.layer model.
            if isinstance(model, paddleslim.nas.ofa.OFA):
                logits = logits[0]
            correct = metric.compute(logits, batch['labels'])
            metric.update(correct)
        res = metric.accumulate()
        logger.info("acc: %s, " % res)
        model.train()
        return res
```


在调用 `compress()` 时传入这个自定义函数:

```python
trainer.compress(custom_evaluate=evaluate_seq_cls)
```


<a name="传参并运行压缩脚本"></a>

### Step 4:传参并运行压缩脚本

这一步主要是将压缩需要用到的参数通过命令行传入,并启动压缩脚本。

压缩启动命令:

**示例代码**

```shell
# Step4: 运行压缩脚本
python compress.py \
    --output_dir ./compress_models  \
    --per_device_train_batch_size 32 \
    --per_device_eval_batch_size 32 \
    --num_train_epochs 4 \
    --width_mult_list 0.75 \
    --batch_size_list 4 8 16 \
    --batch_num_list 1 \

```

下面会介绍模型压缩启动命令可以传递的超参数。

<a name="CompressionArguments参数介绍"></a>

#### CompressionArguments 参数介绍

`CompressionArguments` 中的参数一部分是模型压缩功能特定参数,另一部分继承自 `TrainingArguments`,是压缩训练时需要设置的超参数。下面会进行具体介绍,

**公共参数**

公共参数中的参数和具体的压缩策略无关。

- **--strategy** 模型压缩策略,目前支持 `'dynabert+qat+embeddings'``'dynabert+qat'``'dynabert+embeddings'``'dynabert+ptq'``'dynabert'``'ptq'``'qat'`
其中 `'dynabert'` 代表基于 DynaBERT 的宽度裁剪策略,`'qat'` 表示量化训练,`'ptq'` 表示静态离线量化,`'embeddings'` 表示词表量化,并且 `--strategy` 支持选择它们之间所有合理的策略组合。默认是 `'dynabert+ptq'`

- **--output_dir** 模型压缩后模型保存目录;

- **--input_infer_model_path** 待压缩的静态图模型,该参数是为了支持对静态图模型的压缩。不需使用时可忽略。默认为 `None`

- **--input_dtype** 导出模型的输入类型,一般是 `int64` 或者是 `int32`。默认为 `int64`

**DynaBERT 裁剪参数**

当用户使用了 DynaBERT 裁剪、PTQ 量化策略(即策略中包含 'dynabert'、'qat' 时需要传入以下可选参数:

- **--width_mult_list** 裁剪宽度保留的搜索列表,对 6 层模型推荐 `3/4` ,对 12 层模型推荐 `2/3`,表示对 `q``k``v` 以及 `ffn` 权重宽度的保留比例,假设 12 层模型原先有 12 个 attention heads,裁剪后只剩 9 个 attention heads。默认是 `[3/4]`

- **--per_device_train_batch_size**  用于裁剪训练的每个 GPU/CPU 核心 的 batch 大小。默认是 8;

- **--per_device_eval_batch_size** 用于裁剪评估的每个 GPU/CPU 核心 的 batch 大小。默认是 8;

- **--num_train_epochs** 裁剪训练所需要的 epochs 数。默认是 3.0;

- **--max_steps** 如果设置为正数,则表示要执行的训练步骤总数。覆盖 `num_train_epochs`。默认为 -1;

- **--logging_steps** 两个日志之间的更新步骤数。默认为 500;

- **--save_steps** 评估模型的步数。默认为 100;

- **--optim** 裁剪训练使用的优化器名称,默认为adamw,默认为 'adamw';

- **--learning_rate** 裁剪训练使用优化器的初始学习率,默认为 5e-05;

- **--weight_decay** 除了所有 bias 和 LayerNorm 权重之外,应用于所有层裁剪训练时的权重衰减数值。 默认为 0.0;

- **--adam_beta1** 裁剪训练使用 AdamW 的优化器时的 beta1 超参数。默认为 0.9;

- **--adam_beta2** 裁剪训练使用 AdamW 优化器时的 beta2 超参数。默认为 0.999;

- **--adam_epsilon** 裁剪训练使用 AdamW 优化器时的 epsilon 超参数。默认为 1e-8;

- **--max_grad_norm** 最大梯度范数(用于梯度裁剪)。默认为 1.0;

- **--lr_scheduler_type** 要使用的学习率调度策略。默认为 'linear';

- **--warmup_ratio** 用于从 0 到 `learning_rate` 的线性 warmup 的总训练步骤的比例。 默认为 0.0;

- **--warmup_steps** 用于从 0 到 `learning_rate` 的线性 warmup 的步数。覆盖 warmup_ratio 参数。默认是 0;

- **--seed** 设置的随机种子。为确保多次运行的可复现性。默认为 42;

- **--device** 运行的设备名称。支持 cpu/gpu。默认为 'gpu';

- **--remove_unused_columns** 是否去除 Dataset 中不用的字段数据。默认是 True;

**量化公共参数**


**PTQ 量化参数**

当用户使用了 PTQ 量化策略时需要传入以下可选参数:

- **--algo_list** 量化策略搜索列表,目前支持 `'KL'``'abs_max'``'min_max'``'avg'``'hist'``'mse'``'emd'`,不同的策略计算量化比例因子的方法不同。建议传入多种策略,可批量得到由多种策略产出的多个量化模型,可从中选择效果最优模型。ERNIE 类模型较推荐 `'hist'`, `'mse'`, `'KL'``'emd'` 等策略。默认是 ['mse', 'KL'];

- **--batch_num_list** batch_nums 的超参搜索列表,batch_nums 表示采样需要的 batch 数。校准数据的总量是 batch_size * batch_nums。如 batch_num 为 None,则 data loader 提供的所有数据均会被作为校准数据。默认是 [1];

- **--batch_size_list** 校准样本的 batch_size 搜索列表。并非越大越好,也是一个超参数,建议传入多种校准样本数,最后可从多个量化模型中选择最优模型。默认是 `[4]`

- **--weight_quantize_type** 权重的量化类型,支持 `'abs_max'``'channel_wise_abs_max'` 两种方式。通常使用 'channel_wise_abs_max', 这种方法得到的模型通常精度更高;

- **activation_quantize_type** 激活 tensor 的量化类型。支持 'abs_max', 'range_abs_max' 和 'moving_average_abs_max'。在 'ptq' 策略中,默认是 'range_abs_max';

- **--round_type** 权重值从 FP32 到 INT8 的转化方法,目前支持 `'round'` 和 '[adaround](https://arxiv.org/abs/2004.10568.)',默认是 `'round'`

- **--bias_correction** 如果是 True,表示使用 [bias correction](https://arxiv.org/abs/1810.05723) 功能,默认为 False。

**QAT 量化参数**

当用户使用了 QAT 量化策略时,除了可以设置上面训练相关的参数,还可以传入以下可选参数:

- **--weight_quantize_type** 权重的量化类型,支持 `'abs_max'``'channel_wise_abs_max'` 两种方式。通常使用 'channel_wise_abs_max', 这种方法得到的模型通常精度更高;

- **activation_quantize_type** 激活 tensor 的量化类型。支持 'abs_max', 'range_abs_max' 和 'moving_average_abs_max'。在'qat'策略中,它默认是 'moving_average_abs_max';

- **use_pact** 是否使用 PACT 量化策略,是对普通方法的改进,参考论文[PACT: Parameterized Clipping Activation for Quantized Neural Networks](https://arxiv.org/abs/1805.06085),打开后精度更高,默认是 True。

- **moving_rate** 'moving_average_abs_max' 量化方法中的衰减系数,默认为 0.9;

<a name="模型评估与部署"></a>

## 模型评估与部署

裁剪、量化后的模型不能再通过 `from_pretrained` 导入进行预测,而是需要使用 Paddle 部署工具才能完成预测。

压缩后的模型部署可以参考 [部署文档](../model_zoo/ernie-3.0/deploy) 完成。

### Python 部署

服务端部署可以从这里开始。可以参考 [seq_cls_infer.py](../model_zoo/ernie-3.0/deploy/python/seq_cls_infer.py) 或者 [token_cls_infer.py](../model_zoo/ernie-3.0/deploy/python/token_cls_infer.py) 来编写自己的预测脚本。并根据 [Python 部署指南](../model_zoo/ernie-3.0/deploy/python/README.md) 的介绍安装预测环境,对压缩后的模型进行精度评估、性能测试以及部署。


<a name="服务化部署"></a>

### 服务化部署

- [FastDeploy ERNIE 3.0 模型 Serving 部署示例](../model_zoo/ernie-3.0/deploy/serving/README.md)
- [基于PaddleNLP SimpleServing 的服务化部署](../model_zoo/ernie-3.0/deploy/simple_serving/README.md)

### 移动端部署


<a name="FAQ"></a>

## FAQ

**Q:模型压缩需要数据吗?**

A:DynaBERT 裁剪和量化训练 QAT 需要使用训练集进行训练,验证集进行评估,其过程类似微调;静态离线量化 PTQ 只需要验证集(对样本量要求较低,一般 4-16 个样本就可能可以满足要求);

**Q:示例代码里是内置的数据集,如何使用我自己的数据呢**

A:可以参考 UIE 的例子,也可以参考 [datasets 加载自定义数据集文档](https://huggingface.co/docs/datasets/loading)

**Q:模型压缩后的模型还能继续训练吗?**

A:模型压缩主要用于推理加速,因此压缩后的模型都是静态图(预测)模型,不能再通过 `from_pretrained()` API 导入继续训练;

**Q:裁剪和量化怎么选?**

A:可以设置参数 `--strategy` 来选择压缩的策略,默认是裁剪和量化同时选择,先裁剪后量化。目前裁剪策略有训练过程,需要下游任务的训练数据,其训练时间视下游任务数据量而定,且和微调的训练时间是一个量级。静态离线量化则不需要额外的训练,更快,通常来说量化的加速比比裁剪更明显。建议裁剪和量化同时选择,有些情况下可能比单独量化效果更好;

**Q:裁剪中也有训练过程吗?**

A:DynaBERT 裁剪类似蒸馏过程,也会有模型训练时用到的超参,方便起见,可以直接使用微调时所用的最佳的超参。如果想进一步提升精度,可以对 `batch_size``learning_rate``epoch` 等超参数进行 Grid Search;

**Q:使用 `TensorDataset` 对象做量化报错了,为什么?**

A:使用量化时,`eval_dataset` 不可以是 `TensorDataset` 对象,因为量化功能内部在静态图模式下执行,而 `TensorDataset` 只能在动态图下使用,两者同时使用会导致错误;

<a name="References"></a>

## 参考文献
- 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.

- 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.

- 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.