Analysis.md 7.4 KB
Newer Older
1
# 量化分析工具详细教程
2 3 4 5 6 7 8 9 10 11 12 13 14 15

## 1. 量化分析工具功能
1. 统计分析(statistical_analyse):
    - 可视化激活和权重箱状图。箱状图可发现是否出现离群点。
    - 可视化权重和激活直方分布图。直方分布图可观察更具体的数值分布。
    - 提供量化前后权重和激活的具体数据信息,包括min,max,mean,std等。

2. 精度误差分析(metric_error_analyse):
    - 遍历量化模型的每层,并计算量化后精度。该功能可以定位具体某层导致的量化损失。

3. 获取目标模型(get_target_quant_model):
    - 输入预期精度,直接产出符合预期精度的量化模型。


16
## 2. paddleslim.quant.Analysis 可传入参数解析
17 18
| **参数名**                   | **参数释义**                              |
|-----------------------------|-----------------------------------------|
19 20
| float_model_dir | 必须传入的模型文件路径,可为文件夹名;若模型为ONNX类型,直接输入'.onnx'模型文件名称即可 |
| quant_model_dir | 默认为None,传入的量化模型文件路径,可为文件夹名;若模型为ONNX类型,直接输入'.onnx'模型文件名称即可; 若不传入,分析工具将使用PTQ进行量化并分析|
21 22
| model_filename | 默认为None,若model_dir为文件夹名,则必须传入以'.pdmodel'结尾的模型名称,若model_dir为'.onnx'模型文件名称,则不需要传入 |
| params_filename | 默认为None,若model_dir为文件夹名,则必须传入以'.pdiparams'结尾的模型名称,若model_dir为'.onnx'模型文件名称,则不需要传入 |
23
| eval_function | 若需要验证精度,需要传入自定义的验证函数;若不传入,精度误差分析将根据Cosine Similarity计算得出 |
24 25 26
| data_loader | 模型校准时使用的数据,DataLoader继承自`paddle.io.DataLoader`。可以直接使用模型套件中的DataLoader,或者根据[paddle.io.DataLoader](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/io/DataLoader_cn.html#dataloader)自定义所需要的DataLoader |
| save_dir | 分析后保存模型精度或pdf等文件的文件夹,默认为`analysis_results`|
| resume | 是否加载中间分析文件,默认为False|
27
| quant_config | 可传入的离线量化中的参数,详细可参考[离线量化文档](https://github.com/PaddlePaddle/PaddleSlim/tree/develop/demo/quant/quant_post) |
28 29 30 31 32 33 34





## 3. 量化分析工具的使用
**创建量化分析工具**
35 36 37 38 39 40 41
```shell
# 下载Inference模型
wget -q https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/inference/MobileNetV1_infer.tar
tar -xf MobileNetV1_infer.tar
# 下载demo数据集
wget -q https://sys-p0.bj.bcebos.com/slim_ci/ILSVRC2012_data_demo.tar.gz
tar -xf ILSVRC2012_data_demo.tar.gz
42
```
43 44 45 46 47 48

```shell
import paddle
from PIL import Image
from paddle.vision.datasets import DatasetFolder
from paddle.vision.transforms import transforms
49
from paddleslim.quant.analysis import Analysis
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
paddle.enable_static()

class ImageNetDataset(DatasetFolder):
    def __init__(self, path, image_size=224):
        super(ImageNetDataset, self).__init__(path)
        normalize = transforms.Normalize(
            mean=[123.675, 116.28, 103.53], std=[58.395, 57.120, 57.375])
        self.transform = transforms.Compose([
            transforms.Resize(256), transforms.CenterCrop(image_size),
            transforms.Transpose(), normalize
        ])

    def __getitem__(self, idx):
        img_path, _ = self.samples[idx]
        return self.transform(Image.open(img_path).convert('RGB'))

    def __len__(self):
        return len(self.samples)

train_dataset = ImageNetDataset(
    "./ILSVRC2012_data_demo/ILSVRC2012/train/")
image = paddle.static.data(
    name='inputs', shape=[None] + [3, 224, 224], dtype='float32')
train_loader = paddle.io.DataLoader(
    train_dataset, feed_list=[image], batch_size=8, return_list=False)

76 77
analyzer = Analysis(
    float_model_dir="./MobileNetV1_infer",
78 79 80
    model_filename="inference.pdmodel",
    params_filename="inference.pdiparams",
    save_dir="MobileNetV1_analysis",
81
    quant_config={
82 83 84 85 86 87 88 89
          'quantizable_op_type': ["conv2d", "depthwise_conv2d"],
          'weight_quantize_type': 'abs_max',
          'activation_quantize_type': 'moving_average_abs_max',
          'is_full_quantize': False,
          'batch_size': 8,
          'batch_nums': 1,
    },
    data_loader=train_loader)
90 91 92
```

**统计分析**
93
```shell
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
analyzer.statistical_analyse()
```

调用该接口,会统计量化前和量化后每一个可量化权重和其对应激活的数据。只使用该接口可以不输入Eval Function,但需要输入DataLoader,少量数据即可。会产出以下文件:
- `fp_activation_boxplot.pdf`:量化前Float数据类型的模型激活箱状图
- `fp_weight_boxplot.pdf`:量化前Float数据类型的模型权重箱状图
- `quantized_activation_boxplot.pdf`:量化后INT数据类型的模型激活箱状图
- `quantized_weight_boxplot.pdf`:量化后INT数据类型的模型权重箱状图
- `fp_activation_histplot.pdf`:量化前Float数据类型的模型激活直方图
- `fp_weight_histplot.pdf`:量化前Float数据类型的模型权重直方图
- `quantized_activation_histplot.pdf`:量化后INT数据类型的模型激活直方图
- `quantized_weight_histplot.pdf`:量化后INT数据类型的模型权重直方图
- `statistic.csv`:量化前后权重和激活的具体数据信息,表格中会保存的信息有:
    - Var Name: Variable的名称
    - Var Type:Variable的类型,Weight或Activation
    - Corresponding Weight Name:如果为Activation,其对应的Weight名称
    - FP32 Min:量化前Float数据类型的最小值
    - FP32 Max:量化前Float数据类型的最大值
    - FP32 Mean:量化前Float数据类型的平均值
    - FP32 Std:量化前Float数据类型的方差值
    - Quantized Min:量化后INT数据类型的最小值
    - Quantized Max:量化后INT数据类型的最大值
    - Quantized Mean:量化后INT数据类型的平均值
    - Quantized Std:量化后INT数据类型的方差值
    - Diff Min:量化前后该Variable的相差的最小值
    - Diff Max:量化前后该Variable的相差的最大值
    - Diff Mean:量化前后该Variable的相差的平均值
    - Diff Std:量化前后该Variable的相差的方差值


**精度误差分析**
125
```shell
126 127
analyzer.metric_error_analyse()
```
128 129 130 131
若不传入quant_model_dir,并且调用该接口,会遍历量化模型中的一层,并计算量化该层后模型的损失。调用该接口时,需要输入Eval Function。会产出所有只量化一层的模型精度排序,将默认保存在 `./analysis_results/analysis.txt` 中。

若传入quant_model_dir,并且调用该接口,会遍历量化模型中的每一层,去掉量化节点并计算当前层不量化的模型精度。调用该接口时,需要输入Eval Function。会产出所有去掉一层量化的模型精度排序,将默认保存在 `./analysis_results/analysis.txt` 中。具体使用可参考[GPT量化训练敏感度分析DEMO](../../../../example/quantization_analysis/GPT/README.md)

132 133 134 135



**直接产出符合预期精度的目标量化模型**
136
```shell
137
analyzer.get_target_quant_model(target_metric=0.70)
138 139 140 141
```

## 4. 根据分析结果执行离线量化
执行完量化分析工具后,可根据 `analysis.txt` 中的精度排序,在量化中去掉效果较差的层,具体操作为:在调用 `paddleslim.quant.quant_post_static` 时加入参数 `skip_tensor_list`,将需要去掉的层传入即可。