【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

相关文章

Ubuntu 24.04启用root图形登录的操作流程

《Ubuntu24.04启用root图形登录的操作流程》Ubuntu默认禁用root账户的图形与SSH登录,这是为了安全,但在某些场景你可能需要直接用root登录GNOME桌面,本文以Ubuntu2... 目录一、前言二、准备工作三、设置 root 密码四、启用图形界面 root 登录1. 修改 GDM 配

浅析Spring如何控制Bean的加载顺序

《浅析Spring如何控制Bean的加载顺序》在大多数情况下,我们不需要手动控制Bean的加载顺序,因为Spring的IoC容器足够智能,但在某些特殊场景下,这种隐式的依赖关系可能不存在,下面我们就来... 目录核心原则:依赖驱动加载手动控制 Bean 加载顺序的方法方法 1:使用@DependsOn(最直

Spring Security中用户名和密码的验证完整流程

《SpringSecurity中用户名和密码的验证完整流程》本文给大家介绍SpringSecurity中用户名和密码的验证完整流程,本文结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定... 首先创建了一个UsernamePasswordAuthenticationTChina编程oken对象,这是S

Java中调用数据库存储过程的示例代码

《Java中调用数据库存储过程的示例代码》本文介绍Java通过JDBC调用数据库存储过程的方法,涵盖参数类型、执行步骤及数据库差异,需注意异常处理与资源管理,以优化性能并实现复杂业务逻辑,感兴趣的朋友... 目录一、存储过程概述二、Java调用存储过程的基本javascript步骤三、Java调用存储过程示

Visual Studio 2022 编译C++20代码的图文步骤

《VisualStudio2022编译C++20代码的图文步骤》在VisualStudio中启用C++20import功能,需设置语言标准为ISOC++20,开启扫描源查找模块依赖及实验性标... 默认创建Visual Studio桌面控制台项目代码包含C++20的import方法。右键项目的属性:

MySQL数据库的内嵌函数和联合查询实例代码

《MySQL数据库的内嵌函数和联合查询实例代码》联合查询是一种将多个查询结果组合在一起的方法,通常使用UNION、UNIONALL、INTERSECT和EXCEPT关键字,下面:本文主要介绍MyS... 目录一.数据库的内嵌函数1.1聚合函数COUNT([DISTINCT] expr)SUM([DISTIN

Java实现自定义table宽高的示例代码

《Java实现自定义table宽高的示例代码》在桌面应用、管理系统乃至报表工具中,表格(JTable)作为最常用的数据展示组件,不仅承载对数据的增删改查,还需要配合布局与视觉需求,而JavaSwing... 目录一、项目背景详细介绍二、项目需求详细介绍三、相关技术详细介绍四、实现思路详细介绍五、完整实现代码

Go语言代码格式化的技巧分享

《Go语言代码格式化的技巧分享》在Go语言的开发过程中,代码格式化是一个看似细微却至关重要的环节,良好的代码格式化不仅能提升代码的可读性,还能促进团队协作,减少因代码风格差异引发的问题,Go在代码格式... 目录一、Go 语言代码格式化的重要性二、Go 语言代码格式化工具:gofmt 与 go fmt(一)

浅析如何保证MySQL与Redis数据一致性

《浅析如何保证MySQL与Redis数据一致性》在互联网应用中,MySQL作为持久化存储引擎,Redis作为高性能缓存层,两者的组合能有效提升系统性能,下面我们来看看如何保证两者的数据一致性吧... 目录一、数据不一致性的根源1.1 典型不一致场景1.2 关键矛盾点二、一致性保障策略2.1 基础策略:更新数

Android ViewBinding使用流程

《AndroidViewBinding使用流程》AndroidViewBinding是Jetpack组件,替代findViewById,提供类型安全、空安全和编译时检查,代码简洁且性能优化,相比Da... 目录一、核心概念二、ViewBinding优点三、使用流程1. 启用 ViewBinding (模块级