3、模型量化原理(上):浮点数与定点数表示,线性量化与非线性量化,对称量化与非对称量化

好,咱们今天聊聊量化。说实话,很多同学一听到「量化」就觉得头大,觉得是数学推导、是底层硬件。其实没那么玄乎。说白了,量化就是让模型「瘦身」的同时,尽量别丢太多精度。

我刚开始做模型部署那会儿,也踩过不少坑。有一次把一个BERT模型直接转成int8,结果推理结果全乱套了。后来才发现,是我对量化的基本概念没吃透。所以今天这一讲,咱们先把地基打牢。

1. 浮点数与定点数:计算机怎么存小数?

先问个问题:你写代码时用的 float32,它到底长什么样?

嗯,浮点数在计算机里是用「科学计数法」存的。一个32位浮点数,分成三部分:1位符号位、8位指数位、23位尾数位。它能表示的范围很大,从1.4e-45到3.4e38。但代价是——计算慢、占内存。

定点数就简单多了。它没有指数位,就是固定的小数点位置。比如Q7.8格式,就是7位整数、8位小数。定点数计算快,但范围有限。你想想看,如果小数点位置定死了,遇到特别大或特别小的数,直接就溢出了。

关键区别:

  • 浮点数:范围大、精度高、计算慢、占内存多
  • 定点数:范围小、精度固定、计算快、占内存少

我在项目中遇到过这样一个场景:一个语音识别模型,用float32推理时延迟20ms,换成int8定点后直接降到5ms。但代价是,某些低频音的识别准确率掉了2%。这就是典型的「用精度换速度」。

2. 线性量化 vs 非线性量化

量化分两大类:线性量化和非线性量化。咱们一个一个说。

2.1 线性量化

线性量化,说白了就是「等比例缩放」。公式很简单:

q = round(r / S + Z)

其中:

  • r 是原始浮点数
  • q 是量化后的整数
  • S 是缩放因子(scale)
  • Z 是零点偏移(zero point)

反量化就是反过来:

r = (q - Z) * S

嗯,这里要注意:SZ 一旦确定,整个映射就是线性的。也就是说,浮点数0.1和0.2之间的差距,量化后也是等比例的。

我的经验:线性量化实现简单,硬件支持也好。大多数CPU和NPU都原生支持int8的线性量化计算。所以实际部署中,90%的场景都用线性量化。

2.2 非线性量化

非线性量化就不一样了。它用对数、指数或其他非线性函数来映射。比如:

q = round(log2(r))

这样做的好处是:在数值小的区域,量化精度更高;数值大的区域,精度可以牺牲一点。这很符合神经网络权重的分布——大部分权重都集中在0附近。

我曾经在一个图像超分模型上试过非线性量化。模型权重分布非常集中,大部分值在-0.1到0.1之间。用线性量化时,很多小值直接被截断成0了。换成非线性量化后,PSNR(峰值信噪比)从38.2dB提升到了39.1dB。

注意:非线性量化虽然精度好,但硬件支持差。很多NPU和DSP只支持线性量化。所以除非你用的是专用芯片,否则还是老老实实用线性量化吧。

3. 对称量化 vs 非对称量化

这两个概念,其实是在说零点偏移 Z 怎么处理。

3.1 对称量化

对称量化,就是让浮点数的0映射到整数的0。也就是说 Z = 0。公式变成:

q = round(r / S)

这样做的好处是:计算简单,不需要处理零点偏移。但坏处是:如果浮点数分布不对称(比如全是正数),那量化范围就浪费了一半。

举个例子:一个ReLU层的输出全是0到6之间的正数。如果用对称量化,int8的范围是-128到127,但实际只用到了0到127,负半轴全浪费了。

3.2 非对称量化

非对称量化就灵活多了。它允许 Z 不为0,可以偏移到任意位置。公式就是咱们前面说的:

q = round(r / S + Z)

这样,无论浮点数分布在哪,都能完整利用int8的256个等级。

特性 对称量化 非对称量化
零点偏移 Z = 0 Z ≠ 0
计算复杂度 高(需处理偏移)
适用范围 权重(通常对称分布) 激活值(通常不对称)
硬件支持 部分硬件不支持

我个人习惯是:权重用对称量化,激活值用非对称量化。为什么?因为权重的分布通常比较对称(正负都有),而激活值经过ReLU后全是非负的。这样搭配,精度损失最小。

4. 实际项目中的选择策略

好了,理论讲完了。咱们说说实际项目中怎么选。

我记得有一次给一个安防检测模型做量化。模型不大,但要求精度不能掉超过1%。我试了三种方案:

  1. 全对称量化:精度掉了3.2%,不行。
  2. 权重对称+激活非对称:精度掉了0.8%,可以接受。
  3. 全非线性量化:精度只掉了0.3%,但推理速度慢了20%。

最后选了方案2。为什么?因为方案3虽然精度好,但硬件不支持快速计算,得不偿失。

总结一下我的选择原则:

  • 硬件支持优先:先看目标芯片支持哪种量化方式
  • 精度要求:如果精度要求高,考虑非对称或非线性
  • 速度要求:如果追求极致速度,对称量化+int8矩阵乘是最优解

嗯,今天的内容就到这。下一讲咱们会深入量化参数的计算方法,包括怎么确定 SZ,以及量化误差怎么分析。到时候我会拿一个完整的PyTorch量化示例来演示。

记住一句话:量化不是玄学,是工程。多试、多调、多对比,你也能成为量化高手。