深度学习的数学原理(四十三)—— 模型量化

衔接前序 :第 42 篇讨论了当模型太大放不进单卡时的解决方案------分布式训练。但分布式训练并不能减少单张 GPU 上的显存压力。有没有一种方法,在不改变模型架构、不增加硬件的情况下,让模型更小、更快 ?答案就是量化。第 41 篇(KV Cache)已经触及了 KV Cache 的 INT8 量化,本文聚焦模型权重本身的量化------从 FP32 压缩到 INT8/INT4 的数学原理、主流方法和核心 trade-off。

量化是将深度学习从"实验室"推向"大规模部署"的关键技术。本文从量化误差的数学本质出发,逐步深入到 GPTQ、AWQ 等业界主流方法。

一、引言:为什么要量化

1.1 显存困境

以 Llama 2-7B 为例,不同精度下的模型大小:

精度 每参数比特 7B 模型大小
FP32 32 bit 28 GB
FP16/BF16 16 bit 14 GB
INT8 8 bit 7 GB
INT4 4 bit 3.5 GB
INT2(实验性) 2 bit 1.75 GB

一张 RTX 3090 有 24 GB 显存。FP16 的 7B 模型(14 GB)勉强能放进去,但只剩下 10 GB 给 KV Cache 和激活值。如果使用 INT4(3.5 GB),省下的 10.5 GB 可以给 KV Cache 处理超过 10 万 token 的长序列。

这正是量化最直接的吸引力------在不增加硬件的条件下,让模型更小、更快、承载更长上下文。

1.2 量化的本质

量化本质上就是给浮点数"瘦身"------把原本用 32 位(float32)或 16 位(float16)存储的数值,压缩成 8 位甚至 4 位的整数。

你可以把它想象成给照片压缩画质:一张 4K 超清照片(float32)占空间很大,但转成 720p 的 JPEG(INT8)后,肉眼几乎看不出区别,文件却小了好几倍。量化对模型做的,就是类似的事------牺牲一点点精度,换来更小的体积和更快的运行速度。

数学上,量化是一个有损压缩过程,它将一个连续的实数值映射到有限的离散集合:

Q:R→Q={q0,q1,...,q2b−1}Q: \mathbb{R} \to \mathcal{Q} = \{q_0, q_1, ..., q_{2^b-1}\}Q:R→Q={q0,q1,...,q2b−1}

其中 bbb 是量化位宽。通俗地说:bbb 越大,能表示的"刻度"就越多 。比如 b=8b=8b=8 时有 256 个刻度(0~255),b=4b=4b=4 时只有 16 个刻度------就像一把尺子,毫米刻度比厘米刻度更精细,量东西自然更准。

从信息论的角度,量化就是用 bbb 个比特来表示一个浮点数的分布------比特越少,信息损失越大,但存储和计算效率越高。这就像用更少的字数概括一本书:字数越少,概括越粗糙,但读起来也越快。

💡 量化是不是等同于四舍五入?

不完全等同,但四舍五入是量化中最基础的一步。

四舍五入 只是把一个小数变成离它最近的整数(如 3.14 → 3),它只涉及取整这一个操作。

量化则是一个更完整的过程,包含三步:

  1. 缩放(Scale) :根据浮点数的实际范围,确定一个缩放因子 SSS,把浮点数映射到整数区间。例如,若权重范围是 −1.0,1.0-1.0, 1.0−1.0,1.0,要映射到 INT8 的 −128,127-128, 127−128,127,则 S=127−(−128)1.0−(−1.0)=127.5S = \frac{127 - (-128)}{1.0 - (-1.0)} = 127.5S=1.0−(−1.0)127−(−128)=127.5。
  2. 取整(Round) :缩放后的值做四舍五入,得到整数。这一步才是四舍五入。
  3. 反量化(Dequantize) :推理时把整数再乘回 SSS,恢复成近似的浮点数。

所以,四舍五入只是量化流程中的一个环节。量化还涉及缩放因子的选择 (如何确定 SSS 才能让精度损失最小)、零点偏移 (非对称量化中的 ZZZ)、以及各种高级策略(如 GPTQ 用二阶信息补偿舍入误差)。这些内容将在后续章节展开。
💡 量化 vs 归一化

量化和归一化其实在某种程度上很相似,但两者有本质区别:

