# INT8 Bmodel转化

​在BM1684算力板上，目前已经支持int8模型的部署。在通用流程中，需要先借助于bitmain提供的量化工具对fp32模型进行量化。 ​Qantization-Tools是比特大陆自主开发的网络模型量化工具，它解析各种已训练好的32bit浮点网络模型，生成8bit的定点网络模型。该8bit定点网络模型，可用于比特大陆SOPHON系列AI运算平台。在SOPHON运算平台上，网络各层输入、输出、系数都用8bit来表示，从而在保证网络精度的基础上，大幅减少功耗，内存，传输延迟，大幅提高运算速度。 ​

Quantization-Tools工具架构如下:

![](/files/-LufkpSehfqZY0sgIVdp)

## 1. FP32 Umodel转化

基于开源框架(caffe, tensorflow,pytorch,mxnet)的模型首先需要借助于量化工具转换成为fp32umodel，成为bitmain量化平台私有的格式。基于fp32umodel,后续量化流程已经跟开源框架解耦，作为通用流程执行量化校准。 Bitmain量化平台框架参考caffe框架，因此天然支持caffemodel，在caffemodel无需借助工具，可以直接作为int8校准的输入即可。但是tensorflow、pytorch、mxnet等必须首先转换为fp32umodel.

### **1.1 caffe模型转换fp32umodel**&#x20;

原生支持caffemodel，可以直接把.caffemodel当做.fp32umodel作为输入。

### **1.2 tensorflow模型转换fp32umodel**

在BM1684平台，支持TF int8模型的部署运行，需要对TF标准模型模型(\*.pb)进行量化操作，首先都需要转换为fp32umodel，之后就使用标准量化流程。如下介绍如何使用Quantization-tools提供的工具把TF模型转换成fp32umodel。

量化工具包提供了名为：pb\_to\_umodel的python工具 例如在pb\_to\_fp32umodel的示例中，演示如何把TF resnet50\_v2.pb转换为fp32umodel:

```
 13 import pb_to_umodel
 14 
 15 tf_resnet50 = [
 16     '-m', './models/frozen_resnet_v2_50.pb',
 17     '-i', 'input:0',
 18     '-o', 'resnet_v2_50/predictions/Softmax:0',
 19     '-s', '(1, 299, 299, 3)',
 20     '-d', 'compilation',
 21     '-n', 'resnet50_v2',
 22     '-p', 'INCEPTION',
 23     '-D', '../classify_demo/lmdb/imagenet_s/ilsvrc12_val_lmdb',
 24     '-a',
 25     '-t'
 26 ]
 27 
 28 if __name__ == '__main__':
 29     args = pb_to_umodel.parse_args().parse_args(tf_resnet50)
 30     pb_to_umodel.convert_pb_to_umodelv2(args)
```

在docker环境下，直接执行：

```
python3 resnet50_v2_to_umodel.py
```

在当前文件夹下,新生成 compilation 文件夹,存放新生成&#x7684;*.fp32umodel 与*.prototxt

* pb\_to\_umodel的命令参数：

| args | Description                                                                            |
| ---- | -------------------------------------------------------------------------------------- |
| -m   | 指向\*.pb文件的路径                                                                           |
| -i   | 输入tensor的名称                                                                            |
| -o   | 输出tensor的名称                                                                            |
| -s   | 输入tensor的维度,(N,H,W,C)                                                                  |
| -d   | 输出文件夹的名字                                                                               |
| -n   | 网络的名字                                                                                  |
| -p   | 数据预处理类型,预先定义了VGG,INCEPTION,SSD\_V,SSD\_I几种,没有合适的随意选一个,然后在手动编辑prototxt文件的时候,根据实际的预处理来添加 |
| -D   | lmdb数据集的位置,没有的话,可以暂时随意填个路径,然后在手动编辑prototxt文件的时候,根据实际的路径来添加                             |
| -a   | 加上该参数,会在生成的模型中添加top1,top5两个accuracy层                                                   |
| -t   | 固定参数                                                                                   |

