B 当你给权重排了座次

当你给权重排了座次

Jun 10, 2025
ai

K-quants 把说明书也量化之后,一个 160 亿参数的模型,量化常量从约 2 GB 砍到了约 1 GB。

但事情还没完。面前还有两个问题。

第一个:到目前为止,量化都是一对一的——一个权重对应一个整数编码。这叫标量量化。能不能一次处理一组权重?8 个权重打包,共享一个编码。

第二个:前面不管是 legacy 还是 K-quants,所有 block 一视同仁。但有些权重改一点点,输出就天翻地覆;有些改得面目全非,模型几乎不受影响。能不能让重要的权重分到更宽的桶?

这两个问题的答案,就是 I-quants 和重要性矩阵。它们是同一时期引入的,概念上独立,但经常一起出现。下载页里的 IQ2、IQ3,那个 I 指的就是"importance"。

八个打包,挑一个

前两篇里的量化是标量级别的。一个权重 → 一个 INT4 整数。一对一。

向量量化把 8 个权重编成一组,看作一个 8 维向量。不给每个权重单独找桶,而是给这整组向量找一个"最像的参考向量"。参考向量的编号就是编码。

想象一个极简版:把维度降到 2,密码本缩小到 4 个参考向量:

$$ \text{codebook} = \{(1, 0),\ (0, 1),\ (1, 1),\ (0.5, 1.5)\} $$

现在有一个权重向量 $\mathbf{w} = [-0.8,\ 1.2]$。找最近邻:

第一步,取绝对值:$|\mathbf{w}| = [0.8,\ 1.2]$。为什么取绝对值?密码本里全是正向量——这能省一半空间。正负号另外存。

第二步,算到四个参考向量的距离。$(0.5, 1.5)$ 最近(你可以心算一下欧氏距离验证)。密码本编号 = 3(从 0 开始)。

第三步,还原长度。scale $S$ 是原始向量的模除以参考向量的模:

$$ S = \frac{\|\mathbf{w}\|}{\|\mathbf{r}\|} = \frac{\sqrt{0.8^2 + 1.2^2}}{\sqrt{0.5^2 + 1.5^2}} = \frac{\sqrt{2.08}}{\sqrt{2.5}} = \frac{1.442}{1.581} \approx 0.912 $$

第四步,存符号。$\mathbf{w}$ 的第一维是负、第二维是正 → 符号字节 = 0b01(或者说 $0 \times 2^0 + 1 \times 2^1 = 2$,怎么编码都行,细节不重要)。

还原时用 $S \times$ 参考向量,再乘回符号:

$$ \tilde{\mathbf{w}} = S \times \mathbf{r} \times \text{signs} = 0.912 \times (0.5, 1.5) \times (-1, +1) = (-0.456,\ 1.368) $$

误差 = $(-0.344,\ 0.168)$。不小。但别忘了这是在 2 维、4 个参考向量的极端简化下。GGUF 实际用的是 8 维、256 个参考向量,加上符号字节让有效数量膨胀到 $256 \times 2^8 = 65536$——精度远高于这个玩具例子。

回到实际的存储计算。一个 8 权重向量用 IQ2 量化:

项目大小
符号字节8 bit
密码本编号(256 选 1)8 bit
scale S(FP16,256 向量共享)$16 / 256 = 0.0625$ bit
$$ \text{IQ2 每权重} = \frac{8 + 8 + 0.0625}{8} \approx 2.01\ \text{bpw} $$

对比 legacy Q4_0 的 4.5 bpw 和 K-quant Q4_K 的约 4.3 bpw,压缩率直接翻了一倍。一个 160 亿参数的模型:Q4_0 约 9 GB,Q4_K 约 8.6 GB,IQ2 约 4 GB。

4 GB。刚好塞进一张 8 GB 显卡,还有充裕的空间给 KV cache。

代价也明显。标量量化丢的是每个权重的尾数,向量量化连"方向"都丢了。8 个权重之间的比例关系消失了——只能还原整体长度。这也是为什么 IQ2 的困惑度通常比 Q4_K 差一截。不是在同一个赛道上比的——标量 4 bit vs 向量 2 bit,差了整整一倍的基础精度。

密码本里存的 256 个参考向量来自哪里?代码里直接硬编码的,没有训练过程(有个 PR 引用了 E8 晶格的论文,但实际代码似乎没用)。8 维空间的 256 个方向——大概是通过某种均匀采样选的。Kawrakow 的原话引用了 QuIP# 论文作为灵感来源,但细节只有代码知道。

重要的人坐前排

向量量化解决的是"怎么组织桶"。重要性矩阵解决的是"桶分给谁"。

核心洞察很简单:不是所有权重都平等。