归一化(Normalization) 是把数据缩放到一个固定区间(如 0,10,10,1 或 −1,1-1,1−1,1),数据类型不变------float32 归一化后还是 float32,只是数值范围变了。它的目的是让不同量纲的特征可比,或加速模型收敛。

量化(Quantization) 则是改变数据类型------把 float32 变成 INT8/INT4,同时也要做缩放。这是由于原数据可能超出 16 位表示范围,因此需要先缩放"完全正确!

举个具体例子:假设一个 float32 的权重向量是 0.12,−0.55,0.98,−0.030.12, -0.55, 0.98, -0.030.12,−0.55,0.98,−0.03,要量化到 INT8(范围 −128,127-128, 127−128,127):

  1. 找范围 :最大值 0.98,最小值 -0.55,范围 −0.55,0.98-0.55, 0.98−0.55,0.98
  2. 计算缩放因子 :S=127−(−128)0.98−(−0.55)=2551.53≈166.67S = \frac{127 - (-128)}{0.98 - (-0.55)} = \frac{255}{1.53} \approx 166.67S=0.98−(−0.55)127−(−128)=1.53255≈166.67
  3. 缩放 :0.12×166.67≈20.00.12 \times 166.67 \approx 20.00.12×166.67≈20.0,−0.55×166.67≈−91.7-0.55 \times 166.67 \approx -91.7−0.55×166.67≈−91.7,0.98×166.67≈163.30.98 \times 166.67 \approx 163.30.98×166.67≈163.3,−0.03×166.67≈−5.0-0.03 \times 166.67 \approx -5.0−0.03×166.67≈−5.0
  4. 取整 :20,−92,163,−520, -92, 163, -520,−92,163,−5(INT8 整数)

可以观察到,这和归一化一样需要"缩放",但归一化后还是 float32(0.12,−0.55,0.98,−0.030.12, -0.55, 0.98, -0.030.12,−0.55,0.98,−0.03 归一化到 0,10,10,1 后是 0.42,0,1,0.340.42, 0, 1, 0.340.42,0,1,0.34),而量化后变成了整数 20,−92,163,−520, -92, 163, -520,−92,163,−5------这才是量化的核心:用更少的比特数存储。

总结:

  • 归一化 = 给数据"换尺子"(厘米→米),但尺子精度不变
  • 量化 = 给数据"换尺子 + 换刻度密度"(厘米刻度→分米刻度),牺牲精度换体积

二、量化的数学基础

2.1 线性量化(Uniform Quantization)

线性量化是最基本的量化形式,所有后续方法都建立在此基础上。

对称量化

Quantize:xq=clamp(round(xs),−2b−1,2b−1−1)\text{Quantize:} \quad x_q = \text{clamp}\left(\text{round}\left(\frac{x}{s}\right), -2^{b-1}, 2^{b-1} - 1\right)Quantize:xq=clamp(round(sx),−2b−1,2b−1−1)

Dequantize:x^=xq×s\text{Dequantize:} \quad \hat{x} = x_q \times sDequantize:x^=xq×s

其中 s=max⁡(∣x∣)2b−1−1s = \frac{\max(|x|)}{2^{b-1} - 1}s=2b−1−1max(∣x∣) 是缩放因子(scale),控制量化精度。

复制代码
        [-max_abs]          0          [+max_abs]
            │               │               │
            ▼               ▼               ▼
    INT4:   -7  -6  ...  0  1  ...  6   7
            │               │               │
            ▼               ▼               ▼
    量化值: -7s  -6s  ...  0  s  ...  6s  7s
非对称量化

Quantize:xq=clamp(round(x−xmin⁡s),0,2b−1)\text{Quantize:} \quad x_q = \text{clamp}\left(\text{round}\left(\frac{x - x_{\min}}{s}\right), 0, 2^b - 1\right)Quantize:xq=clamp(round(sx−xmin),0,2b−1)

s=xmax⁡−xmin⁡2b−1,z=round(−xmin⁡s)s = \frac{x_{\max} - x_{\min}}{2^b - 1}, \quad z = \text{round}\left(-\frac{x_{\min}}{s}\right)s=2b−1xmax−xmin,z=round(−sxmin)

Dequantize:x^=(xq−z)×s\text{Dequantize:} \quad \hat{x} = (x_q - z) \times sDequantize:x^=(xq−z)×s

非对称量化比对称量化多一个零点(zero point) zzz,可以更精确地表示非对称分布(如经过 ReLU 后的正数值)。

2.2 量化误差与 SQNR

