神经网络量化

2023-11-16

前言

神经网络在图像、语音识别等领域使用越来越广泛,大部分实时性要求不高的服务都可以部署在云上,然而还是有不少模型需要在计算能力有限的可移动设备上快速运行,如人脸解锁、拍照视频的实时处理等。

一般训练的模型采用的都是32位浮点数,考虑到大部分的模型都具有比较强的抗噪能力,即即使输入受到了一定的干扰,最后预测出正确的结果,所以在手机等智能设备上,可以通过适当降低精度而基本影响结果的正确率,来达到加速计算或降低功耗的目的,例如GPU可以使用half计算、DSP上可以使用int8计算。

最近刚好了解了一下tensorflownnlib的一些量化的实现,踩过一些坑,在此总结和分享一下。

正文

什么是量化

引用百度百科上的一句话:

在数字信号处理领域,量化指将信号的连续取值(或者大量可能的离散取值)近似为有限多个(或较少的)离散值的过程。

对神经网络的量化,也就是将神经网络中大部分op的浮点权重值转换为定点整数表示,同时将op替换成可以执行类似的定点整数运算的op。于是网络中大部分的浮点运算,都能使用定点整数计算替代。

为什么要量化

  1. 提高计算速度&降低功耗。将32位浮点数计算转换成8位定点计算,在一些支持SIMD的平台上能大大提速,例如高通的DSP支持一条指令同时计算128字节的向量。

  2. 减少存储消耗。将神经网络每层的32位浮点数权重,转换为8位定点+最小最大值的存储方式,模型的大小能减少为原来的约25%。

神经网络量化的实现

  1. 神经网络对量化的实现需要把常见操作(卷积,矩阵乘法,激活函数,池化,拼接等)转换为等价的8位整数版本的操作,然后在操作的前后分别加上quantize和dequantize操作,quantize操作将input从浮点数转换成8 位整数,dequantize操作把output从8 位整数转回浮点数。以Relu为例:

image

经过转换后,新的子图如下:

image

  1. 连续的dequantize和quantize操作可以互相抵消,如图所示:

image

量化操作的实现

量化操作需要将一组float输入转换成uint8(0~255),最直观的想法就是先求出这组输入的最小值min和最大值max,然后对每个输入数据可以用

q = (x - min) / (max - min) * 255

求出其量化值。反之,也可以用

x = q * (max - min) / 255 + min

实现反量化操作。

量化后引入的量化误差为(max - min)/255.

量化过程这里有一个坑,那就是真实值0.0的量化误差,一般来说需要保证输入0.0值被精确地量化成一个整数qzero表示,如果量化值qzero所表示的值和真实值0.0之间有一定误差,那么对一些操作会有比较大的影响,比如卷积或者pooling层做padding时需要在边缘补0,Relu层需要截断小于0的输入。

关于量化操作,tensorflow和nnlib的策略不太一样。

  1. tensorflow:
    分有符号输入和无符号输入两种情况。
  • 有符号输入:调整min和max,max=MAX(-min, max), min = -max, 这样可以使得范围是对称的,[min, max]被量化至[-127, 127]
  • 无符号输入:令min=0,然后将[0, max]量化至[0, 255]

以上两种情况下,都能保证输入的0.0值能刚好被量化成0.

  1. nnlib:
    不区分是否为有符号,统一量化到0~255。下面这部分源码是为了调整min和max的值,使得0.0被量化后的误差小于2^-14.
static inline void quantize_adjust_range(float *out_min, float *out_max, float *out_stepsize, float *out_recip_stepsize, float in_min, float in_max)
{
    // 确保0被包含在[min, max]
	float minval = fminf(0.0f,in_min);
	float maxval = fmaxf(0.0f,in_max);
	float range = fmaxf(0.0001f,maxval-minval);
	float recip_stepsize = 255.0f/range;

	// move either min, or max, as  little as possible, so that
	// the 'zero' point  -min *255/range  is an integer. if minval == 0
	// this is already true.
	if( minval < 0.0f ){
		float z = - minval *recip_stepsize;		// current 'zero point'
		float zi = floorf(z);					// integer part, >=0
		float zf = z - zi;
		// if within 2^-14 of an integer, call it close enough
		if( zf > 6.1035156e-05f && zf < 0.999938965f){
			// choose which end to move
			// if zi <= 0  or >= 254, the decision is based on that only (to
			// avoid divide by 0) otherwise choose based on which can be moved
			// the least.
			//
			if( zi > 0.0f && ( zi > 253.0f || (zf-1.0f)*minval>= zf*maxval )) {
				// increase max, change z to zi
				range = -255.0f*minval/zi;
				maxval = minval+ range;
			}else{
				// decrease min; change z to zi+1
				minval = maxval*(zi+1.0f)/(zi-254.0f);
				range = maxval-minval;
			}
			// recalc range
			recip_stepsize = 255.0f/range;
		}
	}
	*out_min = minval;
	*out_max = maxval;
	*out_stepsize = flt_div_255(range);
	*out_recip_stepsize = recip_stepsize;
}

参考链接

  1. tensorflow quantization
  2. What I’ve learned about neural network quantization
  3. https://github.com/tensorflow/tensorflow
  4. https://source.codeaurora.org/quic/hexagon_nn/nnlib
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

神经网络量化 的相关文章