考虑一个权重矩阵 $W$,输入激活 $x$,输出 $y = Wx$。如果某个权重 $w_{ij}$ 改变了一个很小的量,输出 $y_i$ 却变化很大——这个权重是"重要的"。反过来,改完跟没改一样——不重要。

GGUF 用激活值的平方来量化这个观念。跑一次校准数据集的推理,拿到每一层输出激活 $y$:

$$ I_i = y_i^2 $$

$I_i$ 越大的行,说明这行权重对输出有更大影响力。再叠加上权重本身的大小:

$$ I_{ij} = y_i^2 + \sqrt{\sigma^2 + w_{ij}^2} $$

$\sigma$ 是这一行的权重标准差——防止 $w_{ij}$ 恰好为零时整项消失,纯工程细节。

有了重要性矩阵,量化的逻辑多了一步。之前我们用一个 scale $S$ 和零点 $Z$ 做完量化和反量化,所有 block 平等对待。现在反量化引入一套独立的参数 $S'$ 和 $Z'$,专门服务重要的权重。

目标是让重要权重的重建误差尽可能小,不重要的可以大一些:

$$ L = \sum_i \sum_j I_{ij} \cdot (w_{ij} - \tilde{w}_{ij})^2 $$

不重要权重的 $I_{ij}$ 小 → 误差被打了折扣。重要权重的 $I_{ij}$ 大 → 误差被放大,优化器会优先照顾它们。

固定 $S$ 和 $Z$(还是按之前的方式从区间极值算),$S'$ 和 $Z'$ 有闭式解——一个带权最小二乘问题。GGUF 还多做了一步:在 $S$ 附近扫 36 个候选值,挑让加权损失最小的那个。大一点的 $S$ 意味着 clip 掉更多极端值,把精度倾斜给靠近零的权重——这些往往数量多,量化后整体误差更容易控制。

整个过程不增加任何推理开销。重要性矩阵只在量化时多算了几步,最终的 GGUF 文件里只多存了一组更"聪明"的 $S'$ 和 $Z'$,不存额外数据。从文件外部完全看不出一个模型有没有用过重要性矩阵(GitHub 上有人为此很抓狂——没法追溯一个 GGUF 文件到底是怎么量化的)。

实际效果:同样的 Q4_K_M,加上重要性矩阵后困惑度能降低 10-30%。低 bit 场景下改善明显——IQ2 这种极端压缩,没有重要性矩阵几乎没法用。

校准数据集通常用 Wikipedia 的几百条文本。有人担心过拟合——模型会不会变成 Wiki 专家?作者认为不太可能,但最稳妥的做法是用跟你的场景接近的数据做校准。写代码的用代码数据集,做法律的用法律文本。

最后那排名字

回到第一篇开头让我愣住的那一排名字。Q4_0、Q4_K_M、Q5_1、IQ2、IQ3。

现在能翻译了。

Q 后面的数字是基础 bit 数。下划线后面的内容告诉你方案类型

_0_1:legacy 对称/非对称量化。桶少,说明书大,朴素但可靠。

_K:K-quant。套娃压缩了说明书,super-block 让内存访问更连续。后缀 S/M/L 决定敏感层的保护力度——S 省空间但激进,M 折中(大多数人的选择),L 保守。

IQ:I-quant。向量量化,8 个权重打包匹配密码本。bit 数是约数——IQ2 约 2 bpw,IQ3 约 3 bpw,IQ4 约 4 bpw。后缀同样控制混合精度策略。

我之前觉得这一排名字是密码。现在看,它确实是一套密码——只是加密算法不难。双字母体系:Q 开头是标量量化,IQ 开头是向量量化。数字是基础 bit,下划线后面是具体的压缩策略和敏感层分配。

选择模型的过程,就是一个权衡三角形:

Q8_0 → 几乎无损,但文件跟 FP16 差不了多少。跑不起就别想。

Q4_K_M → 多数人的答案。4 bit 基础配 K-quant 的说明书压缩,M 档给关键层留余量。

IQ2 → 最小、最快、最笨。显存实在不够时的最后退路。

尽头

这趟从 legacy 走到 I-quants,本质上是一个不断追问"还能省哪里"的过程。

先省权重:FP16 → INT4,16 bit 砍到 4 bit。

再省说明书:FP16 → INT8 scale,每 block 省 6 bit。

然后省桶的组织方式:标量 → 向量,8 个权重共享一个编码。

最后省桶的分配:不重要权重的误差打个折,把精度留给关键层。

每一步都在多丢一点信息。丢到 IQ2 的时候,丢失的已经不单是每个权重的尾数了,连权重之间的比例关系都消失了。

量化不是魔术。它只是在告诉你:你愿意用多少精度,换多大的模型。

diet 没有尽头。尽头是你的显存。


参考资料

TouchingFish.top