Netrans Cookbook - 实用指南
本文档提供 Netrans 的速查表、配置说明、场景示例和故障排查。
目录
快速开始
安装指南
1# 克隆仓库并创建 Python 3.10 环境后,在源码根目录执行
2make install
3source ~/.bashrc
请使用项目提供的 Makefile 完成安装;在源码根目录执行 make install 即可安装 Netrans 及所需组件。环境创建和日常更新步骤见本项目的介绍与安装页(仓库中为 README.md)。
基础转换流程
1# 1. 加载模型
2netrans load ./model --mean 0 0 0 --std 255
3
4# 2. 量化
5netrans quantize ./model asymu8 --algorithm 1 --iterations 1
6
7# 3. 导出
8netrans export ./model asymu8 --platform pnna
Python API 完整流程
from netrans import Netrans
model = Netrans()
model.load('./model', mean=[0, 0, 0], std=255)
model.quantize('asymu8')
model.export('asymu8', platform='pnna', preprocess=True, postprocess=True)
速查表
量化类型
类型 |
激活 |
权重 |
说明 |
|---|---|---|---|
|
uint8 |
uint8 |
非对称8位 |
|
int8 |
int8 |
对称8位 |
|
int16 |
int16 |
对称16位 |
|
int16 |
int16 |
动态定点16位 |
|
float16 |
float16 |
半精度浮点 |
注意事项:
FP16: 支持将预处理和后处理嵌入推理计算图
symi16: 不支持将预处理嵌入推理节点,导出时需设置
preprocess=False,或改用dfpi16
量化算法
值 |
算法 |
说明 |
适用场景 |
|---|---|---|---|
|
normal |
直接统计 min/max |
快速测试 |
|
KL |
KL散度(推荐) |
平衡精度和速度 |
|
moving_average |
移动平均 |
动态范围大的数据 |
|
auto |
自动选择 |
最高精度,最慢 |
预处理参数
自动广播
mean/std 参数支持自动广播,无需手动填写所有通道值:
# 显式指定每个通道
model.load('./model', mean=[128, 128, 128], std=[255, 255, 255])
# 使用自动广播
model.load('./model', mean=128, std=255) # 单值自动广播到所有通道
model.load('./model', mean=[128], std=[255]) # 单元素列表也自动广播
model.load('./model', mean=[128, 128, 128], std=255) # std 单值广播
广播规则:
单值(如
mean=128)→ 自动广播到所有通道单元素列表(如
mean=[128])→ 自动广播到所有通道多值列表(如
mean=[128, 128, 128])→ 原样使用,长度必须匹配通道数
常见模型的 mean/std 配置:
模型 |
mean |
std |
说明 |
|---|---|---|---|
YOLOv5/v8 |
|
|
归一化到 [0,1] |
ResNet/ImageNet |
|
|
ImageNet 统计值 |
MobileNet |
|
|
归一化到 [-1,1] |
自定义 |
根据训练配置 |
根据训练配置 |
与训练时一致 |
std 是归一化除数;生成的 _inputmeta.yml 固定使用 scale 字段,其值为 1 / std。
平台与多核
平台 |
多核支持 |
说明 |
|---|---|---|
|
不支持 |
默认平台,单核架构 |
|
支持 1-4 核 |
多核架构 |
多核配置(仅 pnna2):
配置值 |
说明 |
|---|---|
|
单核模式 |
|
双核模式 |
|
三核模式 |
|
四核模式 |
数据集格式
Netrans 量化支持以下数据集格式用于校准:
1. 文本列表 (.txt)
每行一个图像路径:
/path/to/image1.jpg
/path/to/image2.jpg
/path/to/image3.jpg
2. NumPy 数组 (.npy)
预处理后的数组数据,形状为 [N, C, H, W]。
注意:使用 .npy 作为输入时,Netrans 不会触发预处理(mean/std 等操作),请确保数组数据已经完成预处理。
3. 自动生成(默认)
当未提供数据集时,Netrans 会自动生成随机数据用于量化。
注意:随机数据会影响量化精度,生产环境建议使用真实数据。
导入格式兼容性
格式 |
支持版本/说明 |
|---|---|
ONNX |
opset 7-17(ONNX 1.2-1.12) |
TensorFlow |
1.4.x, 2.0.x, 2.3.x, 2.6.x, 2.8.x, 2.10.x, 2.12.x, 2.15.x |
TFLite |
schema 2.15.0(TensorFlow 2.15.0) |
PyTorch |
1.5.1-2.2.2( |
Caffe |
标准协议及部分扩展协议,具体取决于模型层和算子 |
Darknet |
标准模型,具体取决于模型层和算子 |
Keras |
TensorFlow 2.0.x - 2.15.x 生成的模型 |
配置字段说明
_inputmeta.yml 重点字段
1input_meta:
2 databases:
3 - ports:
4 - lid: input_0 # 输入层 ID
5 shape: [1, 3, 640, 640] # [batch, channels, height, width]
6 preprocess:
7 mean: [0, 0, 0] # 通道均值
8 scale: [0.00392, 0.00392, 0.00392] # 缩放系数
9 preproc_node_params:
10 add_preproc_node: true # 是否嵌入预处理节点到网络
11 preproc_dtype_converter: # 数据类型转换(定点量化时)
12 qtype: uint8
13 quantizer: asymmetric_affine
14 scale: 0.965
15 zero_point: 0
关键字段:
mean: 与load()的mean对应;scale是_inputmeta.yml的固定字段,值为1 / std,不是load()的参数名add_preproc_node: 设为true将预处理嵌入网络图preproc_dtype_converter: 定点量化时的输入数据类型转换
_postprocess_file.yml 重点字段
1app_postprocs:
2 - lid: output_0 # 输出层 ID
3 postproc_params:
4 add_postproc_node: true # 是否嵌入后处理节点
5 force_float32: true # 强制输出为 float32
关键字段:
add_postproc_node: 设为true将反量化等后处理嵌入网络图force_float32: 强制输出数据类型为 float32
场景示例
场景1:YOLOv5s 完整转换
#!/usr/bin/env python3
"""YOLOv5s 模型转换完整示例"""
from netrans import Netrans
model = Netrans()
model.load('./yolov5s', mean=[0, 0, 0], std=255)
model.quantize('asymu8', algorithm=1)
model.export('asymu8', platform='pnna', preprocess=True, postprocess=True)
print("✅ 转换完成: wksp/yolov5s_asymu8_nbg_unify/network_binary.nb")
场景2:ResNet50 ImageNet 模型
#!/usr/bin/env python3
"""ResNet50 ImageNet 模型转换"""
from netrans import Netrans
model = Netrans()
model.load(
'./resnet50',
mean=[123.675, 116.28, 103.53],
std=[58.395, 57.12, 57.375]
)
model.quantize('asymu8', algorithm=1, iterations=5)
model.export('asymu8', platform='pnna')
场景3:混合量化
#!/usr/bin/env python3
"""YOLO 模型混合量化 - 检测头高精度"""
from netrans import Netrans
import os
model_dir = './yolov5s'
model = Netrans()
model.load(model_dir, mean=[0, 0, 0], std=255)
# 创建混合量化配置
config_file = os.path.join(model_dir, 'cust_qnt_layers.txt')
with open(config_file, 'w') as f:
f.write('Conv_245\nConv_269\nConv_293\n')
model.quantize_hybrid('asymu8', cust_qnt_layers=config_file)
model.export('asymu8', platform='pnna', use_hybrid=True)
场景4:PNNA2 多核导出
#!/usr/bin/env python3
"""PNNA2 平台 4 核导出"""
from netrans import Netrans
model = Netrans()
model.load('./model', mean=[0, 0, 0], std=255)
model.quantize('asymu8')
model.export('asymu8', platform='pnna2', core_num='4core')
场景5:批量转换
1#!/bin/bash
2MODELS=("yolov5s" "yolov5m" "yolov5l")
3
4for model in "${MODELS[@]}"; do
5 echo "=== 转换 $model ==="
6 netrans load ./$model --mean 0 0 0 --std 255
7 netrans quantize ./$model asymu8 --algorithm 1
8 netrans export ./$model asymu8 --platform pnna
9 echo "✅ $model 完成"
10done
场景6:精度验证
#!/usr/bin/env python3
"""精度验证 - 对比浮点和量化模型"""
from netrans import Netrans
model = Netrans()
model.load('./model', mean=[0, 0, 0], std=255)
# 浮点推理
model.inference('float32', iterations=1)
# 量化并推理
model.quantize('asymu8')
model.inference('asymu8', iterations=1)
# 对比 golden 目录输出
# wksp/model_float32/golden/ vs wksp/model_asymu8/golden/
场景7:复用 json/data 多量化类型导出
#!/usr/bin/env python3
"""一次 load,多量化类型连续导出"""
from netrans import Netrans
model = Netrans()
model.load('./model', mean=[0, 0, 0], std=255)
# 同一实例上连续量化不同类型 — 安全,无需反复 load
for qtype in ['asymu8', 'symi8', 'fp16']:
model.quantize(qtype)
model.export(qtype, platform='pnna')
# 原因: nn.quantize(net, rebuild=True) 会重建网络,
# 输入 net 是否已被上一次量化不影响最终结果。
# 经验证,此方式与"每次重新 load"产生的 NBG 大小完全一致。
场景8:自定义层量化类型(set_ioq)
lid + in_out_quantized 参数组合允许为模型的输入/输出层指定与主体不同的量化类型。这在以下场景中很有用:
输入层需要更高精度以保留细节(如
dfpi16)需要验证不同 ioq 类型对精度的影响
#!/usr/bin/env python3
"""为特定输入/输出层指定不同的量化类型"""
from netrans import Netrans
model = Netrans()
model.load('./model', mean=[0, 0, 0], std=255)
# 全模型 asymu8,但输入层 input_0 使用 dfpi16(更高精度)
model.quantize('asymu8', lid='input_0', in_out_quantized='dfpi16')
model.export('asymu8', platform='pnna')
# 同时指定多个层,逗号分隔
model.quantize('asymu8', lid='input_0,output_0', in_out_quantized='symi16')
model.export('asymu8', platform='pnna')
注意事项:
lid和in_out_quantized必须同时使用,单独指定其中之一不会生效层名可以通过
netrans dump查看各层名称多输入模型 + 有符号整数(symi8/symi16)+
in_out_quantized+preprocess=True可能触发 SDK 报 Error 65280,这是 SDK 侧限制
场景9:计算模型计算量
#!/usr/bin/env python3
"""统计模型 FLOPs 和参数量"""
from netrans import Netrans
model = Netrans()
model.load('./yolov5s', mean=0, std=255)
# 浮点模型计算量
model.measure('float32')
# 输出:wksp/yolov5s_float32/
# 量化后模型计算量
model.quantize('asymu8')
model.measure('asymu8')
# 输出:wksp/yolov5s_asymu8/
# Hybrid 量化模型计算量
model.quantize_hybrid('asymu8', cust_qnt_layers='layers.txt')
model.measure('asymu8', use_hybrid=True)
# 输出:wksp/yolov5s_asymu8_hy/
1# CLI 方式
2netrans measure ./yolov5s float32
3netrans measure ./yolov5s asymu8
4netrans measure ./yolov5s asymu8 --use-hybrid
quant_type 省略时默认为 float32。非 float32 模式需要先生成对应的 .quantize 文件;Hybrid 模式需要先完成 quantize_hybrid 并同时指定 --use-hybrid。输出位于模型目录下的 wksp/<model>_<quant_type>/(Hybrid 为 wksp/<model>_<quant_type>_hy/)。
场景10:多输入模型转换
多输入模型(如双分支网络、Siamese 网络等)的转换流程与单输入基本一致,关键差异在于 dataset.txt 格式和 channel_mean_value.txt 配置。
#!/usr/bin/env python3
"""多输入 Caffe 模型转换"""
from netrans import Netrans
model = Netrans()
model.load('./multi_input', mean=[0, 0, 0], std=1.0)
model.quantize('asymu8')
model.add_pre_post('asymu8', preprocess=True, postprocess=True)
model.export('asymu8')
1# CLI 方式
2netrans load ./multi_input --mean 0 0 0 --std 1.0
3netrans quantize ./multi_input asymu8
4netrans add_pre_post ./multi_input asymu8 --preprocess --postprocess
5netrans export ./multi_input asymu8
多输入关键点:
要点 |
说明 |
|---|---|
|
每个输入端口单独一个文件( |
|
当前只接受一组共享的 |
|
多输出时用 |
前后处理节点嵌入 |
同时作用于所有输入/输出端口 |
|
多输入模型 + 有符号整数 + ioq=Y + pre=T 可能触发 SDK Error 65280 |
故障排查
错误速查表
错误信息 |
可能原因 |
解决方案 |
|---|---|---|
|
未执行 quantize 或类型不匹配 |
执行 |
|
hybrid 层名不匹配 |
使用 |
模型性能分析需求 |
需要统计 FLOPs/参数量 |
使用 |
NBG 文件大小异常 |
量化未生效 |
确保 |
预处理参数不生效 |
配置未正确加载 |
检查 |
问题1: NBG 文件大小异常
症状: 量化后的 NBG 文件大小与浮点模型相近
原因: Python API 使用时未更新网络对象,或重新加载了浮点模型
解决:
# ✅ 正确流程
model.quantize('asymu8') # 量化
model.export('asymu8') # 导出(使用同一实例)
# ❌ 错误:不要重新创建实例
model1 = Netrans()
model1.load('./model')
model1.quantize('asymu8')
model2 = Netrans() # 新实例!
model2.load('./model') # 加载的是浮点模型
model2.export('asymu8') # 导出的是浮点 NBG
问题2: 预处理参数不生效
症状: 模型输出与预期不符
排查步骤:
1# 1. 检查 channel_mean_value.txt 格式
2cat channel_mean_value.txt
3# 应该是: "mean1 mean2 mean3 std"
4
5# 2. 检查 _inputmeta.yml
6cat *_inputmeta.yml | grep -A 10 "preprocess:"
7
8# 3. 确认 add_preproc_node 设置
9grep "add_preproc_node" *_inputmeta.yml