详细文件可以参考pb\_to\_fp32umodel的示例.

### **1.3 pytorch模型转换fp32umodel**&#x20;

暂未发布&#x20;

### **1.4 mxnet模型转换fp32umodel**&#x20;

暂未发布

## 2. FP32 Umodel转换INT8 Umodel转化

此流程从fp32umodel转换为int8umodel，即为量化过程。&#x20;

基于fp32umodel网络模型进行int8的量化，主要骤如下： ​&#x20;

2.1 准备lmdb数据集 ​&#x20;

2.2 生成int8umodel ​&#x20;

2.3 精度测试（optional）

### **2.1 准备lmdb数据集**&#x20;

原始数据集合转换成lmdb格式，供后续校准量化使用。

lmdb数据集合的生成，有两种方式：一是通过convert\_imageset工具直接针对测试图片集合生成，二是通过u\_framework框架接口来生成，主要针对级联网络，后级网络的输入依赖前级网络的输出，例如mtcnn.

当前主要介绍convert\_imageset工具如何生成数据集合，此方式是通用方式。u\_framework生成级联网络所需要的lmdb在mtcnn demo中详细介绍。

SDK工具包包括了将图像转换成lmdb的工具，convert\_imageset，类似于caffe框架中的使用方式。

```
   Usage:
       convert_imageset [FLAGS] ROOTFOLDER/ LISTFILE DB_NAME
```

其中ROOTFOLDER为图像集的根目录，LISTFILE 为列表文件，该文件中记录了图像集中的各图样的路径和相应的标注，DB\_NAME为要生成的数据库的名字。

* 参数说明：