量化误差定义为 ϵ=x−x^\epsilon = x - \hat{x}ϵ=x−x^。测量量化精度的常用指标是 SQNR(Signal-to-Quantization-Noise Ratio):

SQNR=10log⁡10∑x2∑(x−x^)2(dB)\text{SQNR} = 10 \log_{10} \frac{\sum x^2}{\sum (x - \hat{x})^2} \quad (\text{dB})SQNR=10log10∑(x−x^)2∑x2(dB)

SQNR 每增加 6 dB,等价于信噪比翻倍。一个经验法则:每减少 1 bit,SQNR 大约下降 6 dB。

2.3 手算示例:对称量化一个权重向量

取一个权重向量 w=0.5,−0.3,1.2,−0.8,2.5,−1.5w = 0.5, -0.3, 1.2, -0.8, 2.5, -1.5w=0.5,−0.3,1.2,−0.8,2.5,−1.5,量化到 INT4。

Step 1: 计算 scale

INT4 对称量化的范围是 −7,7-7, 7−7,7(Q4 对称格式通常用 7 而不是 8,因为 24−1−1=72^{4-1} - 1 = 724−1−1=7,负半轴多一个 −8-8−8)。

max⁡(∣w∣)=max⁡(0.5,0.3,1.2,0.8,2.5,1.5)=2.5\max(|w|) = \max(0.5, 0.3, 1.2, 0.8, 2.5, 1.5) = 2.5max(∣w∣)=max(0.5,0.3,1.2,0.8,2.5,1.5)=2.5

s=2.57≈0.3571s = \frac{2.5}{7} \approx 0.3571s=72.5≈0.3571

Step 2: 量化

原始值 xxx x/sx / sx/s round clamp xqx_qxq 反量化 x^=xq×s\hat{x} = x_q \times sx^=xq×s 误差
0.5 1.40 1 1 1 0.357 +0.143
-0.3 -0.84 -1 -1 -1 -0.357 -0.057
1.2 3.36 3 3 3 1.071 +0.129
-0.8 -2.24 -2 -2 -2 -0.714 +0.086
2.5 7.00 7 7 7 2.500 0.000
-1.5 -4.20 -4 -4 -4 -1.429 +0.071

Step 3: 计算 SQNR

w=0.5,−0.3,1.2,−0.8,2.5,−1.5,w^=0.357,−0.357,1.071,−0.714,2.500,−1.429w = 0.5, -0.3, 1.2, -0.8, 2.5, -1.5, \quad \hat{w} = 0.357, -0.357, 1.071, -0.714, 2.500, -1.429w=0.5,−0.3,1.2,−0.8,2.5,−1.5,w^=0.357,−0.357,1.071,−0.714,2.500,−1.429

e=w−w^=0.143,0.057,0.129,−0.086,0.000,−0.071e = w - \hat{w} = 0.143, 0.057, 0.129, -0.086, 0.000, -0.071e=w−w^=0.143,0.057,0.129,−0.086,0.000,−0.071

SQNR=10log⁡100.52+0.32+1.22+0.82+2.52+1.520.1432+0.0572+0.1292+0.0862+0.0002+0.0712\text{SQNR} = 10 \log_{10} \frac{0.5^2 + 0.3^2 + 1.2^2 + 0.8^2 + 2.5^2 + 1.5^2}{0.143^2 + 0.057^2 + 0.129^2 + 0.086^2 + 0.000^2 + 0.071^2}SQNR=10log100.1432+0.0572+0.1292+0.0862+0.0002+0.07120.52+0.32+1.22+0.82+2.52+1.52

SQNR=10log⁡1010.320.054≈22.8 dB\text{SQNR} = 10 \log_{10} \frac{10.32}{0.054} \approx 22.8 \, \text{dB}SQNR=10log100.05410.32≈22.8dB

对于 LLM 推理,SQNR 在 15-25 dB 通常是可以接受的。

2.4 校准方法:如何选 Scale

Scale 的选择直接影响量化质量。三种常见方法:

MinMax :直接用 max⁡(∣x∣)\max(|x|)max(∣x∣) 作为 scale 依据。简单但容易被 outlier 干扰。

MinMax:s=max⁡(∣x∣)2b−1−1\text{MinMax:} \quad s = \frac{\max(|x|)}{2^{b-1} - 1}MinMax:s=2b−1−1max(∣x∣)

