目录
前言
在上一篇中提到了在FPGA中实现网络,因为网络过于臃肿而难以综合,因此随后通过资料的查阅发现参数量化这一技术能够大大降低网络的复杂度。但在我调研过程中,我发现网络上关于参数量化的FPGA实现资料太少,因此我打算将这一过程记录下来,希望能够通过这篇博客与大家分享这一技术的实现过程以及我的一些心得。
一、参数量化简介
下面的图片取自哔哩哔哩一个搬运视频:【基于PyTorch的量化技术详解 by Umar Jamil】
同时也参考了一个优快云文章 模型量化(一)—— 非对称量化、对称量化(全代码)
1.1 参数量化是什么?
随着人工智能和深度学习技术的迅猛发展,模型的复杂性和计算需求也不断增加,尤其是在边缘计算和嵌入式设备中,计算资源的限制使得模型的高效部署成为一大挑战。
参数量化作为一种有效的优化技术,通过将浮点数表示的模型参数转换为低精度整数,可以大幅减少模型存储和计算开销,从而提高推理速度并降低功耗。
简单来说,参数量化技术就是对数据进行降维,降低网络的计算成本。
1.2 为什么要使用参数量化?
有两方面考虑,一方面是为了减小网络大小,使得能够使用FPGA进行设计。另一方面,因为在FPGA中,其内置的DSP资源更加有利于定点化计算,而对于浮点数计算形式有一定的困难,使用参数量化将32float转化为int8类型,在卷积计算的过程中能够使用内置的DSP资源进行运算。
1.3 参数量化的类型
参数量化主要有两种类型,一个是对称量化,另一个是非对称量化。

1.3.1 对称量化
对称量化要求量化后的值中零点必须对应于原始值中的零,这意味着量化操作的零点固定不变。因此,对称量化通常使用两个参数(量化的最小值和最大值)来定义量化的范围,而这个范围是以零为中心对称的。
比如一个float型的数列,范围是[-0.3,3],可以看出,这个数列的分布不是对称的,如果要使用对称量化,意思就是将最大值3量化为255,同时最小值0对应的是-3,这使得在[-3,-0.3]范围内的数被浪费掉,造成不小的量化误差(量化误差是在量化过程中损耗的精度)

1.3.2 非对称量化
非对称量化不要求量化后的值中零点对应于原始值中的零。这意味着量化操作可以有一个任意的零点,这个零点被映射到量化范围内的某个整数值上。因此,非对称量化使用三个参数(量化最小值、量化最大值和零点)来定义从原始数值到量化数值的映射关系。
还是那个比喻,但是现在量化后的0不再是对称过去的-3,而是数列的最小值-0.3,这样的设计能够使得量化后的数据占满0-255的8位数据,有效降低量化误差。

非对称量化的计算公式为:

其中rint表示量化后的数据,s表示量化的放缩因子,z表示偏差值,然后clamp函数是为了将超过0到255范围的数进行限制,其以及s、z的计算公式如下:


1.4 参数量化的实现方式
参数量化有两个很广泛的实现方式——训练后量化(Post-training Quantization,PTQ)以及量化感知训练(Quantization Aware Training, QAT)两者有一定的相同点,其中PTQ不需要进行训练,而QAT需要进行二次训练。
1.4.1 训练后量化(PTQ)
训练后量化(Post-training Quantization,PTQ)是一种常见的模型量化技术,它在模型训练完成之后应用,旨在减少模型的大小和提高推理速度,同时尽量保持模型的性能。训练后量化对于部署到资源受限的设备上,如移动设备和嵌入式设备,特别有用。
其主要的原理就是在训练网格后,对网格的权值、偏置等参数进行量化,直接作用于网络。但是值得注意的是,量化的数据在卷积层中传输的过程中,数据会逐渐变大,如下所示:

上面是一个简单的卷积操作,我们将所有数据将转化8bit后,计算得到的Yq的位宽已经不是8bit了,至少需要用16bit来表示(1111_1111 * 1111_1111 + 1111*1111 = 1111_1111_0000_0000)。因此需要在计算完毕后在进行反量化,还原32位浮点数,形成一个量化-计算-反量化的一个过程。
但是这时候聪明的小朋友就会问了:在FPGA计算的过程中,各个层输出后还要进行反量化,岂不是还要使用浮点数模块?
这个问题问得好,这也是我困惑的一点,如果是这样的话还是无法避免使用浮点数模块,但是在传输到下一层的时候我们依然要将浮点数进行量化后输入,这样我们可以在FPGA中重新设计反量化模块,让卷积层输出的数据再次量化为0-255范围内,这样就可以把网络设计成这样:
量化-计算-再次量化-计算 ... ...
&nbs

最低0.47元/天 解锁文章
10万+





