9.8 KiB
9.8 KiB
Netrans Cookbook - 实用指南
本文档提供 Netrans 的速查表、配置说明、场景示例和故障排查。
目录
快速开始
安装指南
pip install netrans
基础转换流程
# 1. 加载模型
netrans load ./model --mean 0 0 0 --scale 255
# 2. 量化
netrans quantize ./model asymu8 --algorithm 1 --iterations 1
# 3. 导出
netrans export ./model asymu8 --platform pnna
Python API 完整流程
from netrans import Netrans
model = Netrans()
model.load('./model', mean=[0, 0, 0], scale=255)
model.quantize('asymu8')
model.export('asymu8', platform='pnna', preprocess=True, postprocess=True)
速查表
量化类型
| 类型 | 激活 | 权重 | 说明 |
|---|---|---|---|
asymu8 |
uint8 | uint8 | 非对称8位 |
symi8 |
int8 | int8 | 对称8位 |
symi16 |
int16 | int16 | 对称16位 |
dfpi16 |
int16 | int16 | 动态定点16位 |
fp16 |
float16 | float16 | 半精度浮点 |
注意事项:
- FP16: v6.33.4+ 支持将预处理和后处理嵌入推理计算图
- symi16: 不支持将预处理嵌入推理节点,导出时需设置
preprocess=False,或改用dfpi16
量化算法
| 值 | 算法 | 说明 | 适用场景 |
|---|---|---|---|
0 |
normal | 直接统计 min/max | 快速测试 |
1 |
KL | KL散度(推荐) | 平衡精度和速度 |
2 |
moving_average | 移动平均 | 动态范围大的数据 |
3 |
auto | 自动选择 | 最高精度,最慢 |
预处理参数
v6.33.4 新增:自动广播功能
mean/scale 参数支持自动广播,无需手动填写所有通道值:
# 以前:必须写全所有通道
model.load('./model', mean=[128, 128, 128], scale=[255, 255, 255])
# 现在:自动广播(推荐)
model.load('./model', mean=128, scale=255) # 单值自动广播到所有通道
model.load('./model', mean=[128], scale=[255]) # 单元素列表也自动广播
model.load('./model', mean=[128, 128, 128], scale=255) # scale 单值广播
广播规则:
- 单值(如
mean=128)→ 自动广播到所有通道 - 单元素列表(如
mean=[128])→ 自动广播到所有通道 - 多值列表(如
mean=[128, 128, 128])→ 原样使用,长度必须匹配通道数
常见模型的 mean/scale 配置:
| 模型 | mean | scale | 说明 |
|---|---|---|---|
| YOLOv5/v8 | 0 或 [0, 0, 0] |
255 |
归一化到 [0,1] |
| ResNet/ImageNet | [123.675, 116.28, 103.53] |
[58.395, 57.12, 57.375] |
ImageNet 统计值 |
| MobileNet | 127.5 |
127.5 |
归一化到 [-1,1] |
| 自定义 | 根据训练配置 | 根据训练配置 | 与训练时一致 |
平台与多核
| 平台 | 多核支持 | 说明 |
|---|---|---|
pnna |
❌ 不支持 | 默认平台,单核架构 |
pnna2 |
✅ 支持 1-4 核 | 多核架构,需 viv-sdk |
多核配置(仅 pnna2):
| 配置值 | VIV_OVX_MULTI_DEVICES | 说明 |
|---|---|---|
1core / 1 |
0:1 |
单核模式 |
2core / 2 |
0:2-2 |
双核模式 |
3core / 3 |
0:3-1 |
三核模式 |
4core / 4 |
0:4-1 |
四核模式 |
数据集格式
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/scale 等操作),请确保数组数据已经完成预处理。
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 | 2.2.2+(通过 ONNX 后端导入) |
| Caffe | standard 和 non-standard 协议 |
| Darknet | https://pjreddie.com/darknet/ 列出的模型 |
| Keras | TensorFlow 2.0.x - 2.15.x 生成的模型 |
配置字段说明
_inputmeta.yml 重点字段
input_meta:
databases:
- ports:
- lid: input_0 # 输入层 ID
shape: [1, 3, 640, 640] # [batch, channels, height, width]
preprocess:
mean: [0, 0, 0] # 通道均值
scale: [0.00392, 0.00392, 0.00392] # 缩放系数
preproc_node_params:
add_preproc_node: true # 是否嵌入预处理节点到网络
preproc_dtype_converter: # 数据类型转换(定点量化时)
qtype: uint8
quantizer: asymmetric_affine
scale: 0.965
zero_point: 0
关键字段:
mean/scale: 预处理参数,与load()时传入的值对应add_preproc_node: 设为true将预处理嵌入网络图preproc_dtype_converter: 定点量化时的输入数据类型转换
_postprocess_file.yml 重点字段
app_postprocs:
- lid: output_0 # 输出层 ID
postproc_params:
add_postproc_node: true # 是否嵌入后处理节点
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], scale=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],
scale=[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], scale=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], scale=255)
model.quantize('asymu8')
model.export('asymu8', platform='pnna2', core_num='4core')
场景5:批量转换
#!/bin/bash
MODELS=("yolov5s" "yolov5m" "yolov5l")
for model in "${MODELS[@]}"; do
echo "=== 转换 $model ==="
netrans load ./$model --mean 0 0 0 --scale 255
netrans quantize ./$model asymu8 --algorithm 1
netrans export ./$model asymu8 --platform pnna
echo "✅ $model 完成"
done
场景6:精度验证
#!/usr/bin/env python3
"""精度验证 - 对比浮点和量化模型"""
from netrans import Netrans
model = Netrans()
model.load('./model', mean=[0, 0, 0], scale=255)
# 浮点推理
model.inference('float32', iterations=1)
# 量化并推理
model.quantize('asymu8')
model.inference('asymu8', iterations=1)
# 对比 golden 目录输出
# wksp/model_float32/golden/ vs wksp/model_asymu8/golden/
故障排查
错误速查表
| 错误信息 | 可能原因 | 解决方案 |
|---|---|---|
xxx.quantize file does not exist |
未执行 quantize 或类型不匹配 | 执行 netrans quantize 并确保类型一致 |
Warning: @{lid}:<suffix> not found |
hybrid 层名不匹配 | 使用 netrans dump 查看实际层名 |
| NBG 文件大小异常 | 量化未生效 | 确保 quantize() 后调用 export(),不要重新创建实例 |
| 预处理参数不生效 | 配置未正确加载 | 检查 channel_mean_value.txt 格式和 _inputmeta.yml |
问题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. 检查 channel_mean_value.txt 格式
cat channel_mean_value.txt
# 应该是: "mean1 mean2 mean3 scale"
# 2. 检查 _inputmeta.yml
cat *_inputmeta.yml | grep -A 10 "preprocess:"
# 3. 确认 add_preproc_node 设置
grep "add_preproc_node" *_inputmeta.yml