2. 量化原理精讲:浮点数与定点数、对称量化与非对称量化、量化粒度

好,咱们直接进入正题。量化这东西,说白了就是给模型“减肥”。但减肥不能减到残废,对吧?你得知道哪些肉能减,哪些骨头不能动。这一章,我就带你把这套“减肥”的底层逻辑彻底搞明白。

2.1 浮点数 vs 定点数:模型世界的两种“语言”

模型里存的是什么?是权重和激活值。这些值最初都是浮点数,也就是带小数点的数。比如 0.1234567,或者 -3.1415926。浮点数精度高,但占地方大,计算也慢。

那定点数呢?你可以把它想象成“整数+缩放”。比如 12345,我告诉你这个数要除以 1000,那它实际代表 12.345。定点数就是这种思路——用整数来模拟小数。

我刚开始做量化的时候,总觉得浮点数转定点数就是“四舍五入”那么简单。后来踩了个大坑——有个模型量化后直接崩了,查了半天才发现是定点数的精度不够,导致梯度爆炸。嗯,从那以后我再也不敢小看这个转换过程了。

核心区别一句话:

  • 浮点数:动态范围大,精度高,但存储和计算开销大。
  • 定点数:动态范围固定,精度有限,但存储小、计算快。

你想想看,大模型动辄几十亿参数,每个参数都存成 float32,那得多少显存?所以量化就是要把这些浮点数“翻译”成定点数,用更少的比特去表示。

2.2 对称量化 vs 非对称量化:两种“翻译”策略

好,现在我们知道要把浮点数转成定点数了。但怎么转?这里有两种主流策略:对称量化和非对称量化。

2.2.1 对称量化

对称量化,顾名思义,就是量化后的整数范围关于 0 对称。比如 int8 的范围是 [-128, 127],那对称量化就是把浮点数的最大值和最小值映射到 [-127, 127](通常不用 -128,留一个给特殊值)。

公式很简单:

scale = max(|x_max|, |x_min|) / 127
x_quant = round(x / scale)

我个人习惯在权重量化时优先用对称量化。为什么?因为权重的分布通常比较对称,而且对称量化在推理时计算更简单——不需要处理零点偏移。

我的经验:

我在项目中遇到过,有些模型的权重分布严重不对称(比如全是正数)。这时候用对称量化,有一半的量化范围就浪费了。说白了,就是精度会下降。所以对称量化不是万能的。

2.2.2 非对称量化

非对称量化就灵活多了。它允许量化后的整数范围不关于 0 对称,通过引入一个“零点”(zero point)来偏移。

公式:

scale = (x_max - x_min) / (q_max - q_min)
zero_point = round(q_min - x_min / scale)
x_quant = round(x / scale) + zero_point

非对称量化特别适合激活值。为什么?因为激活值经过 ReLU 后全是非负数,分布天然不对称。用非对称量化,就能把整个量化范围都利用起来。

避坑指南:

我曾经在量化一个 NLP 模型时,对激活值用了对称量化,结果精度掉了 5 个点。后来换成非对称量化,精度只掉了 0.5 个点。差别就这么大。所以,权重用对称,激活用非对称,这是一个很实用的经验法则。

2.3 量化粒度:per-tensor vs per-channel

量化粒度,说白了就是“量化参数(scale 和 zero point)共享的范围有多大”。

2.3.1 Per-tensor 量化

整个张量(比如一个权重矩阵)只用一个 scale 和一个 zero point。这是最简单的量化方式,计算量最小。

但问题也很明显:如果张量内部数值分布不均匀,那量化精度就会很差。比如一个矩阵里,大部分值在 0.1 左右,但有几个异常值是 10.0。那 scale 就会被这几个异常值拉大,导致大部分值的量化精度严重下降。

2.3.2 Per-channel 量化

每个通道(channel)单独计算 scale 和 zero point。比如一个卷积层的权重形状是 [64, 3, 3, 3],那 per-channel 量化就会对 64 个输出通道分别计算量化参数。

这样做的好处很明显:每个通道都能“量身定制”自己的量化范围,精度损失更小。代价就是需要存储更多的量化参数,计算也稍微复杂一点。

我的建议:

在 GGUF 量化中,我通常这样选:

  • 权重:用 per-channel 量化。权重的分布在不同通道间差异很大,per-channel 能显著提升精度。
  • 激活值:用 per-tensor 量化。激活值的分布相对稳定,per-tensor 够用,而且能减少计算开销。

2.4 知识体系图:量化原理全景

下面这张图,我把这一章的核心逻辑串起来了。你一看就明白:

量化原理全景图 模型量化 浮点数 vs 定点数 对称 vs 非对称量化 量化粒度 高精度 大存储 权重常用 计算简单 per-tensor per-channel 激活常用 有零点偏移 核心原则:权重用对称+per-channel,激活用非对称+per-tensor 具体选择需根据模型结构和精度要求调整

2.5 实战中的选择策略

好了,理论讲完了,咱们来点实际的。你在做 GGUF 量化时,到底该怎么选?

场景 推荐方案 原因
权重量化(int8) 对称 + per-channel 权重分布对称,per-channel 精度高
激活量化(int8) 非对称 + per-tensor 激活值非负,per-tensor 够用且快
低比特量化(4-bit) 非对称 + per-channel 低比特下精度损失大,per-channel 能挽回一些
嵌入式设备部署 对称 + per-tensor 计算资源有限,优先保证速度

一个小技巧:

我在量化 LLM 时,经常先用 per-tensor 快速跑一遍,看看精度损失。如果损失在可接受范围内,就保持 per-tensor。如果损失太大,再切换到 per-channel。这样能节省不少调参时间。

嗯,这一章的内容就到这。量化原理听起来复杂,但说白了就是“用更少的比特,尽可能保留更多的信息”。你只要记住:权重用对称+per-channel,激活用非对称+per-tensor,这个组合在大多数场景下都是最优解。


专注资料整理