Percentile :去掉绝对值最大的 p%p\%p% 的值后再计算 scale,减小 outlier 影响。

Percentile:s=P99(∣x∣)2b−1−1\text{Percentile:} \quad s = \frac{P_{99}(|x|)}{2^{b-1} - 1}Percentile:s=2b−1−1P99(∣x∣)

KL 散度校准:遍历不同的 scale 候选,选择量化后分布与原分布 KL 散度最小的那个。

s∗=arg⁡min⁡s KL(Poriginal∥Pquantized(s))s^* = \arg\min_s \, \text{KL}(P_{\text{original}} \parallel P_{\text{quantized}}(s))s∗=argsminKL(Poriginal∥Pquantized(s))


三、后训练量化(PTQ)

PTQ 是最简单的量化方法:模型训练完成后,直接对权重做量化,不需要任何额外训练。

3.1 逐张量 vs 逐通道量化

对权重矩阵 W∈Rdout×dinW \in \mathbb{R}^{d_{\text{out}} \times d_{\text{in}}}W∈Rdout×din:

  • Per-tensor:整个矩阵共用一个 scale
  • Per-channel:每一行(输出通道)各用一个 scale

Per-channel 的量化精度更高,因为不同通道的权重分布可能差异很大(尤其是 attention 的 QprojQ_projQproj 和 KprojK_projKproj)。

复制代码
Per-tensor:  scale = max(|W|) / q_max

    ┌──────────────────────────┐
    │  w₁₁  w₁₂  w₁₃  w₁₄     │  ← 所有元素共享一个 scale
    │  w₂₁  w₂₂  w₂₃  w₂₄     │
    │  w₃₁  w₃₂  w₃₃  w₃₄     │
    └──────────────────────────┘

Per-channel:  每行一个 scale

    ┌──────────────────────────┐
    │  w₁₁  w₁₂  w₁₃  w₁₄     │  ← scale₁
    │  w₂₁  w₂₂  w₂₃  w₂₄     │  ← scale₂
    │  w₃₁  w₃₂  w₃₃  w₃₄     │  ← scale₃
    └──────────────────────────┘

3.2 PTQ 的局限性

PTQ 的问题是 Round-to-Nearest(RTN)------对每个权重独立做最近舍入,没有考虑权重之间的相互关系和输入数据的分布。对于有大量 outlier 的 LLM 权重(尤其是深层),PTQ/RTN 会带来显著的精度下降。


四、量化感知训练(QAT)

QAT 在训练过程中模拟量化,让模型参数适应量化噪声。

4.1 Fake Quantization

前向传播时,QAT 插入 Fake Quantize 操作:

x^=s⋅clamp(round(x/s),−2b−1,2b−1−1)\hat{x} = s \cdot \text{clamp}(\text{round}(x / s), -2^{b-1}, 2^{b-1} - 1)x^=s⋅clamp(round(x/s),−2b−1,2b−1−1)

这个操作在数值上模拟了量化 (x 被限制在离散值上),但 x^\hat{x}x^ 仍然是浮点数,可以用 FP32 精度计算梯度。

4.2 STE(Straight-Through Estimator)

round\text{round}round 函数不可微,它的梯度几乎处处为 0,无法传递任何信息。STE 的解决方案简单粗暴:

∂L∂x≈∂L∂x^\frac{\partial \mathcal{L}}{\partial x} \approx \frac{\partial \mathcal{L}}{\partial \hat{x}}∂x∂L≈∂x^∂L

即将 round 的梯度直接跳过,看作恒等映射。

复制代码
前向:          x ──→ round ──→ x_q ──→ dequant ──→ x_hat ──→ 后续计算
反向:          x ←── [STE 跳过] ←── x_q ── [STE 跳过] ── x_hat ←── ∂L/∂x_hat

4.3 QAT vs PTQ

维度 PTQ QAT
需要训练 不需要 需要(微调数轮)
精度 较低 较高(可恢复 80-90% 的精度损失)
时间 几分钟(校准) 数小时到数天
需要数据 少量校准集(~128 条) 需要训练集
适用场景 快速部署 精度敏感场景

五、GPTQ------基于二阶信息的量化

GPTQ(Generative Pre-Trained Transformer Quantization)是目前 LLM 量化中最主流的方法之一。它的核心思想是:量化一个权重后,调整剩余权重来补偿误差。

5.1 Optimal Brain Quantizer 的数学

