【mnn】——模型离线量化流程代码浅析

2024-06-13 08:08

本文主要是介绍【mnn】——模型离线量化流程代码浅析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

mnn, 离线量化

1. 前言

mnn的离线量化,需要首先将其他模型转换成mnn的模型表达,再进行量化。

这里我们采用MAX_ABS进行weight权重量化,KL散度进行激活值的量化,int8对称量化。

2. Code

2.1 mnn模型读入与解析

std::unique_ptr<MNN::NetT> netT;{std::ifstream input(modelFile);std::ostringstream outputOs;outputOs << input.rdbuf();netT = MNN::UnPackNet(outputOs.str().c_str());}// temp build net for inferenceflatbuffers::FlatBufferBuilder builder(1024);auto offset = MNN::Net::Pack(builder, netT.get());builder.Finish(offset);int size      = builder.GetSize();auto ocontent = builder.GetBufferPointer();// model buffer for creating mnn Interpreterstd::unique_ptr<uint8_t> modelForInference(new uint8_t[size]);memcpy(modelForInference.get(), ocontent, size);std::unique_ptr<uint8_t> modelOriginal(new uint8_t[size]);memcpy(modelOriginal.get(), ocontent, size);netT.reset();netT = MNN::UnPackNet(modelOriginal.get());

2.2 创建Calibration数据dataloader
这个Calibration是整个量化的主流程,整体流程可以归纳为:

  • fake quant weight,对原有的模型进行假量化,就是将模型的权重用MAX_ABS量化到int8,再从int8反量化到float类型。这里是为了统计的激活值的范围更精确。
  • 将假量化模型和浮点模型的tensor放入两个不同的map

2.3 离线量化
整体流程:

  • 给假量化模型传入图片,更新每个tensor的最大值,最小值
    在这里插入图片描述
  • 计算所有tensor的分布,将激活值用2048个bin进行离散,统计其直方图
    在这里插入图片描述
  • 通过KL散度为每个tensor计算一个阈值threshold,并将阈值转换为浮点和int8之间转换的scale
    在这里插入图片描述
  • 将量化参数,tensor scale,int8 weight等量化参数写回模型。 注意这里需要将浮点的weight clear掉。
