量化理论基础:浮点数与定点数表示,线性量化与非线性量化,对称量化与非对称量化

量化,说白了就是把模型里那些高精度的浮点数,换成低精度的整数。为什么要这么干?因为嵌入式设备上的算力有限,内存也紧张。我刚开始接触这个领域时,总觉得量化会损失很多精度,心里有点抵触。后来在项目里被逼着做了一次,才发现——嗯,其实损失没想象中那么大,收益却非常可观。

这一章,我们先把量化最核心的几个概念掰扯清楚。你搞懂了这些,后面实战才不会踩坑。

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

先问个问题:你在模型里看到的权重,比如 0.123456,计算机里到底是怎么存的?

有两种主流方式:

  • 浮点数:用科学计数法表示,比如 0.123456 = 1.23456 × 10⁻¹。在计算机里,它分成符号位、指数位、尾数位三部分。FP32(32位浮点)是深度学习默认的精度。
  • 定点数:小数点的位置是固定的。比如 Q1.7 格式,1位整数,7位小数,能表示的范围很小,但计算快、硬件开销低。

我在项目中遇到过一个问题:用浮点模型在 PC 上跑得好好的,一部署到 ARM Cortex-M 上,速度慢得离谱。为什么?因为那个芯片没有 FPU(浮点运算单元),所有浮点运算都要用软件模拟,效率极低。换成定点数之后,速度直接提升了 10 倍。

核心结论:嵌入式端做量化,本质就是把浮点模型转成定点模型,用精度换速度。

2. 线性量化与非线性量化:映射方式不同

量化就是找一个映射关系,把浮点数范围映射到整数范围。这个映射可以是线性的,也可以是非线性的。

2.1 线性量化

线性量化是最常用的方式。它假设浮点数和整数之间是简单的线性关系:

q = round(r / scale) + zero_point

其中:

  • r 是原始浮点数
  • q 是量化后的整数
  • scale 是缩放因子
  • zero_point 是零点偏移

反量化就是反过来:

r = (q - zero_point) × scale

我建议你把这个公式记牢,后面所有量化算法都绕不开它。

2.2 非线性量化

非线性量化不要求均匀映射。比如对数值大的区域用更粗的粒度,对数值小的区域用更细的粒度。典型代表是 对数量化 和 查表量化。

非线性量化在 YOLO 里用得不多,为什么?因为 YOLO 的权重和激活值分布比较均匀,线性量化已经够用了。但如果你做语音模型或者某些特殊网络,非线性量化可能会有优势。

对比项 线性量化 非线性量化
实现复杂度 低,硬件友好 高,需要查表
精度损失 均匀分布时较小 非均匀分布时更优
YOLO适用性 ✅ 主流选择 ❌ 很少使用
推理速度 快 较慢(查表开销)

我的经验:做 YOLO 量化,优先选线性量化。除非你发现精度损失不可接受,再考虑非线性方案。

3. 对称量化与非对称量化:零点怎么处理?

这是量化里最容易搞混的地方。我刚开始也绕了很久,后来画了一张图才彻底明白。

3.1 对称量化

对称量化假设浮点数的范围关于 0 对称。也就是说,最大值和最小值的值相等。零点直接映射到整数 0。

zero_point = 0
q = round(r / scale)

优点:实现简单,不需要存储 zero_point。缺点:如果数据分布不对称(比如全是正数),会浪费一半的量化范围。

3.2 非对称量化

非对称量化允许零点偏移。它用 zero_point 来补偿数据分布的不对称性。

zero_point = round(-min_float / scale)
q = round(r / scale) + zero_point

优点:能充分利用量化范围,精度更高。缺点:需要额外存储 zero_point,计算时多一步减法。

避坑指南:我曾经在一个项目中,对 ReLU 后的激活值用了对称量化。ReLU 输出全是非负数,对称量化把一半的整数范围浪费在了负数区域,导致精度掉了 3 个点。后来换成非对称量化,精度就回来了。

对比项 对称量化 非对称量化
零点 固定为 0 可偏移
存储开销 小(无需 zero_point) 大(多存一个值)
适用场景 权重(分布近似对称) 激活值(分布常偏移)
YOLO推荐 权重用对称 激活用非对称

4. 知识结构总览

下面这张图把本章的核心概念串起来了。你把它存下来,后面学量化的时候随时回来对照。

量化理论基础结构图 量化理论基础 浮点数 vs 定点数 线性 vs 非线性量化 对称 vs 非对称量化 FP32 / FP16 / BF16 Q1.7 / Q8.8 定点格式 硬件 FPU 决定选择 q = round(r/s + zp) 均匀映射 YOLO 主流选择 zp=0,实现简单 适合权重 浪费非对称分布 实践建议 权重 → 对称量化 | 激活值 → 非对称量化 | 线性量化为主

5. 实战中的选择建议

说了这么多理论,你可能会问:那我做 YOLO 量化时到底怎么选?

我直接给你一个清单:

  1. 权重:用对称量化。因为训练好的权重分布通常近似对称,用对称量化不会浪费范围。
  2. 激活值:用非对称量化。尤其是 ReLU 后的激活值全是非负数,对称量化会浪费一半的整数范围。
  3. 量化方式:用线性量化。YOLO 的卷积和全连接层对线性量化非常友好,非线性量化带来的收益微乎其微。
  4. 位宽选择:优先试 INT8。如果精度不够,再考虑 INT16 或混合精度。

一个小技巧:如果你不确定某个层该用对称还是非对称,可以先用非对称量化跑一遍,然后看 zero_point 的值。如果 zero_point 接近 0,说明数据分布是对称的,可以换成对称量化来省一点存储。

好了,这一章的内容就到这里。你把这些概念吃透了,后面讲量化算法和实战部署时,就不会觉得吃力了。