出发点是一个逐层优化问题。对于权重矩阵 WWW 的每一行 www(对应一个输出通道),给定校准数据 XXX,损失为:

L(w)=∥Xw⊤−Xw^⊤∥22\mathcal{L}(w) = \|Xw^\top - X\hat{w}^\top\|_2^2L(w)=∥Xw⊤−Xw^⊤∥22

其中 w^\hat{w}w^ 是量化后的权重行。这个损失衡量量化前后输出的差异。

对 www 中第 iii 个元素 wiw_iwi 做量化,引起的损失变化(二阶泰勒展开):

δLi=12(wi−quant(wi))2H−1ii\delta\mathcal{L}i = \frac{1}{2} \frac{(w_i - \text{quant}(w_i))^2}{H\^{-1}{ii}}δLi=21H−1ii(wi−quant(wi))2

其中 H=2X⊤XH = 2X^\top XH=2X⊤X 是 Hessian 矩阵。GPTQ 选择量化那些 H−1iiH\^{-1}_{ii}H−1ii 最大(即对精度影响最小)的权重。

5.2 核心公式

量化第 iii 个权重后,对剩余权重做补偿:

δF=−wi−quant(wi)H−1iiH:,i−1\delta_F = -\frac{w_i - \text{quant}(w_i)}{H\^{-1}{ii}} H^{-1}{:,i}δF=−H−1iiwi−quant(wi)H:,i−1

这本质上是利用 Hessian 信息,将量化误差在剩余权重中"分摊",使总输出误差最小化。

5.3 手算示例:2×2 权重矩阵的 GPTQ

设 W=(1.2−0.80.50.3)W = \begin{pmatrix} 1.2 & -0.8 \\ 0.5 & 0.3 \end{pmatrix}W=(1.20.5−0.80.3),校准数据 X=(1.00.50.01.0)X = \begin{pmatrix} 1.0 & 0.5 \\ 0.0 & 1.0 \end{pmatrix}X=(1.00.00.51.0)。

Step 1: 计算 Hessian 和 Hessian 逆

H=2X⊤X=2(1.00.50.51.25)=(2.01.01.02.5)H = 2X^\top X = 2 \begin{pmatrix} 1.0 & 0.5 \\ 0.5 & 1.25 \end{pmatrix} = \begin{pmatrix} 2.0 & 1.0 \\ 1.0 & 2.5 \end{pmatrix}H=2X⊤X=2(1.00.50.51.25)=(2.01.01.02.5)

H−1=12.0×2.5−1.0×1.0(2.5−1.0−1.02.0)=14(2.5−1.0−1.02.0)=(0.625−0.250−0.2500.500)H^{-1} = \frac{1}{2.0 \times 2.5 - 1.0 \times 1.0} \begin{pmatrix} 2.5 & -1.0 \\ -1.0 & 2.0 \end{pmatrix} = \frac{1}{4} \begin{pmatrix} 2.5 & -1.0 \\ -1.0 & 2.0 \end{pmatrix} = \begin{pmatrix} 0.625 & -0.250 \\ -0.250 & 0.500 \end{pmatrix}H−1=2.0×2.5−1.0×1.01(2.5−1.0−1.02.0)=41(2.5−1.0−1.02.0)=(0.625−0.250−0.2500.500)

Step 2: 对第一列进行量化(从 WWW 的第一行开始)

对 W0,0=1.2W0,0 = 1.2W0,0=1.2,假设 INT4 量化到 q=1.0q = 1.0q=1.0(量化误差 δ=−0.2\delta = -0.2δ=−0.2)。

补偿(调整第二列第一行的权重):

δF=−−0.2H00−1×H01−1=−−0.20.625×(−0.250)=−0.08\delta_F = -\frac{-0.2}{H^{-1}{00}} \times H^{-1}{01} = -\frac{-0.2}{0.625} \times (-0.250) = -0.08δF=−H00−1−0.2×H01−1=−0.625−0.2×(−0.250)=−0.08

更新 W0,1=−0.8+(−0.08)=−0.88W0,1 = -0.8 + (-0.08) = -0.88W0,1=−0.8+(−0.08)=−0.88

对 W1,0=0.5W1,0 = 0.5W1,0=0.5,假设 INT4 量化到 q=0.5q = 0.5q=0.5(量化误差 δ=0.0\delta = 0.0δ=0.0,巧合)。

补偿:δF=0\delta_F = 0δF=0,不需调整 W1,1W1,1W1,1。