for (const auto iter :  _scales) {std::unique_ptr<MNN::TensorDescribeT> describe(new MNN::TensorDescribeT);describe->index = _tensorIdx[iter.first];describe->quantInfo.reset(new MNN::TensorQuantInfoT);describe->quantInfo->scale = iter.second;describe->quantInfo->type = MNN::DataType_DT_INT8;describe->quantInfo->min = -1 * _featureClampValue;describe->quantInfo->max = 1 * _featureClampValue;_originalModel->extraTensorDescribe.emplace_back(std::move(describe));          // 1. extraTensorDescribe量化后添加的属性,在哪里使用??}SymmetricQuantizeWeight(param->weight.data(), weightSize, quantizedWeight.data(), quantizedWeightScale.data(), outputChannel, _weightClampValue);param->quanParameter = IDSTEncoder::encode(param->weight, quantizedWeightScale, weightSize/channles, channles, false, quantizedWeight.data(), -_weightClampValue);          // 3. 
param->quanParameter->scaleIn = inputScale;
param->quanParameter->scaleOut = outputScale;
if (param->common->relu6) {param->common->relu  = true;param->common->relu6 = false;
}
param->weight.clear();          // 4. 清除原有的weight
  • 重新写回到模型

总结

  • 整个代码还是很清晰的,结构也很明确。只是后续要如何使用这些量化参数需要深入到mnn的框架里,后面再补上mnn框架代码的浅析

这篇关于【mnn】——模型离线量化流程代码浅析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1056741

相关文章

Nginx分布式部署流程分析

《Nginx分布式部署流程分析》文章介绍Nginx在分布式部署中的反向代理和负载均衡作用,用于分发请求、减轻服务器压力及解决session共享问题,涵盖配置方法、策略及Java项目应用,并提及分布式事... 目录分布式部署NginxJava中的代理代理分为正向代理和反向代理正向代理反向代理Nginx应用场景

Java集合之Iterator迭代器实现代码解析

《Java集合之Iterator迭代器实现代码解析》迭代器Iterator是Java集合框架中的一个核心接口,位于java.util包下,它定义了一种标准的元素访问机制,为各种集合类型提供了一种统一的... 目录一、什么是Iterator二、Iterator的核心方法三、基本使用示例四、Iterator的工

Java 线程池+分布式实现代码

《Java线程池+分布式实现代码》在Java开发中,池通过预先创建并管理一定数量的资源,避免频繁创建和销毁资源带来的性能开销,从而提高系统效率,:本文主要介绍Java线程池+分布式实现代码,需要... 目录1. 线程池1.1 自定义线程池实现1.1.1 线程池核心1.1.2 代码示例1.2 总结流程2. J

Spring Boot分层架构详解之从Controller到Service再到Mapper的完整流程(用户管理系统为例)

《SpringBoot分层架构详解之从Controller到Service再到Mapper的完整流程(用户管理系统为例)》本文将以一个实际案例(用户管理系统)为例,详细解析SpringBoot中Co... 目录引言:为什么学习Spring Boot分层架构?第一部分:Spring Boot的整体架构1.1

JS纯前端实现浏览器语音播报、朗读功能的完整代码

《JS纯前端实现浏览器语音播报、朗读功能的完整代码》在现代互联网的发展中,语音技术正逐渐成为改变用户体验的重要一环,下面:本文主要介绍JS纯前端实现浏览器语音播报、朗读功能的相关资料,文中通过代码... 目录一、朗读单条文本:① 语音自选参数,按钮控制语音:② 效果图:二、朗读多条文本:① 语音有默认值:②

nodejs打包作为公共包使用的完整流程

《nodejs打包作为公共包使用的完整流程》在Node.js项目中,打包和部署是发布应用的关键步骤,:本文主要介绍nodejs打包作为公共包使用的相关资料,文中通过代码介绍的非常详细,需要的朋友可... 目录前言一、前置准备二、创建与编码三、一键构建四、本地“白嫖”测试(可选)五、发布公共包六、常见踩坑提醒

Vue实现路由守卫的示例代码

《Vue实现路由守卫的示例代码》Vue路由守卫是控制页面导航的钩子函数,主要用于鉴权、数据预加载等场景,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着... 目录一、概念二、类型三、实战一、概念路由守卫(Navigation Guards)本质上就是 在路

uni-app小程序项目中实现前端图片压缩实现方式(附详细代码)

《uni-app小程序项目中实现前端图片压缩实现方式(附详细代码)》在uni-app开发中,文件上传和图片处理是很常见的需求,但也经常会遇到各种问题,下面:本文主要介绍uni-app小程序项目中实... 目录方式一:使用<canvas>实现图片压缩(推荐,兼容性好)示例代码(小程序平台):方式二:使用uni

JAVA实现Token自动续期机制的示例代码

《JAVA实现Token自动续期机制的示例代码》本文主要介绍了JAVA实现Token自动续期机制的示例代码,通过动态调整会话生命周期平衡安全性与用户体验,解决固定有效期Token带来的风险与不便,感兴... 目录1. 固定有效期Token的内在局限性2. 自动续期机制:兼顾安全与体验的解决方案3. 总结PS

Ubuntu向多台主机批量传输文件的流程步骤

《Ubuntu向多台主机批量传输文件的流程步骤》:本文主要介绍在Ubuntu中批量传输文件到多台主机的方法,需确保主机互通、用户名密码统一及端口开放,通过安装sshpass工具,准备包含目标主机信... 目录Ubuntu 向多台主机批量传输文件1.安装 sshpass2.准备主机列表文件3.创建一个批处理脚