update netrans_py
This commit is contained in:
parent
b8f50fc918
commit
f7b0552329
|
@ -12,8 +12,6 @@ netrans
|
|||
└── utils
|
||||
```
|
||||
|
||||
目录说明如下:
|
||||
|
||||
| 目录 | 说明 |
|
||||
| :--- | ---
|
||||
| netrans_cli | 导入,量化,推理和导出的一键运行脚本 |
|
||||
|
@ -30,9 +28,6 @@ netrans
|
|||
|
||||
## 1.3 支持介绍
|
||||
netrans 支持的 输入模型、量化数据和输出数据类型、算子 如下表
|
||||
|
||||
支持框架介绍
|
||||
|
||||
|输入支持|描述|
|
||||
|:---|---|
|
||||
| caffe|支持|
|
||||
|
@ -41,10 +36,8 @@ netrans 支持的 输入模型、量化数据和输出数据类型、算子 如
|
|||
| ONNX|支持 ONNX 至 1.14.0, opset支持至19 |
|
||||
| Pytorch | 支持 Pytorch 至 1.5.1 |
|
||||
| Keras |支持以TensorFLow 2.0.x, 2.3.x, 2.6.x, 2.8.x, 2.10.x, 2.12.x 作为后端导出的keras模型|
|
||||
| Darknet |支持[Darknet官网](https://pjreddie.com/darknet/)列出 darknet 模型|
|
||||
| Darknet |支持[官网](https://pjreddie.com/darknet/)列出 darknet 模型|
|
||||
|
||||
支持数据类型介绍:
|
||||
|
||||
|数据支持|描述|
|
||||
|:---|---|
|
||||
| 推理输入数据| 推理输入数据支持txt文本文件、numpy数据|
|
||||
|
@ -53,7 +46,6 @@ netrans 支持的 输入模型、量化数据和输出数据类型、算子 如
|
|||
|
||||
## 1.4 系统要求
|
||||
运行 Netrans 的计算机应该满足以下要求。
|
||||
|
||||
|资源|描述|
|
||||
|:---|---|
|
||||
| CPU | Intel® Core™ i5-6500 CPU @ 3.2 GHz x4 支持 the Intel® Advanced Vector Extensions.|
|
||||
|
@ -77,21 +69,21 @@ Netrans为编译好的文件,只需要在系统中添加对应的路径即可
|
|||
|
||||
方案一:需要修改.bashrc文件增加以下行,请注意路径匹配。
|
||||
|
||||
```shell
|
||||
export NETRANS_PATH=netrans/bin
|
||||
```
|
||||
```shell
|
||||
export NETRANS_PATH=netrans/bin
|
||||
```
|
||||
|
||||
然后执行
|
||||
|
||||
```shell
|
||||
source ~/.bashrc
|
||||
```
|
||||
```shell
|
||||
source ~/.bashrc
|
||||
```
|
||||
|
||||
方案二:在命令行中直接输入以下行,请注意路径匹配。
|
||||
|
||||
```shell
|
||||
export NETRANS_PATH=netrans/bin
|
||||
```
|
||||
```shell
|
||||
export NETRANS_PATH=netrans/bin
|
||||
```
|
||||
|
||||
## 2.2 工作流程
|
||||
对于float数据类型的模型,工作流程如下:
|
||||
|
@ -181,34 +173,34 @@ Netrans 支持文本文件,通过读取文本文件 dataset.txt 获取 推理
|
|||
|
||||
新建数据集文件“dataset.txt”,里面包括推理和导出需要用到的图片数据。新建一个名为dataset.txt的文本文件,在文件中指定图片路径。例如:
|
||||
|
||||
```shell
|
||||
$ cat lenet/dataset.txt
|
||||
0.jpg
|
||||
```
|
||||
```shell
|
||||
$ cat lenet/dataset.txt
|
||||
0.jpg
|
||||
```
|
||||
|
||||
### 2.3.2 工程目录准备
|
||||
以上需要准备的文件,模型相关和数据相关,都需要放在同一个文件夹中,如果使用命令行工具 netrans_cli,模型文件和权重文件的名字要和文件夹的名字一致,且需要将目录放在目录 netrans_cli 下。
|
||||
|
||||
下面以 lenet 为例进行展示 :
|
||||
|
||||
```shell
|
||||
$ cd pnna_sdk/netrans/netrans_cli/
|
||||
$ cp -r ../../models/lenet ./
|
||||
$ cd lenet
|
||||
$ ls -l
|
||||
total 3396
|
||||
-rw-r--r-- 1 hope hope 553 Nov 5 2018 0.jpg
|
||||
-rwxr--r-- 1 hope hope 6 Apr 21 17:04 dataset.txt
|
||||
-rw-rw-r-- 1 hope hope 69 Apr 23 15:10 inputs_outputs.txt
|
||||
-rwxr-xr-x 1 hope hope 1727201 Nov 5 2018 lenet.pb
|
||||
```
|
||||
```shell
|
||||
$ cd pnna_sdk/netrans/netrans_cli/
|
||||
$ cp -r ../../models/lenet ./
|
||||
$ cd lenet
|
||||
$ ls -l
|
||||
total 3396
|
||||
-rw-r--r-- 1 hope hope 553 Nov 5 2018 0.jpg
|
||||
-rwxr--r-- 1 hope hope 6 Apr 21 17:04 dataset.txt
|
||||
-rw-rw-r-- 1 hope hope 69 Apr 23 15:10 inputs_outputs.txt
|
||||
-rwxr-xr-x 1 hope hope 1727201 Nov 5 2018 lenet.pb
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
# 3. netrans_cli
|
||||
|
||||
netrans_cli 脚本介绍
|
||||
|
||||
|脚本|功能|使用|
|
||||
|:---|---|---|
|
||||
|import_model.sh| 模型导入功能,将模型转换成 pnna 支持的格式| sh import_model.sh model_name|
|
||||
|
@ -227,7 +219,6 @@ netrans_cli 脚本介绍
|
|||
|
||||
在netrans_cli目录下使用import.sh脚本进行导入
|
||||
- 用法: ./import.sh 以模型文件名命名的模型数据文件夹,例如:
|
||||
|
||||
```shell
|
||||
$ ./import.sh lenet
|
||||
... ...
|
||||
|
@ -238,7 +229,6 @@ netrans_cli 脚本介绍
|
|||
SUCCESS
|
||||
```
|
||||
"lenet"是文件夹名,也作为模型名和权重文件名。导入会打印相关日志信息,成功后会打印SUCESS。导入后lenet文件夹应该有"lenet.json"和"lenet.data"文件:
|
||||
|
||||
```shell
|
||||
$ ls -lrt lenet
|
||||
total 3396
|
||||
|
@ -253,80 +243,78 @@ netrans_cli 脚本介绍
|
|||
### 3.2 生成Inputmeta文件
|
||||
在netrans_cli目录下使用inputmeta_gen.sh脚本生成inputmeta文件:
|
||||
- 用法: ./inputmeta_gen.sh 以模型文件名命名的模型数据文件夹,例如:
|
||||
|
||||
```shell
|
||||
$ ./inputmeta_gen.sh lenet
|
||||
... ...
|
||||
I Namespace(generate='inputmeta', input_meta_output=None, model='lenet.json', separated_database=True, which='generate')
|
||||
I Load model in lenet.json
|
||||
I Generate input meta lenet_inputmeta.yml
|
||||
I ----------------Error(0),Warning(0)----------------
|
||||
```shell
|
||||
$ ./inputmeta_gen.sh lenet
|
||||
... ...
|
||||
I Namespace(generate='inputmeta', input_meta_output=None, model='lenet.json', separated_database=True, which='generate')
|
||||
I Load model in lenet.json
|
||||
I Generate input meta lenet_inputmeta.yml
|
||||
I ----------------Error(0),Warning(0)----------------
|
||||
|
||||
$ ls -lrt lenet
|
||||
total 3400
|
||||
-rwxr-xr-x 1 hope hope 1727201 Nov 5 2018 lenet.pb
|
||||
-rw-r--r-- 1 hope hope 553 Nov 5 2018 0.jpg
|
||||
-rwxr--r-- 1 hope hope 6 Apr 21 17:04 dataset.txt
|
||||
-rw-rw-r-- 1 hope hope 69 Jun 7 09:19 inputs_outputs.txt
|
||||
-rw-r--r-- 1 hope hope 5553 Jun 7 09:21 lenet.json
|
||||
-rw-r--r-- 1 hope hope 1725178 Jun 7 09:21 lenet.data
|
||||
-rw-r--r-- 1 hope hope 948 Jun 7 09:35 lenet_inputmeta.yml
|
||||
```
|
||||
$ ls -lrt lenet
|
||||
total 3400
|
||||
-rwxr-xr-x 1 hope hope 1727201 Nov 5 2018 lenet.pb
|
||||
-rw-r--r-- 1 hope hope 553 Nov 5 2018 0.jpg
|
||||
-rwxr--r-- 1 hope hope 6 Apr 21 17:04 dataset.txt
|
||||
-rw-rw-r-- 1 hope hope 69 Jun 7 09:19 inputs_outputs.txt
|
||||
-rw-r--r-- 1 hope hope 5553 Jun 7 09:21 lenet.json
|
||||
-rw-r--r-- 1 hope hope 1725178 Jun 7 09:21 lenet.data
|
||||
-rw-r--r-- 1 hope hope 948 Jun 7 09:35 lenet_inputmeta.yml
|
||||
```
|
||||
可以看到,最终生成的是*.yml文件,该文件用于为Netrans中间模型配置输入层数据集合。<b>Netrans中的量化、推理、导出和图片转dat的操作都需要用到这个文件。因此,此步骤不可跳过。</b>
|
||||
|
||||
Inputmeta.yml文件结构如下:
|
||||
|
||||
```yaml
|
||||
%YAML 1.2
|
||||
---
|
||||
# !!!This file disallow TABs!!!
|
||||
# "category" allowed values: "image, undefined"
|
||||
# "database" allowed types: "H5FS, SQLITE, TEXT, LMDB, NPY, GENERATOR"
|
||||
# "tensor_name" only support in H5FS database
|
||||
# "preproc_type" allowed types:"IMAGE_RGB, IMAGE_RGB888_PLANAR, IMAGE_RGB888_PLANAR_SEP,
|
||||
IMAGE_I420,
|
||||
# IMAGE_NV12, IMAGE_YUV444, IMAGE_GRAY, IMAGE_BGRA, TENSOR"
|
||||
input_meta:
|
||||
databases:
|
||||
- path: dataset.txt
|
||||
type: TEXT
|
||||
ports:
|
||||
- lid: data_0
|
||||
category: image
|
||||
dtype: float32
|
||||
sparse: false
|
||||
tensor_name:
|
||||
layout: nhwc
|
||||
shape:
|
||||
- 50
|
||||
- 224
|
||||
- 224
|
||||
- 3
|
||||
preprocess:
|
||||
reverse_channel: false
|
||||
mean:
|
||||
- 103.94
|
||||
- 116.78
|
||||
- 123.67
|
||||
scale: 0.017
|
||||
preproc_node_params:
|
||||
preproc_type: IMAGE_RGB
|
||||
add_preproc_node: false
|
||||
preproc_perm:
|
||||
- 0
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
- lid: label_0
|
||||
redirect_to_output: true
|
||||
category: undefined
|
||||
tensor_name:
|
||||
dtype: float32
|
||||
shape:
|
||||
- 1
|
||||
- 1
|
||||
|
||||
```
|
||||
```yaml
|
||||
%YAML 1.2
|
||||
---
|
||||
# !!!This file disallow TABs!!!
|
||||
# "category" allowed values: "image, undefined"
|
||||
# "database" allowed types: "H5FS, SQLITE, TEXT, LMDB, NPY, GENERATOR"
|
||||
# "tensor_name" only support in H5FS database
|
||||
# "preproc_type" allowed types:"IMAGE_RGB, IMAGE_RGB888_PLANAR, IMAGE_RGB888_PLANAR_SEP,
|
||||
IMAGE_I420,
|
||||
# IMAGE_NV12, IMAGE_YUV444, IMAGE_GRAY, IMAGE_BGRA, TENSOR"
|
||||
input_meta:
|
||||
databases:
|
||||
- path: dataset.txt
|
||||
type: TEXT
|
||||
ports:
|
||||
- lid: data_0
|
||||
category: image
|
||||
dtype: float32
|
||||
sparse: false
|
||||
tensor_name:
|
||||
layout: nhwc
|
||||
shape:
|
||||
- 50
|
||||
- 224
|
||||
- 224
|
||||
- 3
|
||||
preprocess:
|
||||
reverse_channel: false
|
||||
mean:
|
||||
- 103.94
|
||||
- 116.78
|
||||
- 123.67
|
||||
scale: 0.017
|
||||
preproc_node_params:
|
||||
preproc_type: IMAGE_RGB
|
||||
add_preproc_node: false
|
||||
preproc_perm:
|
||||
- 0
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
- lid: label_0
|
||||
redirect_to_output: true
|
||||
category: undefined
|
||||
tensor_name:
|
||||
dtype: float32
|
||||
shape:
|
||||
- 1
|
||||
- 1
|
||||
|
||||
```
|
||||
|
||||
上面示例文件的各个参数解释:
|
||||
|
||||
|
@ -358,21 +346,21 @@ Inputmeta.yml文件结构如下:
|
|||
可以根据实际情况对生成的inputmeta文件进行修改。
|
||||
|
||||
### 3.3 模型量化
|
||||
如果我们训练好的模型的数据类型是float32的,为了使模型以更高的效率在pnna上运行,我们可以对模型进行量化操作,量化操作可能会带来一定程度的精度损失。
|
||||
如果我们训练好的模型的数据类型是float32的,为了使模型以更高的效率在pnna上运行,我们可以对模型进行量化操作,量化操作可能会带来一定程度的精度损失。<
|
||||
在netrans_cli目录下使用quantize.sh脚本进行量化操作。
|
||||
|
||||
- 用法:./quantize.sh 以模型文件名命名的模型数据文件夹 量化类型,例如:
|
||||
用法:./quantize.sh 以模型文件名命名的模型数据文件夹 量化类型,例如:
|
||||
|
||||
```shell
|
||||
$ ./quantize.sh lenet uint8
|
||||
... ...
|
||||
I End quantization...
|
||||
I Dump net quantize tensor table to lenet_asymmetric_affine.quantize
|
||||
I Save net to lenet.data
|
||||
I ----------------Error(0),Warning(0)----------------
|
||||
SUCCESS
|
||||
```shell
|
||||
$ ./quantize.sh lenet uint8
|
||||
... ...
|
||||
I End quantization...
|
||||
I Dump net quantize tensor table to lenet_asymmetric_affine.quantize
|
||||
I Save net to lenet.data
|
||||
I ----------------Error(0),Warning(0)----------------
|
||||
SUCCESS
|
||||
|
||||
```
|
||||
```
|
||||
|
||||
支持的量化类型有:uint8、int8、int16
|
||||
|
||||
|
@ -409,25 +397,25 @@ Inputmeta.yml文件结构如下:
|
|||
|
||||
在netrans_cli目录下使用export.sh脚本进行推理。
|
||||
|
||||
- 用法:./export.sh 以模型文件名命名的模型数据文件夹 数据类型,例如:
|
||||
用法:./export.sh 以模型文件名命名的模型数据文件夹 数据类型,例如:
|
||||
|
||||
```shell
|
||||
./export.sh lenet uint8
|
||||
... ...
|
||||
I End exporting ovxlib case...
|
||||
I ----------------Error(0),Warning(0)----------------
|
||||
=======================================================================
|
||||
=========== End Generate lenet ovx C code with type of asymmetric_affine ===========
|
||||
=======================================================================
|
||||
```
|
||||
```shell
|
||||
./export.sh lenet uint8
|
||||
... ...
|
||||
I End exporting ovxlib case...
|
||||
I ----------------Error(0),Warning(0)----------------
|
||||
=======================================================================
|
||||
=========== End Generate lenet ovx C code with type of asymmetric_affine ===========
|
||||
=======================================================================
|
||||
```
|
||||
|
||||
导出支持的数据类型:float、uint8、int8、int16,其中使用uint8、int8、int16导出时需要先进行[模型量化](#33-模型量化)。导出的工程会在模型所在的目录下面的wksp目录里。
|
||||
network_binary.nb文件在"asymmetric_affine"文件夹中:
|
||||
|
||||
```shell
|
||||
ls -lrt lenet/wksp/asymmetric_affine/
|
||||
-rw-r--r-- 1 hope hope 694912 Jun 7 09:55 network_binary.nb
|
||||
```
|
||||
```shell
|
||||
ls -lrt lenet/wksp/asymmetric_affine/
|
||||
-rw-r--r-- 1 hope hope 694912 Jun 7 09:55 network_binary.nb
|
||||
```
|
||||
|
||||
目前支持将生成的network_binary.nb文件部署到pnna硬件平台。具体部署方法请参阅模型部署相关文档。
|
||||
|
||||
|
@ -458,8 +446,205 @@ network_binary.nb文件在"asymmetric_affine"文件夹中:
|
|||
## 3.7 使用实例
|
||||
|
||||
请参照quick_start.md。
|
||||
|
||||
# 4 netrans_py
|
||||
netrans_cli 脚本介绍
|
||||
|脚本|功能|使用|
|
||||
|:---|---|---|
|
||||
|import_model.py| 模型导入功能,将模型转换成 pnna 支持的格式| python import_model.py model_name|
|
||||
|inputmeta_gen.py| 预处理模版生成功能,生成预处理模版,根据模型进行对于的修改| python inputmeta_gen.py model_name|
|
||||
|quantize.py| 量化功能, 对模型进行量化生成量化参数文件| python quantize.sh model_name quantize_data_type|
|
||||
|quantize_hb.py| 混合量化功能, 对模型进行量化生成量化参数文件| python quantize.py model_name quantize_data_type|
|
||||
|infer.py| 推理保存输出的功能,对模型进行推理|python infer.py model_name quantize_data_type<br/>注意:该功能可用于测试模型精度,和开发板上推理结果大体一致|
|
||||
|dump.py| 推理保存每一层结果的功能,对模型进行推理|python dump.py model_name quantize_data_type<br/>注意:该功能可用于测试模型精度,和开发板上推理结果大体一致|
|
||||
|export.py|导出功能,将量化好的模型导出成 pnna 上可以运行的runtime| python export.py model_name quantize_data_type|
|
||||
|img2dat.py|图片数据转换成量化后的二进制文件。需要转换的图片名存放在dataset.txt中。需要实先进行 inputmeta 文件生成 和 模型量化。 | python img2dat.py model_name quantize_data_type|
|
||||
|
||||
**<font color="#dd0000">注意:</font>准备好数据的目录需要在**netrans_cli目录**下,且目录名和模型名需要保持一致。
|
||||
|
||||
比如导入一个TensorFlow的lenet模型,那么需要在<font color="#dd0000">netrans_cli文件夹</font>中新建一个"lenet"名字的文件夹,然后将模型名字命名为lenet.pb,并将其放入"lenet"文件夹中,如果有权重文件也需要这样处理。参数文件和数据集文件名字固定,但是也是需要放进同一个目录。
|
||||
|
||||
### 4.1 导入模型
|
||||
|
||||
在netrans_py目录下使用import_model.py脚本进行导入
|
||||
- 用法1:import_model.py 以模型文件名命名的模型数据文件夹,例如:
|
||||
```shell
|
||||
$ python import_model.py lenet
|
||||
```
|
||||
"lenet"是文件夹名,也作为模型名和权重文件名。导入会打印相关日志信息,成功后会打印SUCESS。导入后lenet文件夹应该有"lenet.json"和"lenet.data"文件:
|
||||
- 用法2:如果需要裁剪模型,则需要新建model_name_outputs.txt,然后在txt的第一行添加模型新的输出层的名称:prob_8则是修改后的输出,多个输出用空格间隔,然后再执行用法1即可。
|
||||
```shell
|
||||
$ cat lenet_outputs.txt
|
||||
prob_8
|
||||
```
|
||||
|
||||
|
||||
### 4.2 生成Inputmeta文件
|
||||
在netrans_py目录下使用inputmeta_gen.sh脚本生成inputmeta文件:
|
||||
- 用法: ./inputmeta_gen.sh 以模型文件名命名的模型数据文件夹,例如:
|
||||
```shell
|
||||
$ python inputmeta_gen.sh lenet
|
||||
```
|
||||
可以看到,最终生成的是*.yml文件,该文件用于为Netrans中间模型配置输入层数据集合。<b>Netrans中的量化、推理、导出和图片转dat的操作都需要用到这个文件。因此,此步骤不可跳过。</b>
|
||||
|
||||
Inputmeta.yml文件结构如下:
|
||||
```yaml
|
||||
%YAML 1.2
|
||||
---
|
||||
# !!!This file disallow TABs!!!
|
||||
# "category" allowed values: "image, undefined"
|
||||
# "database" allowed types: "H5FS, SQLITE, TEXT, LMDB, NPY, GENERATOR"
|
||||
# "tensor_name" only support in H5FS database
|
||||
# "preproc_type" allowed types:"IMAGE_RGB, IMAGE_RGB888_PLANAR, IMAGE_RGB888_PLANAR_SEP,
|
||||
IMAGE_I420,
|
||||
# IMAGE_NV12, IMAGE_YUV444, IMAGE_GRAY, IMAGE_BGRA, TENSOR"
|
||||
input_meta:
|
||||
databases:
|
||||
- path: dataset.txt
|
||||
type: TEXT
|
||||
ports:
|
||||
- lid: data_0
|
||||
category: image
|
||||
dtype: float32
|
||||
sparse: false
|
||||
tensor_name:
|
||||
layout: nhwc
|
||||
shape:
|
||||
- 50
|
||||
- 224
|
||||
- 224
|
||||
- 3
|
||||
preprocess:
|
||||
reverse_channel: false
|
||||
mean:
|
||||
- 103.94
|
||||
- 116.78
|
||||
- 123.67
|
||||
scale: 0.017
|
||||
preproc_node_params:
|
||||
preproc_type: IMAGE_RGB
|
||||
add_preproc_node: false
|
||||
preproc_perm:
|
||||
- 0
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
- lid: label_0
|
||||
redirect_to_output: true
|
||||
category: undefined
|
||||
tensor_name:
|
||||
dtype: float32
|
||||
shape:
|
||||
- 1
|
||||
- 1
|
||||
|
||||
```
|
||||
|
||||
上面示例文件的各个参数解释:
|
||||
|
||||
| 参数 | 说明 |
|
||||
| :--- | ---
|
||||
| input_meta | 预处理参数配置申明。 |
|
||||
| databases | 数据配置,包括设置 path、type 和 ports 。|
|
||||
| path | 数据集文件的相对(执行目录)或绝对路径。默认为 dataset.txt, 不建议修改。 |
|
||||
| type | 数据集文件格式,固定为TEXT。 |
|
||||
| ports | 指向网络中的输入或重定向的输入,目前只支持一个输入,如果网络存在多个输入,请与@ccyh联系。 |
|
||||
| lid | 输入层的lid |
|
||||
| category | 输入的类别。将此参数设置为以下值之一:image(图像输入)或 undefined(其他类型的输入)。 |
|
||||
| dtype | 输入张量的数据类型,用于将数据发送到 pnna 网络的输入端口。支持的数据类型包括 float32 和 quantized。 |
|
||||
| sparse | 指定网络张量是否以稀疏格式存在。将此参数设置为以下值之一:true(稀疏格式)或 false(压缩格式)。 |
|
||||
| tensor_name | 留空此参数 |
|
||||
| layout | 输入张量的格式,使用 nchw 用于 Caffe、Darknet、ONNX 和 PyTorch 模型。使用 nhwc 用于 TensorFlow、TensorFlow Lite 和 Keras 模型。 |
|
||||
| shape | 此张量的形状。第一维,shape[0],表示每批的输入数量,允许在一次推理操作之前将多个输入发送到网络。如果batch维度设置为0,则需要从命令行指定--batch-size。如果 batch维度设置为大于1的值,则直接使用inputmeta.yml中的batch size并忽略命令行中的--batch-size。 |
|
||||
| fitting | 保留字段 |
|
||||
| preprocess | 预处理步骤和顺序。预处理支持下面的四个键,键的顺序代表预处理的顺序。您可以相应地调整顺序。 |
|
||||
| reverse_channel | 指定是否保留通道顺序。将此参数设置为以下值之一:true(保留通道顺序)或 false(不保留通道顺序)。对于 TensorFlow 和 TensorFlow Lite 框架的模型使用 true。 |
|
||||
| mean | 用于每个通道的均值。 |
|
||||
| scale | 张量的缩放值。均值和缩放值用于根据公式 (inputTensor - mean) × scale 归一化输入张量。|
|
||||
| preproc_node_params | 预处理节点参数,在 OVxlib C 项目案例中启用预处理任务 |
|
||||
| add_preproc_node | 将数据前处理以及量化嵌入网络中。此参数仅在 add_preproc_node 参数设置为 true 时有效。|
|
||||
| preproc_type | 预处理节点输入类型。 [IMAGE_RGB, IMAGE_RGB888_PLANAR,IMAGE_YUV420, IMAGE_GRAY, IMAGE_BGRA, TENSOR] 中的字符串值 |
|
||||
| preproc_perm | 预处理节点输入的置换参数。 |
|
||||
| redirect_to_output | 将database张量重定向到图形输出的特殊属性。如果为该属性设置了一个port,网络构建器将自动为该port生成一个输出层,以便后处理文件可以直接处理来自database的张量。 如果使用网络进行分类,则上例中的lid“input_0”表示输入数据集的标签lid。 您可以设置其他名称来表示标签的lid。 请注意,redirect_to_output 必须设置为 true,以便后处理文件可以直接处理来自database的张量。 标签的lid必须与后处理文件中定义的 labels_tensor 的lid相同。 [true, false] 中的布尔值。 指定是否将由张量表示的输入端口的数据直接发送到网络输出。true(直接发送到网络输出)或 false(不直接发送到网络输出)|
|
||||
|
||||
可以根据实际情况对生成的inputmeta文件进行修改。
|
||||
|
||||
### 4.3 模型量化
|
||||
如果我们训练好的模型的数据类型是float32的,为了使模型以更高的效率在pnna上运行,我们可以对模型进行量化操作,量化操作可能会带来一定程度的精度损失。<
|
||||
在netrans_py目录下使用quantize.py脚本进行量化操作。
|
||||
|
||||
用法1:python quantize.sh 以模型文件名命名的模型数据文件夹 量化类型,例如:
|
||||
|
||||
```shell
|
||||
$ python quantize.sh lenet uint8
|
||||
```
|
||||
|
||||
支持的量化类型有:uint8、int8、int16
|
||||
|
||||
用法2:先执行python quantize.sh 以模型文件名命名的模型数据文件夹 量化类型;
|
||||
```shell
|
||||
$ python quantize.sh lenet uint8
|
||||
```
|
||||
uint8执行成功会生成lenet_asymmetric_affine.quantize.打开.quantize文件,
|
||||
在最后一行加入需要混合量化的节点名字和类型,如下所示:
|
||||
```shell
|
||||
$ customized_quantize_layers:
|
||||
stage1/rebnconvin/conv_s1/Conv_output_0_39: dynamic_fixed_point-i16
|
||||
input.1_378: dynamic_fixed_point-i16
|
||||
```
|
||||
最后执行python quantize_hb.sh 以模型文件名命名的模型数据文件夹 量化类型, 例如:
|
||||
|
||||
```shell
|
||||
$ python quantize_hb.sh lenet uint8
|
||||
```
|
||||
|
||||
混合量化支持的量化类型有:uint8
|
||||
### 4.4 模型推理
|
||||
|
||||
在netrans_py目录下使用infer.py、dump.py脚本进行推理
|
||||
|
||||
- 用法1:python infer.sh 以模型文件名命名的模型数据文件夹 数据类型,推理成功则会在inf目录下生成输入、
|
||||
输出的.tensor文件,例如:
|
||||
|
||||
```shell
|
||||
$ python infer.sh lenet uint8
|
||||
```
|
||||
- 用法2:python dump.py 以模型文件名命名的模型数据文件夹 数据类型,推理成功则会在inf目录下生成输入、
|
||||
每层的输出的.tensor文件,例如:
|
||||
|
||||
```shell
|
||||
$ python dump.py lenet uint8
|
||||
```
|
||||
推理支持的数据类型:float、uint8、int8、int16,其中使用uint8、int8、int16推理时需要先进行模型量化。
|
||||
|
||||
### 4.5 模型导出
|
||||
|
||||
在netrans_py目录下使用export.sh脚本进行推理。
|
||||
|
||||
用法1:python export.py 以模型文件名命名的模型数据文件夹 数据类型,例如:
|
||||
```shell
|
||||
python export.py lenet uint8
|
||||
```
|
||||
用法2:如果需要将反量化嵌入网络中,则需新建model_name_postprocess_file.yml.如下所示
|
||||
再执行用法1。
|
||||
```shell
|
||||
postprocess:
|
||||
app_postprocs:
|
||||
- lid: attach_1837/out0_0 #输出节点名1
|
||||
postproc_params:
|
||||
add_postproc_node: true
|
||||
force_float32: true
|
||||
- lid: attach_1837/out0_0 #输出节点名2
|
||||
postproc_params:
|
||||
add_postproc_node: true
|
||||
force_float32: true
|
||||
```
|
||||
导出支持的数据类型:float、uint8、int8、int16,其中使用uint8、int8、int16导出时需要先进行[模型量化](#33-模型量化)。导出的工程会在模型所在的目录下面的wksp目录里。
|
||||
network_binary.nb文件在"asymmetric_affine"文件夹中:
|
||||
|
||||
目前支持将生成的network_binary.nb文件部署到pnna硬件平台。具体部署方法请参阅模型部署相关文档。
|
||||
|
||||
|
||||
# 5 netrans_api
|
||||
netrans_py 支持通过 python api 灵活地将模型转换成pnna 支持的格式。
|
||||
ntrans_py 支持以下功能:
|
||||
- 导入并转换模型为 pnna 支持的格式
|
||||
|
@ -470,20 +655,19 @@ ntrans_py 支持以下功能:
|
|||
|
||||
在使用netrans_py之前。需要安装netrans,具体请参考 [安装说明](#21-安装)
|
||||
|
||||
## 4.1 创建 Netrans
|
||||
## 5.1 创建 Netrans
|
||||
|
||||
描述: 实例化 Netrans 类。
|
||||
代码示例:
|
||||
|
||||
```python3
|
||||
import sys
|
||||
sys.path.append("netrans_py")
|
||||
from netrans import Netrans
|
||||
yolo_netrans = Netrans("../../models/yolov4_tiny")
|
||||
```
|
||||
```python3
|
||||
import sys
|
||||
sys.path.append("netrans_py")
|
||||
from netrans import Netrans
|
||||
yolo_netrans = Netrans("../../models/yolov4_tiny")
|
||||
```
|
||||
|
||||
参数
|
||||
|
||||
| 参数名 | 类型 | 说明 |
|
||||
|:---| -- | -- |
|
||||
|model_path| str| 第一位置参数,模型文件的路径|
|
||||
|
@ -494,7 +678,7 @@ ntrans_py 支持以下功能:
|
|||
|
||||
**<font color="#dd0000">注意:</font>模型目录准备需要和netrans_cli一致**,具体数据准备要求见[2.3数据准备](#23-数据准备)。
|
||||
|
||||
## 4.2 模型导入 load_model
|
||||
## 5.2 模型导入 load_model
|
||||
|
||||
描述: 将模型转换成 pnna 支持的格式。
|
||||
代码示例:
|
||||
|
@ -510,7 +694,7 @@ ntrans_py 支持以下功能:
|
|||
无。
|
||||
在工程目录下生成 pnna 支持的模型格式,以.json结尾的模型文件和 .data结尾的权重文件。
|
||||
|
||||
## 4.3 预处理配置文件生成 inputmeta_gen
|
||||
## 5.3 预处理配置文件生成 inputmeta_gen
|
||||
|
||||
描述: 将模型转换成 pnna 支持的格式。
|
||||
代码示例:
|
||||
|
@ -525,7 +709,7 @@ ntrans_py 支持以下功能:
|
|||
输出返回:
|
||||
无。
|
||||
|
||||
## 4.4 量化模型 quantize
|
||||
## 5.4 量化模型 quantize
|
||||
|
||||
描述: 对模型生成量化配置文件。
|
||||
代码示例:
|
||||
|
@ -535,7 +719,6 @@ ntrans_py 支持以下功能:
|
|||
```
|
||||
|
||||
参数:
|
||||
|
||||
| 参数名 | 类型 | 说明 |
|
||||
|:---| -- | -- |
|
||||
|quantize_type| str| 第一位置参数,模型量化类型,仅支持 "uint8", "int8", "int16"|
|
||||
|
@ -543,7 +726,7 @@ ntrans_py 支持以下功能:
|
|||
输出返回:
|
||||
无。
|
||||
|
||||
## 4.5 模型导出 export
|
||||
## 5.5 模型导出 export
|
||||
|
||||
描述: 对模型生成量化配置文件。
|
||||
代码示例:
|
||||
|
@ -558,7 +741,7 @@ ntrans_py 支持以下功能:
|
|||
输出返回:
|
||||
无。请在目录 “wksp/*/” 下检查是否生成nbg文件。
|
||||
|
||||
## 4.6 model2nbg
|
||||
## 5.6 model2nbg
|
||||
|
||||
描述: 模型导入、量化、及nbg文件生产
|
||||
代码示例:
|
||||
|
@ -576,7 +759,6 @@ yolo_netrans.model2nbg(quantize_type='uint8', inputmeta=True)
|
|||
```
|
||||
|
||||
参数
|
||||
|
||||
| 参数名 | 类型 | 说明 |
|
||||
|:---| -- | -- |
|
||||
|quantize_type| str, ["uint8", "int8", "int16" ] | 量化类型,将模型量化成该参数指定的类型 |
|
||||
|
@ -589,7 +771,7 @@ yolo_netrans.model2nbg(quantize_type='uint8', inputmeta=True)
|
|||
输出返回:
|
||||
请在目录 “wksp/*/” 下检查是否生成nbg文件。
|
||||
|
||||
## 4.7 use case
|
||||
## 5.7 use case
|
||||
|
||||
```python3
|
||||
import sys
|
||||
|
@ -615,9 +797,8 @@ net.export()
|
|||
net.model2nbg(quantize_type = "int16", inputmeta=True)
|
||||
```
|
||||
|
||||
# 5算子支持情况
|
||||
## 5.1支持的Caffe算子
|
||||
|
||||
# 6算子支持情况
|
||||
## 6.1支持的Caffe算子
|
||||
| | | |
|
||||
|:---| -- | -- |
|
||||
absval | innerproduct | reorg
|
||||
|
@ -634,8 +815,7 @@ eltwise | priorbox | sigmoid
|
|||
flatten | proposal | tanh
|
||||
|
||||
|
||||
## 5.2支持的TensorFlow算子
|
||||
|
||||
## 6.2支持的TensorFlow算子
|
||||
| | | |
|
||||
|:---| -- | -- |
|
||||
tf.abs | tf.nn.rnn_cell_GRUCell | tf.negative
|
||||
|
@ -671,8 +851,7 @@ tf.gather | tf.batch_matmul | tf.where
|
|||
tf.nn.embedding_lookup | tf.not_equal | tf.select
|
||||
|
||||
|
||||
## 5.3支持的TFLite算子
|
||||
|
||||
## 6.3支持的TFLite算子
|
||||
| | | |
|
||||
|:---| -- | -- |
|
||||
ADD | LOGICAL_OR | RELU1
|
||||
|
@ -702,9 +881,7 @@ GATHER | RSQRT | UNIDIRECTIONAL_SEQUEENC
|
|||
GREATER | REDUCE_MAX | E_LSTM
|
||||
GREATER_EQUAL | RELU | WHERE
|
||||
HARD_SWISH | | |
|
||||
|
||||
## 5.4支持的ONNX算子
|
||||
|
||||
## 6.4支持的ONNX算子
|
||||
| | | |
|
||||
|:---| -- | -- |
|
||||
ArgMin | LeakyRelu | ReverseSequence
|
||||
|
@ -738,8 +915,7 @@ LRN | ReduceSum | Xor
|
|||
Log | ReduceMean | |
|
||||
|
||||
|
||||
## 5.5支持的Darknet算子
|
||||
|
||||
## 6.5支持的Darknet算子
|
||||
| | | |
|
||||
|:---| -- | -- |
|
||||
avgpool | maxpool | softmax
|
||||
|
@ -750,8 +926,7 @@ depthwise_convolutional | relu | upsample
|
|||
leaky | route | yolo
|
||||
logistic
|
||||
|
||||
## 5.6支持的Keras算子
|
||||
|
||||
## 6.6支持的Keras算子
|
||||
| | | |
|
||||
|:---| -- | -- |
|
||||
Add | DepthwiseConv2D | GlobalMaxPooling2D
|
||||
|
|
|
@ -63,19 +63,33 @@ class Export(AttributeCopier):
|
|||
if not os.path.exists(f"{name}_{quantization_type}.quantize"):
|
||||
print(f"\033[31m Can not find {name}_{quantization_type}.quantize \033[0m")
|
||||
sys.exit(1)
|
||||
cmd = f"{ovxgenerator} \
|
||||
if not os.path.exists(f"{name}_postprocess_file.yml"):
|
||||
cmd = f"{ovxgenerator} \
|
||||
--model {name}.json \
|
||||
--model-data {name}.data \
|
||||
--model-quantize {name}.quantize \
|
||||
--dtype {type_} \
|
||||
--pack-nbg-viplite \
|
||||
--optimize 'VIP8000NANOQI_PLUS_PID0XB1'\
|
||||
--viv-sdk {netrans_path}/pnna_sdk \
|
||||
--model-quantize {name}_{quantization_type}.quantize \
|
||||
--with-input-meta {name}_inputmeta.yml \
|
||||
--optimize 'VIP8000NANOQI_PLUS_PID0XB1'\
|
||||
--target-ide-project 'linux64' \
|
||||
--output-path {generate_path}/{quantization_type}"
|
||||
else:
|
||||
cmd = f"{ovxgenerator} \
|
||||
--model {name}.json \
|
||||
--model-data {name}.data \
|
||||
--dtype {type_} \
|
||||
--pack-nbg-viplite \
|
||||
--optimize 'VIP8000NANOQI_PLUS_PID0XB1'\
|
||||
--viv-sdk {netrans_path}/pnna_sdk \
|
||||
--output-path {generate_path}/{name}_{quantization_type}"
|
||||
|
||||
--model-quantize {name}_{quantization_type}.quantize \
|
||||
--with-input-meta {name}_inputmeta.yml \
|
||||
--target-ide-project 'linux64' \
|
||||
--postprocess-file {name}_postprocess_file.yml \
|
||||
--output-path {generate_path}/{quantization_type}"
|
||||
|
||||
|
||||
# 执行命令
|
||||
# print(cmd)
|
||||
result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
|
||||
|
@ -124,12 +138,13 @@ def main():
|
|||
|
||||
netrans_path = os.environ['NETRANS_PATH']
|
||||
# netrans = os.path.join(os.environ['NETRANS_PATH'], 'pnnacc')
|
||||
# 调用导出函数
|
||||
# 调用导出函数ss
|
||||
cla = creat_cla(netrans_path, network_name, sys.argv[2])
|
||||
func = Export(cla)
|
||||
func.export_network()
|
||||
|
||||
# export_network(netrans, network_name, sys.argv[2])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
main()
|
||||
|
|
|
@ -73,9 +73,18 @@ def import_onnx_network(name, netrans_path):
|
|||
|
||||
# 打印转换信息
|
||||
print(f"=========== Converting {name} ONNX model ===========")
|
||||
|
||||
# 构建转换命令
|
||||
cmd = f"{convert_onnx_cmd} \
|
||||
if os.path.exists(f"{name}_outputs.txt"):
|
||||
output_path = os.path.join(os.getcwd(), name+"_outputs.txt")
|
||||
with open(output_path, 'r', encoding='utf-8') as file:
|
||||
outputs = str(file.readline().strip())
|
||||
cmd = f"{convert_onnx_cmd} \
|
||||
--model {name}.onnx \
|
||||
--output-model {name}.json \
|
||||
--output-data {name}.data \
|
||||
--outputs '{outputs}'"
|
||||
else:
|
||||
# 构建转换命令
|
||||
cmd = f"{convert_onnx_cmd} \
|
||||
--model {name}.onnx \
|
||||
--output-model {name}.json \
|
||||
--output-data {name}.data"
|
||||
|
@ -179,8 +188,7 @@ class ImportModel(AttributeCopier):
|
|||
print(os.getcwd())
|
||||
print(f"{self.model_name}.weights")
|
||||
name = self.model_name
|
||||
netrans_path = self.netrans
|
||||
|
||||
netrans_path = self.netrans
|
||||
if os.path.isfile(f"{name}.prototxt"):
|
||||
import_caffe_network(name, netrans_path)
|
||||
elif os.path.isfile(f"{name}.pb"):
|
||||
|
@ -199,7 +207,7 @@ class ImportModel(AttributeCopier):
|
|||
sys.exit(-3)
|
||||
# os.chdir("..")
|
||||
|
||||
|
||||
|
||||
def main():
|
||||
if len(sys.argv) != 2 :
|
||||
print("Input a network")
|
||||
|
@ -213,6 +221,5 @@ def main():
|
|||
clas = creat_cla(netrans_path, network_name,verbose=False)
|
||||
func = ImportModel(clas)
|
||||
func.import_network()
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
main()
|
||||
|
|
|
@ -27,11 +27,15 @@ class Quantize(AttributeCopier):
|
|||
else:
|
||||
print("=========== wrong quantization_type ! ( uint8 / int8 / int16 )===========")
|
||||
return
|
||||
|
||||
|
||||
# 输出量化信息
|
||||
print(" =======================================================================")
|
||||
print(f" ==== Start Quantizing {name} model with type of {quantization_type} ===")
|
||||
print(" =======================================================================")
|
||||
current_directory = os.getcwd()
|
||||
txt_path = current_directory+"/dataset.txt"
|
||||
with open(txt_path, 'r', encoding='utf-8') as file:
|
||||
num_lines = len(file.readlines())
|
||||
|
||||
# 移除已存在的量化文件
|
||||
quantize_file = f"{name}_{quantization_type}.quantize"
|
||||
|
@ -49,7 +53,9 @@ class Quantize(AttributeCopier):
|
|||
--model {name}.json \
|
||||
--model-data {name}.data \
|
||||
--with-input-meta {name}_inputmeta.yml \
|
||||
--device CPU"
|
||||
--device CPU \
|
||||
--algorithm kl_divergence \
|
||||
--iterations {num_lines}"
|
||||
|
||||
os.system(cmd)
|
||||
|
||||
|
@ -84,4 +90,4 @@ def main():
|
|||
run.quantize_network()
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
main()
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
import os
|
||||
import sys
|
||||
from utils import check_path, AttributeCopier, creat_cla
|
||||
|
||||
class Quantize(AttributeCopier):
|
||||
def __init__(self, source_obj) -> None:
|
||||
super().__init__(source_obj)
|
||||
|
||||
@check_path
|
||||
def quantize_network(self):
|
||||
netrans = self.netrans
|
||||
quantized_type = self.quantize_type
|
||||
name = self.model_name
|
||||
# check_env(name)
|
||||
# print(os.getcwd())
|
||||
netrans += " quantize"
|
||||
# 根据量化类型设置量化参数
|
||||
if quantized_type == 'float':
|
||||
print("=========== do not need quantized===========")
|
||||
return
|
||||
elif quantized_type == 'uint8':
|
||||
quantization_type = "asymmetric_affine"
|
||||
elif quantized_type == 'int8':
|
||||
quantization_type = "dynamic_fixed_point-8"
|
||||
elif quantized_type == 'int16':
|
||||
quantization_type = "dynamic_fixed_point-16"
|
||||
else:
|
||||
print("=========== wrong quantization_type ! ( uint8 / int8 / int16 )===========")
|
||||
return
|
||||
|
||||
# 输出量化信息
|
||||
print(" =======================================================================")
|
||||
print(f" ==== Start Quantizing {name} model with type of {quantization_type} ===")
|
||||
print(" =======================================================================")
|
||||
|
||||
# 移除已存在的量化文件
|
||||
quantize_file = f"{name}_{quantization_type}.quantize"
|
||||
current_directory = os.getcwd()
|
||||
txt_path = current_directory+"/dataset.txt"
|
||||
with open(txt_path, 'r', encoding='utf-8') as file:
|
||||
num_lines = len(file.readlines())
|
||||
|
||||
|
||||
# 构建并执行量化命令
|
||||
cmd = f"{netrans} \
|
||||
--qtype {quantized_type} \
|
||||
--hybrid \
|
||||
--quantizer {quantization_type.split('-')[0]} \
|
||||
--model-quantize {quantize_file} \
|
||||
--model {name}.json \
|
||||
--model-data {name}.data \
|
||||
--with-input-meta {name}_inputmeta.yml \
|
||||
--device CPU \
|
||||
--algorithm kl_divergence \
|
||||
--divergence-nbins 2048 \
|
||||
--iterations {num_lines}"
|
||||
|
||||
os.system(cmd)
|
||||
|
||||
# 检查量化结果
|
||||
if os.path.exists(quantize_file):
|
||||
print("\033[31m QUANTIZED SUCCESS \033[0m")
|
||||
else:
|
||||
print("\033[31m ERROR ! \033[0m")
|
||||
|
||||
|
||||
def main():
|
||||
# 检查命令行参数数量
|
||||
if len(sys.argv) < 3:
|
||||
print("Input a network name and quantized type ( uint8 / int8 / int16 )")
|
||||
sys.exit(-1)
|
||||
|
||||
# 检查网络目录是否存在
|
||||
network_name = sys.argv[1]
|
||||
|
||||
# 定义 netrans 路径
|
||||
# netrans = os.path.join(os.environ['NETRANS_PATH'], 'pnnacc')
|
||||
# network_name = sys.argv[1]
|
||||
# check_env(network_name)
|
||||
|
||||
netrans_path = os.environ['NETRANS_PATH']
|
||||
# netrans = os.path.join(netrans_path, 'pnnacc')
|
||||
quantize_type = sys.argv[2]
|
||||
cla = creat_cla(netrans_path, network_name,quantize_type)
|
||||
|
||||
# 调用量化函数
|
||||
run = Quantize(cla)
|
||||
run.quantize_network()
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
Loading…
Reference in New Issue