Step 3: 对第二列量化

更新后的第二列 −0.88,0.3-0.88, 0.3−0.88,0.3,按常规量化。

虽然这个 2×2 示例很小,但核心思想是清晰的:GPTQ 量化一个权重后,用 Hessian 信息调整邻近权重来"吸收"量化误差。


六、AWQ------激活感知的量化

6.1 核心洞察

AWQ(Activation-Aware Weight Quantization)的作者发现了一个关键现象:LLM 权重中少数通道(约 1%)的激活值远大于其他通道。这些"显著通道"对模型输出质量至关重要,但它们同时也是量化的难点------因为 outlier 会拉大 scale,降低整体精度。

6.2 方法与 GPTQ 的区别

AWQ 不试图用 Hessian 做最优补偿,而是更简单的方法:

  1. 用校准数据计算每个通道的激活值统计量
  2. 识别显著通道(激活值大的通道)
  3. 对显著通道的权重乘以一个缩放因子 s>1s > 1s>1,将量化负担转移到非显著通道

为什么有效 :乘以 sss 后再做对称量化,相当于对显著通道保留了更多量化等级------sss 越大,显著通道的量化分辨率越高。

6.3 AWQ vs GPTQ

维度 GPTQ AWQ
方法 Hessian 补偿 Activation-aware scaling
复杂度 高(O(d3)O(d^3)O(d3) Hessian 逆) 低(仅统计激活值)
精度 高 相当或略好
实现难度 复杂 简单
校准数据需求 需要 需要

七、量化的优点

量化在工程实践中的核心优势体现在四个维度:

7.1 显存大幅减少

这通常是最直接的动机。以 7B 模型为例:

7B×bits per param=model size \text{7B} \times \text{bits per param} = \text{model size} 7B×bits per param=model size

精度 模型大小 3090(24 GB)剩余 可容纳 KV Cache(序列长)
FP16 14 GB 10 GB 约 40K tokens
INT8 7 GB 17 GB 约 70K tokens
INT4 3.5 GB 20.5 GB 约 85K tokens

7.2 推理速度提升

低位宽整数运算比浮点运算快得多:

  • FP16 Tensor Core:312 TFLOPS(3090)
  • INT8 Tensor Core:624 TFLOPS(3090)
  • INT4 Tensor Core:1248 TFLOPS(5090,原生支持)

更重要的是,减少内存搬运------量化后的权重只有 FP16 的 1/2(INT8)或 1/4(INT4)。对于计算密集度低的解码阶段(batch size 小),瓶颈往往在内存带宽而非计算,此时量化的加速效果尤为显著:

解码速度提升≈FP16 权重大小INT4 权重大小≈4×\text{解码速度提升} \approx \frac{\text{FP16 权重大小}}{\text{INT4 权重大小}} \approx 4\times解码速度提升≈INT4 权重大小FP16 权重大小≈4×

7.3 能效提升

读写更少的数据意味着更低的功耗。根据 NVIDIA 的数据:

操作 能量消耗 INT4 vs FP16
FP16 MAC 约 4 pJ ---
INT8 MAC 约 1 pJ 4× 能效
INT4 MAC 约 0.25 pJ 16× 能效

虽然这是一个"纸面"对比(实际系统需要考虑数据搬运的总能耗),但趋势是明确的。

7.4 更大的有效上下文

量化的最大隐性收益在 KV Cache。如第 41 篇所述,KV Cache 与序列长度成线性增长关系。模型本身越小,留给 KV Cache 的空间越大------这意味着更长的上下文窗口而不需要额外的硬件。


八、量化的缺点与挑战

量化并非免费的午餐。它在带来收益的同时也引入了以下问题:

8.1 精度损失(不可逆)

最核心的代价。量化是将连续值离散化的过程,丢失的信息无法恢复。

Perplexity increase=PPquantized−PPFP16\text{Perplexity increase} = \text{PP}{\text{quantized}} - \text{PP}{\text{FP16}}Perplexity increase=PPquantized−PPFP16

量化方案 Perplexity 上升(7B 模型) 说明
FP16 → INT8 < 0.1 几乎无损
FP16 → INT4(GPTQ) 0.3 - 0.8 可接受
FP16 → INT4(RTN) 1.0 - 5.0 可能不可用
FP16 → INT2 5 - 30+ 基本不可用

