NCNN 模型 INT8 量化

NCNN 模型 INT8 量化

在移动设备上部署深度学习模型时,模型的推理速度和内存占用是关键考虑因素。NCNN 作为腾讯开源的轻量级神经网络推理框架,为移动端优化提供了强大的支持。其中,INT8 量化技术是提升模型性能、降低资源消耗的重要手段。最近公司刚好也有业务需求,需要在手机端部署数字人,故探索了下 NCNN 的量化。本文将基于 NCNN 官方文档,详细介绍如何将浮点模型 F32 量化为 INT8 模型,并在移动设备上实现高效推理。

什么是 INT8 量化

INT8 量化是一种模型优化技术,它将模型中的浮点(FP32)权重和激活值转换为 8 位整数(INT8)表示。相比于 FP32,INT8 数据类型占用更少的内存空间,并且显著提升推理速度。

NCNN 量化

NCNN 提供了一套通用的量化工具,可以将 FP32 模型转换为 INT8 模型。整个过程主要分为三个步骤:模型优化、校准表生成和模型量化。

1. 模型优化

在进行量化之前,首先需要对模型进行优化。NCNN 的 ncnnoptimize 工具可以帮助我们去除模型中不必要的层、融合操作,从而减小模型体积并提高推理效率。这一步是量化过程的基础,能够为后续的量化操作提供一个更“干净”的模型。

ncnnoptimize simplified_f32_jd_shu_90000_040715.ncnn.param simplified_f32_jd_shu_90000_040715.ncnn.bin mobilenet-opt.param mobilenet-opt.bin 0

2. 创建校准表

校准表是 INT8 量化过程中至关重要的一步。它通过分析少量代表性数据(校准数据集)来确定浮点值到 INT8 值的映射关系(即量化因子)。NCNN 提供了 ncnn2table 工具来生成校准表。

2.1 从图像数据校准(未采用)

官方建议使用验证数据集进行校准,通常需要 5000 张以上的图像以确保校准的准确性。校准图像可以是 ImageNet 等大型数据集的子集。

find images/ -type f > imagelist.txt
./ncnn2table mobilenet-opt.param mobilenet-opt.bin imagelist.txt mobilenet.table mean=[104,117,123] norm=[0.017,0.017,0.017] shape=[224,224,3] pixel=BGR thread=8 method=kl
  • meannorm:这些值应与您在 Mat::substract_mean_normalize() 中使用的值保持一致,用于图像预处理。
  • shape:模型的输入 blob 形状,可以是 [w,h][w,h,c]。如果 wh 都给定,图像将被精确缩放。如果都为零或负数,则不进行缩放。如果只有一个为零或负数,则按比例缩放以保持宽高比。
  • pixel:模型的像素格式,图像像素在 Extractor::input() 之前会转换为此类型。
  • thread:用于并行推理的 CPU 线程数。
  • method:后训练量化算法,目前支持 kl(KL 散度)和 aciq

如果模型有多个输入节点,可以指定多个列表文件和参数:

./ncnn2table mobilenet-opt.param mobilenet-opt.bin imagelist-bgr.txt,imagelist-depth.txt mobilenet.table mean=[104,117,123],[128] norm=[0.017,0.017,0.017],[0.0078125] shape=[224,224,3],[224,224,1] pixel=BGR,GRAY thread=8 method=kl
2.2 从 NPY 数据校准(采用)

除了 2.1 的方式,也可以使用 NPY 文件进行校准,因为我的模型输入较多,而且除了图像数据外还有音频特征,所以我是采用这种方式去生成校准表的。官方建议使用验证(开发)数据集进行校准,并使用与训练集相同的预处理方法获取输入向量。对于 batchsize=1 的情况,将每个输入向量存储为一个 NPY 文件,N 个输入对应 N 个 NPY 文件,实际存储的向量应去除批次维度。

例如: 我的模型有两个输入,切记 shape 要为 CHW 格式的,且没有批次这个维度 N

mel, shape=[1, 80, 16]
img, shape=[6, 192, 192]

然后每个实例我们存成一个 npy 文件,并将其记录到一个 txt 文件中

filelist_img.txt

./img_0.npy
./img_1.npy
./img_2.npy

filelist_mel.txt

./mel_0.npy
./mel_1.npy
./mel_2.npy

然后运行生成校准表的命令,切记这里的 shape 要设置成 WHC 格式的

ncnn2table mobilenet-opt.param mobilenet-opt.bin filelist_img.txt,filelist_mel.txt mobilenet-opt.table mean='[0,0,0],[0,0,0]' norm='[1,1,1],[1,1,1]' shape='[16,80,1],[192,192,6]' pixel=GRAY,BGR thread=8 method=kl

3. 量化模型

在生成校准表之后,就可以使用 ncnn2int8 工具将优化后的 FP32 模型和校准表转换为 INT8 模型。

ncnn2int8 mobilenet-opt.param mobilenet-opt.bin simplified-int8.param simplified-int8.bin mobilenet-opt.table

4. Python 侧加载 NCNN 模型并推理

python 侧可以验证量化的 NCNN 模型的可用性,速度等性能指标还是需要在具体的移动端设备上进行测试的

import ncnn
import numpy as np

# 初始化NCNN环境
ncnn.create_gpu_instance()  # 启用GPU加速(可选)
net = ncnn.Net()

# # 加载模型
net.load_param("./simplified_int8.ncnn.param")
net.load_model("./simplified_int8.ncnn.bin")

# 准备输入数据
mel_list = ''
img_list = ''
input_mel = np.array(mel_list).astype(np.float32).reshape(1, 1, 80, 16)
input_img = np.array(img_list).astype(np.float32).reshape(1, 6, 192, 192)

# 调整维度:移除冗余维度并转置图像数据
squeezed_mel = input_mel.squeeze()
squeezed_img = input_img.squeeze().transpose(1, 2, 0)

squeezed_mel = np.ascontiguousarray(squeezed_mel)
squeezed_img = np.ascontiguousarray(squeezed_img)

mat_mel = ncnn.Mat(squeezed_mel)
mat_img = ncnn.Mat(squeezed_img)

# 推理
with net.create_extractor() as ex:
    ex.input("mel", mat_mel)
    ex.input("img", mat_img)

    # 输出的变量名
    ret, out = ex.extract("output_array")
    output_array = np.array(out)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值