随机推荐

  • 阻止移动端 touchmove 与 scroll 事件冲突

    在移动端开发过程中 如果要实现一个元素或按钮的拖动定位 会出现很多坑 例如 元素上下移动过程中 会触发 body 的 scroll 事件 导致整体的位置偏移 这时就需要 阻止移动端 touchmove 与 scroll 事件冲突 一 解决思
  • 【致敬未来的攻城狮计划】--RA2E1 开发板测评(3)按键输入

    前言 1 首先感谢 李肯前辈的活动 从而申请到了RA2L1开发板的测评 2 本文主要介绍按键输入的内容 3 学习本文需要准备的前提 致敬未来的攻城狮计划 RA2E1 开发板测评 1 keil环境配置 致敬未来的攻城狮计划 RA2L1 开发板
  • 自助Linux之问题诊断工具strace

    引言 Oops 系统挂死了 Oops 程序崩溃了 Oops 命令执行报错 对于维护人员来说 这样的悲剧每天都在上演 理想情况下 系统或应用程序的错误日志提供了足够全面的信息 通过查看相关日志 维护人员就能很快地定位出问题发生的原因 但现实情
  • 去除li前面小点点

    li list style type none
  • 3. 性能测试之目标评估

    文章目录 前言 一 模型1 根据日活计算目标QPS 1 原则 2 事例 二 模型2 根据压测数据评估最大支撑并发 1 原则 2 事例 3 备注 三 模型3 根据压测数据评估服务器资源 1 策略 2 备注 四 模型4 评估用户并发或峰值并发
  • Excel·VBA螺旋数组函数

    目录 1 由外到内顺时针的螺旋数组 实现方法1 代码思路 螺旋数组函数代码 举例 实现方法2 代码思路 螺旋数组函数代码 2 由外到内逆时针的螺旋数组 举例 数字1 12从左上角顺时针依次输出的即为螺旋数组 如下图 1 由外到内顺时针的螺旋
  • 网络编程3——TCP Socket实现的客户端服务器通信完整代码(详细注释帮你快速理解)

    文章目录 前言 一 理论准备 Socket套接字是什么 TCP协议的特点 二 TCP 流套接字提供的API ServerSocket API Socket API 三 代码实现请求响应式 客户端服务器 服务器 客户端 疑惑解答 为什么服务器
  • 获取Android设备唯一标识码

    概述 有时需要对用户设备进行标识 所以希望能够得到一个稳定可靠并且唯一的识别码 虽然Android系统中提供了这样设备识别码 但是由于Android系统版本 厂商定制系统中的Bug等限制 稳定性和唯一性并不理想 而通过其他硬件信息标识也因为
  • Simulink代码生成(二)——代码生成时模型的配置方法及操作流程

    Simulink代码生成 二 代码生成时模型的配置方法及操作流程 文章目录 Simulink代码生成 二 代码生成时模型的配置方法及操作流程 一 模型 二 代码生成设置 1 步长选择 2 系统目标文件设置 3 生成代码打开测试报告 4 保存
  • 为什么如今这么多人讨论网络安全?

    网络安全如今备受讨论 跟各种经济政治的关系是分不开的 并且变得更加复杂多变 网络安全的发展前景更可观 很多安全企业也开始积极寻求各类网络风险的防范方案和数据隐私保护技术 当今世界形势的变化 以及各种因素的不断影响 全球网络安全问题再不断提升
  • Qt扫盲-QSS概述

    QSS概述 一 概述 二 详细 一 概述 QSS 其实是Qt样式表 Qt样式表是Qt界面的一种强大的机制 除了通过继承QStyle已经可以实现的功能外 它还允许您自定义窗口组件的外观 Qt样式表的概念 术语和语法很大程度上受到HTML层叠样
  • sql server 提取汉字、数字和字母的sql server方法

    sql server 提取汉字 数字 字母的方法 提取数字 if object id dbo get number2 is not null drop function dbo get number2 go create function
  • QT学习(五)——从子窗口传来多个信号(带参数的自定义信号)

    同样是两个窗口 主窗口与副窗口 给副窗口自定义两个重载的信号 传给主窗口处理 void mySignals 信号可以重载 void mySignals int QString 由被关联的按钮发送消息 并送出两条消息给主窗口 emit myS
  • 常用C语言文件操作

    1 fopen 使用fopen需要引用头文件stdio h 函数声明如下 FILE fopen const char pathname const char mode 这里要多多关心的是第二个参数mode 关系到我们对文件操作的权限 这里做
  • 提升KNN的运行效率

    20221005 引言 KNN算法是一种 懒惰 算法 在模型训练过程 仅仅是将数据存储到快速查询的数据结构中 在测试阶段会通过进行距离计算来输出结果 那么当数据集比较大的时候 一方面内存要求会提升 另一方面在计算的时间也会增大 之前的时候
  • vue实现文字水印效果

    vue文件代码
  • Java自学路线(超全超详细)—初学者零基础版Ⅰ

    Java 对于第一次见到它的人来说 不知道它是什么东西 可能看起来是个单词 可是通过网络翻译却没办法给它一个中文定义 但是 在计算机领域中 它是一门面向对象的编程语言 那么问题来了 有人对于 面向对象的编程语言 这个词组并不理解 在此 作出
  • 出现'MySQL Daemon failed to start‘解决方法

    方法千万条 备份第一条 运行 service mysqld start 重启数据库总是会出现如下提示 MySQL Daemon failed to start Starting mysqld FAILED 的提示 如果直接输入 mysql
  • Ubuntu/linux c开发(6)内存泄露

    写好个服务程序 短期测试没啥问题 准备跑长时间的 结果 前两天正常 第三天突然涨了100多M 这感觉 爽飞了 这里说下Ubuntu中内存泄露检测工具 Valgrind 安装和使用连接如下 链接 Valgrind安装使用 这里大概说下统计结果
  • 神经网络量化

    前言 神经网络在图像 语音识别等领域使用越来越广泛 大部分实时性要求不高的服务都可以部署在云上 然而还是有不少模型需要在计算能力有限的可移动设备上快速运行 如人脸解锁 拍照视频的实时处理等 一般训练的模型采用的都是32位浮点数 考虑到大部分