3. 均匀量化与非线性量化:对称量化、非对称量化、对数量化、查表量化

好,咱们今天聊聊量化。这玩意儿在嵌入式部署里,可以说是“兵家必争之地”。模型再大,算力再强,量化做不好,上板子就是白搭。我个人习惯把量化分成两大类:均匀量化和非线性量化。说白了,就是看你怎么把连续的浮点数,映射到离散的整数点上。

3.1 均匀量化:简单粗暴,但够用

均匀量化,顾名思义,就是量化步长是固定的。你想想看,就像拿一把刻度均匀的尺子去量东西。这把尺子的最小刻度,就是我们的量化步长(Scale)。

均匀量化里,又分两种:对称量化和非对称量化。我刚开始接触时,也经常搞混。后来在项目里踩过坑,才真正理解它们的区别。

3.1.1 对称量化

对称量化,核心思想就是让零点(Zero Point)对齐到浮点数的0。也就是说,浮点数的0,量化后一定是整数0。这样做的好处是啥?计算简单啊!

公式长这样:

// 对称量化公式
// r 是浮点数,q 是量化后的整数,S 是缩放因子
// r = S * q

// 量化过程
S = max(|r_max|, |r_min|) / (2^(n-1) - 1)
q = round(r / S)

// 反量化过程
r = S * q

你看,没有零点偏移,乘除法就搞定了。我在做MobileNet部署时,就特别喜欢用对称量化。因为MobileNet的权重和激活值分布,通常比较对称,用对称量化几乎不掉点。

我的经验: 对称量化对权重分布对称的网络特别友好。比如很多分类网络,权重分布像个钟形,对称量化就很合适。

3.1.2 非对称量化

非对称量化就灵活多了。它允许零点不在0上,可以偏移。公式里多了一个Zero Point(Z)。

// 非对称量化公式
// r = S * (q - Z)

// 量化过程
S = (r_max - r_min) / (2^n - 1)
Z = round(-r_min / S)
q = round(r / S + Z)

// 反量化过程
r = S * (q - Z)

为什么要用非对称?因为很多模型的激活值,比如ReLU后的输出,全是非负的。这时候你用对称量化,有一半的量化范围就浪费了。非对称量化可以把整个量化范围,都用来表示正数,精度自然就高了。

避坑指南: 我曾经在一个检测模型上,对激活值用了对称量化,结果精度掉了2个点。换成非对称量化后,精度就回来了。所以,激活值分布偏了,别犹豫,上非对称。

3.2 非线性量化:精度不够,花样来凑

均匀量化虽然简单,但有个硬伤:它对大数值和小数值的精度是一样的。但实际中,我们往往更关心小数值的精度。比如权重里,很多值都集中在0附近。这时候,非线性量化就派上用场了。

3.2.1 对数量化

对数量化,说白了,就是在对数域里做量化。它的步长不是固定的,而是随着数值增大而增大。这样,小数值的精度就高了。

公式大概这样:

// 对数量化(以2为底)
// q = round(log2(|r|))
// 反量化时:r = sign(r) * 2^q

// 实际实现时,通常用查表法
// 因为2的幂次运算,在硬件上可以转换成移位操作

对数量化有个好处:乘法可以变成加法。因为 log(a * b) = log(a) + log(b)。这在硬件上,能省不少乘法器。我记得在某个语音唤醒词项目里,就用过对数量化,把模型大小压到了原来的1/4,功耗也降了不少。

核心要点: 对数量化特别适合那些数值分布范围广,但小数值更重要的场景。比如音频信号、某些传感器数据。

3.2.2 查表量化

查表量化,可以说是非线性量化的“终极形态”。它不限制你用什么映射关系,你甚至可以手工设计。只要把映射关系存成一张表,量化时查表就行。

举个例子,你想把浮点数映射到0-255的整数,但希望小数值的量化步长更小。你可以这样设计:

// 查表量化示例
// 假设我们设计一个映射表,让小数值的步长更小

// 1. 设计映射关系(比如:q = floor(sqrt(r) * 16))
// 2. 预计算好一张表:float_to_int[float_index] = q
// 3. 量化时,直接查表

// 反量化时,也需要一张表:int_to_float[q] = r

// 实际部署时,这两张表通常放在Flash里

查表量化的好处是灵活,你可以针对你的模型,设计最优的映射。但坏处也明显:需要额外的存储空间来存表。而且,如果表太大,查表速度也会受影响。

我的建议: 查表量化适合那些对精度要求极高,且模型分布非常特殊的场景。比如某些GAN网络,或者超分模型。一般分类网络,均匀量化就够用了。

3.3 如何选择?

说了这么多,到底该用哪种?我一般按这个思路来:

场景 推荐方案 原因
权重分布对称(如分类网络) 对称量化 计算简单,精度损失小
激活值非负(如ReLU后) 非对称量化 充分利用量化范围,精度更高
数值分布范围广,小值重要 对数量化 小值精度高,乘法变加法
特殊分布,精度要求极高 查表量化 最灵活,可定制

嗯,这里要注意一点:没有银弹。每种量化方法都有它的适用场景。我建议你在项目初期,先用均匀量化(对称或非对称)试试水。如果精度达标,就别折腾了。如果精度差那么一点,再考虑非线性量化。

最后,送大家一句话:量化不是目的,部署才是。别为了量化而量化,一切以最终效果为准。