对于 7B 模型,perplexity 上升 0.5 意味着什么?在生成质量上可能感觉不出来,但在**基准测试(MMLU、HellaSwag 等)**上可能下降 1-3 个百分点。

8.2 Outlier 敏感------INT4 的致命弱点

LLM 的权重中存在一种现象:1% 的权重占据约 50% 的绝对值总和。这些 outlier 极大地限制了量化质量。

考虑实验 3 的结论:

Outlier 幅度(× 标准差) INT4 SQNR INT4 最大误差
0(无 outlier) 24.3 dB 0.012
3× 18.7 dB 0.048
5× 14.2 dB 0.153
10× 8.1 dB 0.502
20× 4.3 dB 1.801

当 outlier 达到 10× 标准差时,INT4 的 SQNR 从 24 dB 暴跌到 8 dB------量化精度几乎崩盘。这就是为什么简单 RTN 在 LLM 上效果差,需要 GPTQ/AWQ 这类更精细的方法。

数学原因 :outlier 拉大了 max⁡(∣x∣)\max(|x|)max(∣x∣),导致 scale 增大,使得正常值的量化等级变得稀疏,整体量化误差上升。

8.3 校准数据依赖

GPTQ、AWQ 等高级量化方法都需要**校准数据集(calibration dataset)**来计算 Hessian 或激活统计量:

  • 校准数据需要具有代表性(通常从训练集中抽取 128-1024 条)
  • 不同任务分布的校准数据会产生不同的量化结果
  • 如果部署场景的数据分布与校准数据不匹配,精度损失会更大

8.4 硬件兼容性与部署复杂度

硬件 INT8 Tensor Core INT4 Tensor Core
RTX 3090 (Ampere) ✓ 支持 ✗ 不支持
RTX 4090 (Ada) ✓ 支持 ✗ 不支持
RTX 5090 (Blackwell) ✓ 支持 ✓ 原生支持
A100 (Ampere) ✓ 支持 ✗ 不支持
H100 (Hopper) ✓ 支持 ✓ 支持

RTX 3090 用户(如你)可以享受 INT8 的 2× 加速,但 INT4 只能通过 weight-only 量化来减小显存,计算仍以 FP16 进行。这是因为 3090 的 Tensor Core 不支持 INT4 矩阵乘法。

W4A16 vs W8A8:这两种广泛使用的格式代表了不同的取舍:

W4A16: 权重 INT4, 激活 FP16vsW8A8: 权重 INT8, 激活 INT8 \text{W4A16: 权重 INT4, 激活 FP16} \quad vs \quad \text{W8A8: 权重 INT8, 激活 INT8} W4A16: 权重 INT4, 激活 FP16vsW8A8: 权重 INT8, 激活 INT8

格式 显存节省 计算加速 硬件要求
W4A16 4× ~1×(计算瓶颈) 无特殊要求(仅需整数反量化)
W8A8 2× 2-3×(INT8 Tensor Core) 需要支持 INT8 Tensor Core

W4A16 在 3090 上只省显存不加速,W8A8 两者兼具。

8.5 "一刀切"的瓶颈

不同的 Layer 对量化的敏感度差异巨大:

  • Attention 层 :对量化更敏感(尤其是 QQQ 和 KKK 投影),因为注意力分数的精度直接影响 token 选择
  • FFN 层:对量化更鲁棒,FFN2 比 FFN1 更敏感
  • Embedding 层:通常不量化(只占模型参数的很小比例,但影响极大)
  • 输出投影(lm_head):极度敏感,通常保留 FP16

这意味着最优量化策略是混合精度------不同层用不同位宽。但这增加了工程的复杂度。

8.6 量化方法选择困境

存在多种量化方法,但没有普适的最优解:

复制代码
精度排序(高→低):QAT > AWQ ≈ GPTQ > PTQ(per-channel) > PTQ(per-tensor) > RTN

复杂度排序(高→低):QAT > GPTQ > AWQ > PTQ > RTN

"一个模型一个量化策略"------针对不同模型(Llama、Mistral、Falcon),最佳超参数不同,可能需要多次尝试。


九、实战:量化实验脚本

实验 1:手算量化误差

对比不同位宽下对称/非对称量化的 SQNR:

复制代码
  Bits Type           Scale      SQNR (dB)   Max Error
  ------ ------------- ---------- ----------- ----------
  8     symmetric     0.0196     48.35       0.0099
  6     symmetric     0.0784     36.12       0.0392
  4     symmetric     0.3571     22.84       0.1429
  3     asymmetric    0.8929     12.51       0.9421
  2     asymmetric    2.0833      4.87       3.4167

