找回密码
 立即注册
查看: 262|回复: 0

模型转换、模型压缩、模型加速工具汇总(落地才有价值 ...

[复制链接]
发表于 2022-9-21 20:33 | 显示全部楼层 |阅读模式
随着端侧算力和需求的提升,AI模型的落地需求和市场日益增长,下面就来讲讲pytorch(tf\caffee等)训好的模型部署到移动端的前期准备。以下是我的一些读书笔记,可供初学者快速汲取营养。
先说说整套pipeline,确定任务->设计模型(有时候是多任务、多模型,要自己把握,控场全局)->准备数据(很重要,you are what you eat)->数据增强方式(在训练中不断完善)->训练tricks(loss\mixup等等,这些就要大量调研前沿文章,挑出有用的)->得到模型->蒸馏(看具体需要,如果数据集更新频率很高,蒸馏成本太高,不建议)->量化->模型转到onnx->mnn/ncnn/tnn/tensorrt/tflite/联发科、高通专门的部署工具链。
设计模型时要结合实际,有的operation移动端深度学习框架没有相应的算子,尽量避免,实在没办法要自己写OP,会比较耽搁;
模型转换
模型转换网站,非常便捷:https://convertmodel.com/


进一步可参考一下链接:https://blog.csdn.net/demm868/article/details/114254956?spm=1035.2023.3001.6557&utm_medium=distribute.pc_relevant_bbs_down.none-task-blog-2~default~OPENSEARCH~default-8.nonecase&depth_1-utm_source=distribute.pc_relevant_bbs_down.none-task-blog-2~default~OPENSEARCH~default-8.nonecase
ONNX篇
出protobuf格式的.onnx文件
安装
pip install onnx

pytorch模型转换
import torch
from torchvision import models
net = models.resnet.resnet18(pretrained=True)
dummpy_input = torch.randn(1,3,224,224)
torch.onnx.export(net, dummpy_input, 'resnet18.onnx')
查看.onnx模型
import onnx
# Load the ONNX model
model = onnx.load("resnet18.onnx")
# Check that the IR is well formed
onnx.checker.check_model(model)
# Print a human readable representation of the graphprint(onnx.helper.printable_graph(model.graph))
可视化:netron
onnx runtime
支持ONNX的runtime就是类似于JVM将统一的ONNX格式的模型包运行起来,包括对ONNX 模型进行解读,优化(融合conv-bn等操作),运行。
安装:
brew install libomp
pip install onnxruntime
推理:
import onnxruntime as rt
import numpy as np
data = np.array(np.random.randn(1,3,224,224))
sess = rt.InferenceSession('resnet18.onnx')
input_name = sess.get_inputs()[0].name
label_name = sess.get_outputs()[0].name
pred_onx = sess.run([label_name], {input_name:data.astype(np.float32)})[0]print(pred_onx)print(np.argmax(pred_onx)
模型量化

pytroch自带量化工具,浮点精度之间的量化没啥好说的,基本就是去小数位,重点讲fp32fP16(32)->int8
https://zhuanlan.zhihu.com/p/412528771
https://zhuanlan.zhihu.com/p/72375164
https://zhuanlan.zhihu.com/p/58182172
https://on-demand.gputechconf.com/gtc/2017/presentation/s7310-8-bit-inference-with-tensorrt.pdf
不饱和映射:当权重数据分布较为均匀时
饱和映射:权重数据分布不均与,直接映射到[-127],部分区间数值很多,有效数据区间可能就[-88,-66],这时候要找一个截断阈值T,小于T的都等于-127,剩余的都均匀映射到[-127],使用KL散度loss优化
这里有个Trick,即对于权重是量化到 [127,127],这是为了累加的时候减少溢出的风险。因为8bit的取值区间是[-2^7, 2^7-1],两个8bit相乘之后取值区间是 (-2^14,2^14],累加两次就到了(-2^15,2^15],所以最多只能累加两次而且第二次也有溢出风险,比如相邻两次乘法结果都恰好是2^14会超过2^15-1(int16正数可表示的最大值)。所以把量化之后的权值限制在(-127,127)之间,那么一次乘法运算得到结果永远会小于-128*-128 = 2^14。

使用onnx做量化
#Dynamic quantization  动态量化
import onnx
from onnxruntime.quantization import quantize_dynamic, QuantType
model_fp32 = 'path/to/the/model.onnx'
model_quant = 'path/to/the/model.quant.onnx'
quantized_model = quantize_dynamic(model_fp32, model_quant, weight_type=QuantType.QUInt8)
--------------------------
# QAT quantization  QAT量化
import onnx
from onnxruntime.quantization import quantize_qat, QuantType
model_fp32 = 'path/to/the/model.onnx'
model_quant = 'path/to/the/model.quant.onnx'
quantized_model = quantize_qat(model_fp32, model_quant)
模型简化
python -m onnxsim model.onnx model.onnx
(适用于onnx转ncnn出现问题,一些op没弄干净,sim后或许能解决)
mnn篇
中文文档:https://www.yuque.com/mnn/cn/cvrt_linux_mac
https://blog.csdn.net/weilaicxy22/article/details/118736763
./MNNConvert -f ONNX --modelFile model.onnx --MNNModel model.mnn --bizCode MNN
量化
https://blog.csdn.net/zhou_438/article/details/112321005
mnn不支持多输入参数离线量化,在线量化未了解
直接转
https://www.yuque.com/mnn/cn/usage_in_python
ncnn合集
https://blog.csdn.net/qq_40035462/article/details/123902107
资料很全的一个连接
https://www.freesion.com/article/2518170521/
https://github.com/Ewenwan/MVision/tree/master/CNN/Deep_Compression/quantization
模型剪枝

2值(-1,1)、3值(-1,0,1)
按权重的大小排序,按设定的裁剪阈值,保留权重更大的那一部分-》输出网络形状(0的位置认为cutoff)-》重新确立每一层的卷积数-》重新训练
现有的开源框架都只针对ml or 分类任务,分割任务建议在micronet上改
1.pytorch原生 prune
https://zhuanlan.zhihu.com/p/129376087
权重置0,速度没啥长进,用起来最方便,但没啥用
2. nni
微软开源的,https://www.zhihu.com/question/297982959
3. micronet
dataloader得自己写,还不是很完善,但可开发空间大
https://view.inews.qq.com/a/20210525A02QNA00
https://blog.csdn.net/hacker_long/article/details/109192836?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_title~default-0.pc_relevant_baidujshouduan&spm=1001.2101.3001.4242
4. AutoML
数据、归一化方法、激活函数、损失函数、优化器、剪枝、量化、蒸馏、NAS(强化学习、进化算法、可微分架构)
模型量化

1、Post Training Dynamic Quantization :这是最简单的一种量化方法,Post Training指的是在浮点模型训练收敛之后进行量化操作,其中weight被提前量化,而activation在前向推理过程中被动态量化,即每次都要根据实际运算的浮点数据范围每一层计算一次scale和zero_point,然后进行量化;
2、Post Training Static Quantization:第一种不是很常见,一般说的Post Training Quantization指的其实是这种静态的方法,而且这种方法是最常用的,其中weight跟上述一样也是被提前量化好的,然后activation也会基于之前校准过程中记录下的固定的scale和zero_point进行量化,整个过程不存在量化参数_(_scale和zero_point)的再计算;
3、Quantization Aware Training:对于一些模型在浮点训练+量化过程中精度损失比较严重的情况,就需要进行量化感知训练,即在训练过程中模拟量化过程,数据虽然都是表示为float32,但实际的值的间隔却会受到量化参数的限制。 至于为什么不在一开始训练的时候就模拟量化操作是因为8bit精度不够容易导致模型无法收敛,甚至直接使用16bit进行from scrach的量化训练都极其容易导致无法收敛,不过目前已经有了一些tricks去缓解这个问题,但不在本文讨论之列。

RepVgg paper reading

https://zhuanlan.zhihu.com/p/352239591
https://zhuanlan.zhihu.com/p/353697121
核心思想: 结构重参数化思想,也即训练时尽量用多分支结构来提升网络性能,而推理时,采用利用结构重参数化思想,将其变为单路结构,这样,显存占用少,推理速度又快。
1.多分支结构虽然有效,但更占用显存, 内存访问成本 (Memory Access Cost,MAC) 也会增加
2.ShuffleNet论文中提到的网络高效推理法则:模型分支越少,速度越快

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2025-2-23 00:03 , Processed in 0.092024 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表