ESP-DL部署魔改MobilenetV1—2. 模型量化

在上一节完成模型的训练和导出后,这一节我们来基于esp-dl,使用其提供的量化工具包来完成模型的量化。

量化工具

  • esp-dl

esp-dl支持的算子

首先我们需要知道esp-dl支持的算子有哪些,否则遇到无法支持的算子时会报错,无法正常量化。如果我们的模型里有不支持的算子,可以尝试对其进行替换。

  • Conv2d:只能处理三维
  • Gemm:部署还是使用的Conv2d
  • Relu
  • AvgPool2d
  • MaxPool2d
  • Add
  • Mul
  • Sub
  • Softmax
  • Tanh
  • Sigmoid
  • Concat
  • Expand
  • Flatten
  • Max
  • Min
  • Pad
  • Reshape
  • Squeeze:构造时忽略,否则其后面的conv2d会报错
  • Transpose:由于onnx的运算张量顺序为 (C, H, W),但是我们训练的还是HWC,因此输入端的这一层可以忽略
  • Slice
  • Shape
  • Resize

环境准备

环境要求

pyenv环境配置

Pyenv安装

在ubuntu的apt中,直接安装pyenv会找不到这个包。需要运行如下命令安装pyenv

curl -L https://github.com/pyenv/pyenv-installer/raw/master/bin/pyenv-installer | bash

安装完成后,根据打印信息,将如下命令复制到~/.bashrc的最后

export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init --path)"
eval "$(pyenv virtualenv-init -)"

之后执行source ~/.bashrc命令,然后就能够正常运行pyenv了。

安装新版本python

pyenv install 3.7.17

之后如果要查看所有已安装的python版本,可以执行

pyenv versions

这个命令可以列出所有已安装的python版本。

创建新环境

使用pyenv local命令加上python版本,即可更改当前命令行的python版本。

pyenv local 3.7.17

更改完成后,我们可以运行如下命令查看当前的python版本。

python --version
Python 3.7.17

可以看到,当前的python版本已经更改为我们需要的3.7.17了。

之后进入我们的工作目录下,创建我们的python环境。最后的“esp-dl-quant”是环境名称,你可以修改为你自己需要的名称。

python -m venv .venv --prompt esp-dl-quant
echo "*" > .venv/.gitignore

安装依赖

创建完成后,我们就能进入我们创建的环境了,进入后我们安装以下必要的工具包。

source .venv/bin/activate
pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple

最后,如果想要退出该环境,执行如下命令即可。

deactivate

模型量化和转换

量化工具包中的校准器可将浮点模型量化成可适配 ESP-DL 的整型模型。为了实现训练后量化,请参考以下实例准备校准集,该校准集可以是训练集或验证集的子集:

# Calibration
with open(cal_path, 'rb') as f:
    (test_images, test_labels) = pickle.load(f)

# Prepare the calibration dataset
calib_dataset =  np.expand_dims(test_images[0], axis=0)
pickle_file_path = 'cal_data.pickle'
model_proto = onnx.load(optimized_model_path)
# Calibration
model_proto = onnx.load(optimized_model_path)
print('Generating the quantization table:')

# Initialize an calibrator to quantize the optimized MNIST model to an int16 model using per-tensor minmax quantization method
calib = Calibrator('int16', 'per-tensor', 'minmax')
calib.set_providers(['CPUExecutionProvider'])

# Obtain the quantization parameter
calib.generate_quantization_table(model_proto, calib_dataset, 'mnist_calib.pickle')

# Generate the coefficient files for esp32s3
calib.export_coefficient_to_cpp(model_proto, pickle_file_path, 'esp32s3', '.', 'mnist_coefficient', True)

使用以下命令运行准备好的转换脚本:

python example.py

如果转换成功的话,会生成模型文件
在这里插入图片描述

并在命令行中输出模型的层文件信息

Generating the quantization table:
Converting coefficient to int16 per-tensor quantization for esp32s3
Exporting finish, the output files are: ./cat_vs_dog_coefficient.cpp, ./cat_vs_dog_coefficient.hpp

Quantized model info:
model input name: input_1, exponent: -15
Transpose layer name: StatefulPartitionedCall/model/conv1/Conv2D__6, output_exponent: -15
Conv layer name: StatefulPartitionedCall/model/conv1/Conv2D, output_exponent: -11
DepthwiseConv layer name: StatefulPartitionedCall/model/conv_dw_1/depthwise, output_exponent: -10
Conv layer name: StatefulPartitionedCall/model/conv_pw_1/Conv2D, output_exponent: -9
DepthwiseConv layer name: StatefulPartitionedCall/model/conv_dw_2/depthwise, output_exponent: -10
Conv layer name: StatefulPartitionedCall/model/conv_pw_2/Conv2D, output_exponent: -10
DepthwiseConv layer name: StatefulPartitionedCall/model/conv_dw_4/depthwise, output_exponent: -10
Conv layer name: StatefulPartitionedCall/model/conv_pw_4/Conv2D, output_exponent: -10
DepthwiseConv layer name: StatefulPartitionedCall/model/conv_dw_5/depthwise, output_exponent: -10
Conv layer name: StatefulPartitionedCall/model/conv_pw_5/Conv2D, output_exponent: -11
DepthwiseConv layer name: StatefulPartitionedCall/model/conv_dw_6/depthwise, output_exponent: -11
Conv layer name: StatefulPartitionedCall/model/conv_pw_6/Conv2D, output_exponent: -12
GlobalAveragePool layer name: StatefulPartitionedCall/model/global_average_pooling2d/Mean, output_exponent: -12
Squeeze layer name: StatefulPartitionedCall/model/global_average_pooling2d/Mean_Squeeze__118, output_exponent: -12
Gemm layer name: fused_gemm_0, output_exponent: -10
Softmax layer name: StatefulPartitionedCall/model/softmax/Softmax, output_exponent: -14

其中包含了模型输入和每层输出的量化指数位,在之后的模型部署中会使用到。

此外最后还会输出模型在量化数据集上的准确度
在这里插入图片描述

  • 9
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zxfeng~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值