关键观察:每减少 1 bit,SQNR 下降约 12 dB(比理论值 6 dB 更大,原因是实际数据分布不均匀)。

实验 2:PTQ vs QAT

用简单的线性回归任务模拟 PTQ 和 QAT 的精度差异:

复制代码
  Method              MSE              Weight Error
  ------------------- ---------------- ----------------
  FP32 (full precision) 0.010000        0.000000
  PTQ (4-bit)           0.045217        0.213456
  QAT (4-bit)           0.027893        0.148932

QAT 将 PTQ 的误差减少了 38%,原因是训练过程中参数自适应了量化噪声。

实验 3:Outlier 影响

向标准正态分布权重中注入不同幅度的 outlier,观察 INT4 SQNR 的崩坏:

复制代码
  Outlier Value   INT8 SQNR    INT4 SQNR    INT4 MaxErr
  --------------- ------------ ------------ ------------
  0               49.12        24.31        0.012
  3               44.87        18.72        0.048
  5               38.43        14.21        0.153
  10              29.56        8.11         0.502
  20              21.34        4.28         1.801
  50              12.78        1.93         6.214

结论:当 outlier 达到 10× 标准差时,INT4 的 SQNR 不到 10 dB------量化基本失效。这就是为什么 LLM 量化需要处理 outlier。

实验 4:GPTQ 简化实现

2×4 权重矩阵上,Round-to-Nearest vs GPTQ 的输出 MSE 对比:

复制代码
  Method              Output MSE   vs RTN
  ------------------- ------------- --------
  Round-to-Nearest    0.042316     1.00×
  GPTQ (simplified)   0.018724     2.26× better

GPTQ 的 Hessian 补偿将输出误差降低了超过一半。


十、总结

量化的核心 Trade-off

量化深度↑⟹{显存↓,速度↑,能效↑精度↓,复杂度↑,部署难度↑\text{量化深度} \uparrow \Longrightarrow \begin{cases} \text{显存} \downarrow, \text{速度} \uparrow, \text{能效} \uparrow \\ \text{精度} \downarrow, \text{复杂度} \uparrow, \text{部署难度} \uparrow \end{cases}量化深度↑⟹{显存↓,速度↑,能效↑精度↓,复杂度↑,部署难度↑

这个 trade-off 是物理上的根本限制 ------bbb 个比特最多表示 2b2^b2b 个离散值,浮点数的连续值域信息必然丢失。

三种量化场景的选择

场景 推荐方案 理由
快速部署,硬件支持 INT8 W8A8 PTQ 几乎无损,2× 加速
显存不足,硬件无 INT4 W4A16 GPTQ/AWQ 4× 显存节省,计算不加速
精度敏感场景 QAT 或 W8A8 精度损失最小
追求极致压缩 INT2 + GPTQ + QAT 组合 精度损失大,但显存极省
相关推荐
IT_陈寒15 分钟前
SpringBoot自动配置差点让我加班到凌晨
前端·人工智能·后端
yumgpkpm29 分钟前
Acceldata ODP(Open Data Platform)3.3.6.4(RHEL9)保姆级完整安装手册
大数据·人工智能·hive·hadoop·kafka·hbase·cloudera
程序员cxuan31 分钟前
腾讯又来一王炸,开源版 WorkBuddy 太夯了!
人工智能·后端·程序员
邓工说电41 分钟前
智慧断路器安全吗?数据加密、离线保护与合规认证全解读
大数据·数据库·人工智能·智能断路器·炜晔科技
阿里云大数据AI技术43 分钟前
Lance 数据检索怎么选,当然阿里云 Milvus 向量湖
人工智能
出海客1 小时前
跨境电商多语言客服知识库怎么建:资料结构、检索边界与人工升级
大数据·人工智能
xsd202411181 小时前
从自主导航到视觉读表:一台工业巡检机器人的全栈技术链路拆解
人工智能
袁哥大话安全1 小时前
巡隐WEBSHELL扫描软件
人工智能·安全·web
论文复现现场1 小时前
8卡4090能跑70B吗?Llama-2显存预算、QLoRA与通信瓶颈
人工智能·深度学习·分布式训练·llama·显存·qlora·算家云
酷虎软件1 小时前
如何用AI创作AI歌曲AI音乐
人工智能