Transformer激活值中存在少数隐藏维度,其量级远高于其他维度,且在所有层中持续存在。这类离群特征在模型规模超过约67亿参数时才出现,是小模型量化可用、大模型量化崩溃的根本原因。
将一批文本通过 transformer,然后观察进入线性层的隐藏状态——一个矩阵,每行对应一个 token,每列对应一个隐藏维度。大多数值在零附近几个单位内波动。但有少数列不是这样:它们的值要大出一个数量级甚至更多,而且从一批文本到下一批,这些列是同一组列,对于批次中的大多数 token 来说都很大,而不是只有少数异常 token 才大。
让这个问题成为结构性问题而非统计趣闻的三个属性值得分开说明。它们是系统性的——同一组维度,而非随机散落。它们在深度上持久存在——存在于所有层中,而非局限于某个阶段。它们是涌现的——低于某个规模阈值时不存在,高于阈值时出现,而不是平滑增长。
这一测量来自 Dettmers、Lewis、Belkada 和 Zettlemoyer 的 LLM.int8() 论文(NeurIPS 2022),数据精确到值得直接引用而非转述。
论文发现系统在 6.7B 参数规模时出现系统性异常值,并指出超过约 6B 的 transformer 模型经典量化会失效。
论文通过量级定义异常特征:至少 6.0 的值。这个阈值不是任意的——论文报告,当任何量级为 6 或更大的特征被当作异常值处理时,困惑度降解就会停止。这个数字至今仍作为 llm_int8_threshold 保留在 Hugging Face 的 BitsAndBytesConfig 中,默认值为 6.0。
受影响的维度约占所有输入特征的 0.1%,在所有层中高达 75% 的序列维度上活跃。
将它们置零的代价超过其占比所暗示的:论文报告 top-1 注意力 softmax 概率质量下降超过 20%,验证困惑度降解 600–1000%。
最后一个数字才是需要记住的。千分之一的特征被移除后,模型性能下降约一个数量级。这些维度并非模型计算的附带成分,它们承担了不相称的计算份额。
这些数据来自 2022 年关于 OPT 和 BLOOM 家族的论文,6.7B 这个阈值尤其特定于那些模型训练的属性,而非 transformer 的定律。后续架构的异常值明显程度有所不同;现象是稳健的,精确阈值则不是。如需了解测量方法背后的细节,请阅读 LLM.int8() 论文。
计算很短。Int8 提供 256 个等级。Per-tensor 缩放由张量中的最大绝对值决定。如果普通激活值大致在 [-3.5, 3.5] 范围内,而一个异常维度达到 60——Hugging Face 自己的文档对这类异常值的描述就是这个范围——那么:
grid step = 2 * 60 / 255 = 0.47
ordinary range 7.0 wide
levels available to it = 7.0 / 0.47 ≈ 15 levels
15 levels ≈ log2(15) ≈ 3.9 bits of effective resolution
你要求 8 位,普通值只得到了 4 位。每一个承载大部分信号的维度现在都被量化的比 4 位权重格式量化权重还粗糙,而且与权重不同,它们没有 per-group 缩放来拯救——因为正如粒度解释的那样,沿归约维度变化的缩放无法从累加中分解出来。
而用裁剪而非缩放更糟。将异常值上限设为比如说 6 以保护网格,恰恰做了论文在将这些维度置零时测量的事情:它摧毁了原本承载 20% 注意力质量的特征。
每一种让激活量化可行的方法都是以下三种之一,知道自己运行的是哪一种,就能知道它的失效模式。
隔离它们。LLM.int8() 的混合精度分解将矩阵乘法拆分:超过阈值的维度通过 16 位乘法,其余一切通过 8 位乘法,然后将结果相加。论文指出超过 99.9% 的值仍然走 8 位路径。代价是一个分支、一个聚集和两次矩阵乘法而不是之前的一次——以速度提升换取正确性。
移动它们。SmoothQuant 用一个代数恒等式将异常通道向下缩放,并将相应权重行向上缩放,保持乘积不变。难度迁移到可以承载 per-channel 缩放的运算数上。没有分支,没有聚集,运行时没有任何额外开销——但变换依赖于架构,其迁移强度需要对每个模型进行调优。
避开它们。完全不对激活值进行量化。这是每个流行的本地格式的做法,是一种没有失效模式的响应,而非更便宜的替代方案。
有必要精确说明"避开"的含义,因为异常值问题并没有消失——它不再是一个量化问题。
在 W4A16 内核中,激活值以 FP16 到达并保持在那里。FP16 有指数,所以同一个张量中 60 的值和 0.001 的值相对精度代价相同;没有共享的缩放供异常值主导。权重被量化了,但权重分布没有这种结构——每个通道上大致是正态分布,这恰恰是 NF4 建立的基础假设,也是它工作的原因。
留下的是一个二阶效应,也就是 AWQ 命名的那个。权重仍然按组量化,所以与异常激活通道相乘的权重即使其自身量级并不显著,也对输出误差做出了过大的贡献。这就是 AWQ 从激活统计中选择显著通道而非权重量级的原因,也是 GPTQ 为什么要用从激活构建的 Hessian 对误差补偿进行加权的原因。两者都在处理异常特征——只是位于乘法的权重一侧,那里 per-group 缩放可以派上用场。
SmoothQuant 解析
纯权重量化解析
量化粒度:Per-Tensor、Per-Channel 和 Per-Group 缩放