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
嗯,这里要注意:S 和 Z 一旦确定,整个映射就是线性的。也就是说,浮点数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%。我试了三种方案:
- 全对称量化:精度掉了3.2%,不行。
- 权重对称+激活非对称:精度掉了0.8%,可以接受。
- 全非线性量化:精度只掉了0.3%,但推理速度慢了20%。
最后选了方案2。为什么?因为方案3虽然精度好,但硬件不支持快速计算,得不偿失。
总结一下我的选择原则:
- 硬件支持优先:先看目标芯片支持哪种量化方式
- 精度要求:如果精度要求高,考虑非对称或非线性
- 速度要求:如果追求极致速度,对称量化+int8矩阵乘是最优解
嗯,今天的内容就到这。下一讲咱们会深入量化参数的计算方法,包括怎么确定 S 和 Z,以及量化误差怎么分析。到时候我会拿一个完整的PyTorch量化示例来演示。
记住一句话:量化不是玄学,是工程。多试、多调、多对比,你也能成为量化高手。