| args            | description                                                                                    |
| --------------- | ---------------------------------------------------------------------------------------------- |
| -backend        | The backend (lmdb, leveldb) for storing the result. type: string default: "lmdb"               |
| -check\_size    | When this option is on, check that all the datum have the same size. type: bool default: false |
| -encode\_type   | optional: What type should we encode the image as ('png','jpg',...). type: string default: ""  |
| -encoded        | When this option is on, the encoded image will be save in datum. type: bool default: false     |
| -gray           | When this option is on, treat images as grayscale ones. type: bool default: false              |
| -resize\_height | Height images are resized to. type: int32 default: 0                                           |
| -resize\_width  | Width images are resized to. type: int32 default: 0                                            |
| -shuffle        | (Randomly shuffle the order of images and their labels. type: bool default: false              |

参考sdk中示例：

```
     # argv[1] : image dir
     # argv[2] : image list
     convert_imageset --shuffle --resize_height=256 --resize_width=256 \
               $IMG_DIR/  $IMG_DIR/ImgList.txt  $IMG_DIR/img_lmdb
```

为了使用刚生成的 lmdb 数据集,需要对网络的\*.prototxt 文件作以下三方面的修改:&#x20;

1. 使用 Data layer 作为网络的输入&#x20;
2. 使 Data layer 的参数 data\_param 指向生成的 lmdb 数据集的位置&#x20;
3. 修改 Data layer 的 transform\_param 参数以对应网络对图片的预处理

例如：

![](/files/-Lufz33UHIXAkSnjlIKA)

完成上述步骤就可以配置完lmdb.

另外，在配置prototxt的datalayer参数时，提供了灵活的方式按照网络实际输入特征配置，支持的transform\_paramters:&#x20;

![](/files/-LufzJnsLPT_EI54BjRB)

{% hint style="info" %}
**需要注意**：&#x20;

1. 在编译 prototxt 文件时,transform\_op 中定义的参数与 transform\_op 外定义的参数只能二选一。例如上图左右，一个是transform\_op的参数，另外一个则没有。
2. transform\_op 中定义的参数按其在 prototxt 定义的顺序来执行,适用于灵活的数据预处理组合。
3. transform\_op 外定义的参数其执行顺序是固定的。 预处理的先后顺序如下：
   {% endhint %}

* transform\_parameter支持的参数如下：

```
   message TransformationParameter {
// For data pre-processing, we can do simple scaling and subtracting the
// data mean, if provided. Note that the mean subtraction is always carried
// out before scaling.
optional float scale = 1 [default = 1];
// Specify if we want to randomly mirror data.
optional bool mirror = 2 [default = false];
// Specify if we would like to randomly crop an image.
optional uint32 crop_size = 3 [default = 0];
// mean_file and mean_value cannot be specified at the same time
optional string mean_file = 4;
// if specified can be repeated once (would subtract it from all the channels)
// or can be repeated the same number of times as channels
// (would subtract them from the corresponding channel)
repeated float mean_value = 5;
// Force the decoded image to have 3 color channels.
optional bool force_color = 6 [default = false];
// Force the decoded image to have 1 color channels.
optional bool force_gray = 7 [default = false];
// Resize policy
optional ResizeParameter resize_param = 8;
// Noise policy
optional NoiseParameter noise_param = 9;
// Constraint for emitting the annotation after transformation.
optional EmitConstraint emit_constraint = 10;
optional uint32 crop_h = 11 [default = 0];
optional uint32 crop_w = 12 [default = 0];
// Distortion policy
optional DistortionParameter distort_param = 13;
// Expand policy
optional ExpansionParameter expand_param = 14;
// TensorFlow data pre-processing
optional float crop_fraction = 15 [default = 0];
// if the number of resize is 1 preserve the original aspect ratio
repeated uint32 resize = 16;
// less useful
optional bool standardization = 17 [default = false];
repeated TransformOp transform_op = 18;
}
```

* ResizeParameter定义：

  ```
  / Message that stores parameters used by data transformer for resize policy
  message ResizeParameter {
  //Probability of using this resize policy
  optional float prob = 1 [default = 1];
  enum Resize_mode {
  WARP = 1;
  FIT_SMALL_SIZE = 2;
  FIT_LARGE_SIZE_AND_PAD = 3;
  }
  optional Resize_mode resize_mode = 2 [default = WARP];
  optional uint32 height = 3 [default = 0];
  optional uint32 width = 4 [default = 0];
  // A parameter used to update bbox in FIT_SMALL_SIZE mode.
  optional uint32 height_scale = 8 [default = 0];
  optional uint32 width_scale = 9 [default = 0];
  enum Pad_mode {
  CONSTANT = 1;
  MIRRORED = 2;
  REPEAT_NEAREST = 3;
  }
  // Padding mode for BE_SMALL_SIZE_AND_PAD mode and object centering
  optional Pad_mode pad_mode = 5 [default = CONSTANT];
  // if specified can be repeated once (would fill all the channels)
  // or can be repeated the same number of times as channels
  // (would use it them to the corresponding channel)
  repeated float pad_value = 6;
  enum Interp_mode { //Same as in OpenCV
  LINEAR = 1;
  AREA = 2;
  NEAREST = 3;
  CUBIC = 4;
  LANCZOS4 = 5;
  }
  //interpolation for for resizing
  repeated Interp_mode interp_mode = 7;
  }
  ```
* transform\_parameter中的transform\_op的定义如下：

  ```
  message TransformOp {
  enum Op {
  RESIZE = 0;
  CROP = 1;
  STAND = 2;
  NONE = 3;
  }
  // For historical reasons, the default normalization for
  // SigmoidCrossEntropyLoss is BATCH_SIZE and *not* VALID.
  optional Op op = 1 [default = NONE];
  //resize parameters
  optional uint32 resize_side = 2 ;
  optional uint32 resize_h = 3 [default = 0];
  optional uint32 resize_w = 4 [default = 0];
  //crop parameters
  optional float
  crop_fraction = 5;
  optional uint32 crop_h = 6 [default = 0];
  optional uint32 crop_w = 7 [default = 0];
  optional float
  padding = 8 [default = 0];//for resize_with_crop_or_pad
  //mean substraction(stand)
  repeated float mean_value = 9;
  optional string mean_file = 10;
  optional float scale = 11 [default = 1];
  optional float div = 12 [default = 1];
  optional bool
  bgr2rgb = 13 [default = false];
  }
  ```

  以上步骤主要是为准确配置prototxt的datalayer参数，如何使用lmdb.

#### **关于Annotated information的lmdb处理**&#x20;

对于检测网络来说,其 label 不仅仅是个数字,它包括类别,检测框的位置等复杂信息。对于这种情况,分两种情况处理:&#x20;

1.如果lmdb已经生成存在，并且带有Annotated信息，那么在prototxt中需要使用AnnotatedData layer来加载lmdb，

例如：

![](/files/-Lug-2rhA9u4d6M0oGoY)

2.如果lmdb还没有生成，那么在使用convert\_imageset工具的时候，修改filelist中的label信息为随机数即可(<1000)，正常使用Data layer来加载此lmdb文件。（在量化网络过程中，annotated信息，例如label, bbox坐标都不是必须的，只需要保证生成lmdb的图片集合是正样本即可）

### **2.2 生成int8umodel**

SDK提供工具，直接可以把fp32umodel(.caffemodel)转换成bitmain私有的中间临时模型(int8umodel)。 量化工具中使用calibration\_use\_pb来执行校准操作，命令使用如下：

```
    calibration_use_pb \
          release \ #固定参数
          -model= PATH_TO/**.prototxt \ #描述网络结构的文件
          -weights=PATH_TO/**.fp32umodel \#网络系数文件(caffemodel可以直接使用)
          -iterations=1000 \ #迭代的次数(定点化过程中使用多少张图片，每次迭代使用一张图片)
          -bitwidth=TO_INT8 #固定参数
```

例如示例中的SSD模型转换的步骤：

```
      function calibration() 
      {
        calibration_use_pb release \
          -model=./ssd300_umodel.prototxt   \
          -weights=./ssd300.caffemodel  \
          -iterations=1000 \
          -bitwidth=TO_INT8

      }
```

运行正常后会产生输出部分：

```
      ├── ssd300_deploy_fp32_unique_top.prototxt
      ├── ssd300_deploy_int8_unique_top.prototxt
      ├── ssd300.int8umodel
      ├── ssd300_test_fp32_unique_top.prototxt
      ├── ssd300_test_int8_unique_top.prototxt
      └── ssd300_umodel.prototxt
```

*\**.int8umodel即量化生成的int8格式的网络系数文件&#x20;

\*\_deploy\_int8\_unique\_top.prototxt为int8格式的网络结构文件，&#x20;

*\**\_deploy\_fp32\_unique\_top.prototxt为fp32格式的网络结构文件，int8\_unique\_top.prototxt文件作为后续部署生成bmodel使用, fp32为对比二者的区别。由于为部署文件，此prototxt不包含Datalayer，而是Input layer，同时各layer的输出blob是唯一的，不存在in-place的情&#x51B5;*。*&#x20;

*\**\_test\_int8\_unique\_top.prototxt & \*\_test\_fp32\_unique\_top.prototxt分别是int8/fp32的网络结构文件，此两个文件作为精度比较时使用，验证量化的结果。相对应地，此两文件包含Datalayer。

deploy\_int8\_\*.prototxt*与*test\_int8\_\*.prototxt的内容主要区别例如：

![](/files/-Lug-Lb-PO4sZZkc76Lp)

{% hint style="info" %}
注意deploy*int8.prototxt比testint8*.prototxt在第一层之前多了一个int8\_scale的参数，该参数在部署算法推理的时候需要对Input data做scale处理。 int8\_scale的含义是：在原有的float32网络的数据预处理的基础上，乘以int8\_scale，四舍五入求整后，再送给int8网络。
{% endhint %}

上述量化校准后生成的文件都存放在fp32umodel的同级目录下。 最终量化后，提供给下一步所需要的文件为： deploy\_int8\_unique\_top.prototxt & \*.int8umodel


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://1684.gitbook.io/bmnnsdk2-1684-2-0-1/int8-bmodel-zhuan-hua.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
