跳至内容
Ludovico's Blog
返回

从权重角度理解均匀量化与向量量化

量化这个词经常把几个不同层次的概念混在一起。对于已经训练好的模型,最直接的问题其实是:

一串 FP16 权重,怎样变成更小的整数或索引;推理时又怎样恢复成可以参与矩阵乘法的近似权重?

本文只从权重角度解释两种常见做法:均匀量化(uniform quantization)和向量量化(vector quantization)。先不讨论激活量化、GPTQ 的 Hessian 或具体硬件 kernel。

先看一个权重块

把线性层权重矩阵切成小组。为了方便说明,假设其中一组只有 4 个权重:

w = [0.80, 0.70, -0.20, 0.10]

真实模型通常会按 group_size=32/64/128 分组。分组的意义是:每一组可以有自己的量化参数,不必让整个矩阵共用一把尺子。

均匀量化:每个权重找最近的刻度

均匀量化先准备一条等间距的整数刻度。以 4 bit、无符号量化为例,整数码是:

q = 0, 1, 2, ..., 15

浮点数不直接存储,而是通过 scaleoffset 映射到这些整数格子:

q=round(woffsetscale)q=\operatorname{round}\left(\frac{w-\text{offset}}{\text{scale}}\right)

反量化时再做相反的变换:

w^=qscale+offset\hat{w}=q\cdot\text{scale}+\text{offset}

均匀量化把每个权重映射到等间距整数刻度

scale 和 offset 从哪里来

给定这一组权重的浮点范围:

w_min = -0.80
w_max =  0.70

以及目标整数范围:

q_min = 0
q_max = 15

先算刻度间距:

scale=wmaxwminqmaxqmin\text{scale}=\frac{w_{max}-w_{min}}{q_{max}-q_{min}}

再让 w_min 对应 q_min

offset=wminqminscale\text{offset}=w_{min}-q_{min}\cdot\text{scale}

这里因为 q_min=0,所以 offset=w_min=-0.80。于是大致得到:

-0.80 -> 0
-0.42 -> 4
 0.10 -> 9
 0.70 -> 15

实际实现也经常使用 zero_point 写法:

q=round(w/scale)+zero_pointq=\operatorname{round}(w/\text{scale})+\text{zero\_point}

两种写法等价,关系是:

offset=zero_pointscale\text{offset}=-\text{zero\_point}\cdot\text{scale}

直觉上,scale 负责“格子间距”,offset 负责“尺子放在哪里”。如果权重分布是非对称的,不减 offset 就无法把真实范围准确对齐到目标整数范围。

qmin 和 qmax 不是算出来的

它们由目标整数格式决定:

格式q_minq_max
4-bit unsigned015
8-bit unsigned0255
4-bit signed-87
8-bit signed-128127

所以流程是:先选 bit 数和 signed/unsigned,再得到 qmin/qmax,最后根据权重范围算 scale/offset

向量量化:一组权重找最近的模板

向量量化换了一个问题。它不再问“每个权重应该落在哪个刻度”,而是问:

这一整组权重,最像码本里的哪个向量?

假设每 4 个权重组成一个向量,码本里有 4 个候选向量:

C0 = [ 0.00,  0.00,  0.00,  0.00]
C1 = [ 0.80,  0.80, -0.10,  0.10]
C2 = [-0.50,  0.50,  0.00,  0.20]
C3 = [ 1.00, -1.00,  0.50, -0.50]

对于:

w = [0.80, 0.70, -0.20, 0.10]

量化器会计算它与 C0/C1/C2/C3 的距离,选择最近的 C1。因此这组权重实际只需要保存:

index = 1

反量化时查表:

codebook[1] -> C1 -> [0.80, 0.80, -0.10, 0.10]

这就是向量量化的核心:保存向量索引,反量化时查回整个向量

向量量化把一个权重块匹配到码本中的候选向量

码本是怎么来的

码本不是凭空出现的,常见来源有两种。

后训练聚类

对已经训练好的浮点权重:

  1. 按固定长度切成很多权重向量;
  2. 使用 K-Means 等聚类算法寻找中心点;
  3. 把聚类中心保存为码本;
  4. 每个权重向量只保存最近中心点的索引。

例如,许多相似的权重向量聚成一类后,类中心就是一个码本向量。这样做不需要重新训练整个模型,但码本质量取决于权重分布和聚类设置。

量化感知训练

也可以把码本向量当成可训练参数:

浮点权重 -> 选择码本向量 -> 前向计算 -> 计算误差 -> 更新码本

实际训练时,离散的索引选择通常需要近似梯度或特殊优化。它比简单的 min-max 映射复杂,但有机会让码本更贴合模型任务。

“码本大小决定 bit 数”到底是什么意思

假设码本有 4 个候选向量:C0/C1/C2/C3。一个权重向量块量化后,只需要保存四者之一的编号:

00 -> C0
01 -> C1
10 -> C2
11 -> C3

因为 2 个 bit 有 2^2=4 种组合,所以 4 个候选向量的索引需要 2 bit:

index bits=log2(K)\text{index bits}=\lceil\log_2(K)\rceil

其中 K 是码本大小。

但这里的 bit 是每个向量块的 bit,不一定是每个权重的 bit。如果一个向量块包含 D 个权重,那么理论平均开销是:

bits per weight=log2(K)D\text{bits per weight}=\frac{\lceil\log_2(K)\rceil}{D}

例如:

码本大小 K向量块大小 D每块索引理论平均值
442 bit0.5 bit/weight
1644 bit1 bit/weight
25648 bit2 bit/weight
25688 bit1 bit/weight

还要加上码本、scale、对齐和其他元数据,因此实际模型大小会高于这个理论值。

两种方法放在一起

从权重存储、反量化和部署角度对比两种量化

对比项均匀量化向量量化
量化对象单个权重一组权重向量
保存内容整数码、scaleoffset向量索引、码本,可能还有 scale
量化方式找最近的等间距刻度找最近的码本向量
反量化q * scale + offsetcodebook[index]
低 bit 精度可能受离群值影响能利用权重之间的相关性
部署复杂度低,硬件支持好高,需要查表和专用实现

一句话总结:

均匀量化保存的是“每个权重对应哪个刻度”;向量量化保存的是“这一组权重对应哪个模板”。前者更容易部署,后者更善于利用权重之间的共同模式。


分享:

上一篇
从 LoRA 到 QLoRA、QA-LoRA:低秩更新如何进入量化模型
下一篇
HQQ 算法解读:不用校准数据,怎样把大模型权重压到 4 bit