论文精读 · ICLR 2023 · POST-TRAINING QUANTIZATION
GPTQ:从公式 1 到公式 2
把二阶量化的每一步拆开
GPTQ 最难的并不是记住“用 Hessian 逆补偿误差”,而是理解:它究竟在最小化什么?公式 (2) 为什么必然从公式 (1) 出发?分母为什么是逆 Hessian 的对角元素?本文沿原论文符号,把这条链完整推一遍。
原论文:GPTQ: Accurate Post-Training Quantization for Generative Pre-trained Transformers
Frantar, Ashkboos, Hoefler, Alistarh · arXiv:2210.17323v2 · ICLR 2023
先记住四句话
- GPTQ 的目标不是让量化权重离原权重最近,而是让校准输入上的层输出尽量不变。
- 论文公式 (1) 是层输出重构目标;按权重矩阵的行拆开后,它正好是一个凸二次型,Hessian 为 2XX^\top。
- 论文公式 (2) 来自“第 q 个权重必须落在量化格点”这一线性约束下的二次优化;H^{-1}_{:,q} 给出其他权重最便宜的补偿方向。
- 公式 (2) 对固定 q 的补偿是精确全局最优,对下一步选哪个 q 是贪心单步最优;GPTQ 为速度又用固定列顺序替代了 OBQ 的逐行贪心顺序。
问题背景
01GPTQ 到底要解决什么
一个线性层在浮点模型里计算 Y=WX。权重 W 可能有几十亿个 FP16 元素;把它压成 4 bit,模型体积可接近四分之一,也能降低推理时的显存带宽压力。但每个权重都必须被舍入到稀疏的量化格点,得到 \widehat W,输出就会从 WX 变成 \widehat WX。
常见误解:逐元素最近舍入已经最好
逐元素 RTN 只保证每个
|w-\widehat w| 局部较小,却没有考虑输入激活。某个方向几乎从不被激活,即使权重偏差较大也可能无害;另一个方向在真实数据上很活跃,同样大小的权重偏差会被放大成巨大输出误差。模型真正执行的是矩阵乘法,不是比较两张权重表。
GPTQ 属于训练后量化(PTQ):不重新训练模型,只用一小批校准数据收集各层输入 X,逐层寻找低比特权重。它继承 OBQ(Optimal Brain Quantization)的二阶误差补偿,并用固定顺序、lazy batch update 与 Cholesky 重构把它扩展到 175B 模型。
FP16 权重 W→校准激活 X→构造 H=2XXᵀ→逐列量化→未量化列补偿→低比特 Ŵ
论文原式
02公式 (1):量化目标究竟是什么
论文首先把每个线性层单独处理。原文公式 (1) 是:
论文沿用矩阵 2-范数记法;这里的语义是对校准样本上的全部输出误差求平方和,通常更明确地写成 Frobenius 范数 \|\cdot\|_F^2。
W\in\mathbb R^{d_{out}\times d_{in}}
原始浮点权重矩阵。每一行产生一个输出通道,每一列对应一个输入特征。
\widehat W
待寻找的量化权重。其元素不能任意取实数,而要落在给定 bit 数、scale 和 zero-point 确定的量化格点上。
X\in\mathbb R^{d_{in}\times N}
N 个校准 token 在当前层入口处的激活。列是样本位置,行是输入特征。
WX-\widehat WX
同一批输入经过浮点层和量化层后的输出差。GPTQ 直接保护的是这个量,不是参数本身。
\arg\min
寻找使输出平方误差最小的量化权重,而不是只求最小误差数值。
为什么它能按行拆开
Frobenius 范数是所有元素平方和。把 W 的第 r 行记为 w_r^\top,就有:
每一项只涉及权重矩阵的一行,因此不同输出行可以独立量化;所有行又共享同一个输入 X,也就共享同一个 Hessian。这一“逐行独立、曲率共享”的结构,是后续大规模加速的基础。
公式 (1) 的一句话翻译
给定一小批真实输入,找一张低比特权重表,让这一层在这些输入上的答案尽可能接近原层。它是一种局部层重构代理目标,不等同于直接最小化整个语言模型的最终 loss。
关键桥梁
03从公式 (1) 到 Hessian 二次型
只看任意一行,把量化后的变化定义为 \delta w=\widehat w-w。因为 w-\widehat w=-\delta w,平方会消掉符号:
步骤 2:把范数展开成矩阵乘法
行向量的 2-范数平方等于它和自身转置的内积。\delta w^\top X 是一个 1\times N 行向量,所以:
把右边的转置拆开 (\delta w^\top X)^\top=X^\top\delta w,再把两个 \delta w 提到两端:
中间的 XX^\top 是一个只依赖校准输入、与权重无关的 d_{in}\times d_{in} 常量矩阵。
步骤 3:定义 Hessian
为了写成标准二阶形式,令 H=2XX^\top:
这里不是“用二阶泰勒近似猜一个损失”。层重构损失本身就是关于 \delta w 的二次函数,所以二阶展开是精确的:原点处常数项为 0,梯度为 0,三阶及更高项不存在。
为什么一阶项为 0
\nabla\mathcal L=2XX^\top\delta w。在原权重处 \delta w=0,输出误差恰好为 0,因此梯度也为 0。
H 的几何含义
H 描述不同权重方向的扰动会怎样在校准输入上形成输出误差;大曲率方向动一点就很贵。
为什么会出现 H⁻¹
我们已知某一坐标必须移动,要求其余坐标以最低代价联动。逆曲率把约束施加的“力”转换成最低损失的位移。
为什么需要 damping
若校准样本不足或特征共线,XX^\top 可能奇异。实现会用 H+\lambda I 保证可逆并稳定 Cholesky。
核心推导
04公式 (2):选谁量化,其他权重怎样补偿
论文在回顾 OBQ 时给出公式 (2)。它把两个动作写在一起:
更严谨地说,第一式选择的是索引 q^*;F 表示当前仍未被固定、还能参加补偿的权重集合。
先统一符号,避免正负号看乱
定义取整造成的必需变化
r_q=\operatorname{quant}(w_q)-w_q。于是论文第二式也可写成
\delta_F=\frac{r_q}{[H_F^{-1}]_{qq}}(H_F^{-1})_{:,q}。两种写法完全相同,因为
-(w_q-quant(w_q))=r_q。
4.1 固定候选 q 后,优化问题是什么
现在先不讨论“选哪个 q”,只假设第 q 个权重已经决定要量化。它的第 q 维必须变化 r_q,而其他未量化权重仍可自由调整:
e_q 是第 q 个标准基向量;左乘 e_q^\top 只是从完整扰动中取出第 q 个坐标。约束说的是:无论其他权重怎么帮忙,第 q 个权重必须准确落到量化格点。
4.2 用拉格朗日乘子求补偿方向
这是一个严格凸二次目标 + 单个线性等式约束的问题,可以用一个拉格朗日乘子 \lambda 精确求解。下面每一步只做一件事,不合并。
第 1 步 · 写出拉格朗日函数
把目标函数和约束用乘子 \lambda 合并成一个无约束函数:
第 2 步 · 对扰动向量 δ_F 求梯度并令其为零
二次项求导得 H_F\delta_F,线性项求导得 \lambda e_q,因此驻点条件是:
第 3 步 · 解出 δ_F(还含未知的 λ)
把上式移项,两边左乘 H_F^{-1}:
这里已经能看出关键信息:H_F^{-1}e_q 就是逆 Hessian 的第 q 列。也就是说,最优补偿方向不是谁凭经验指定的,而是驻点方程直接决定的——其余权重必须沿着这一列的方向联动。
第 4 步 · 代回约束,解出 λ
补偿必须满足“第 q 维恰好变化 r_q”这个约束。把第 3 步的 \delta_F 代入 e_q^\top\delta_F=r_q:
第 5 步 · 把二次型识别成对角元素
注意 e_q^\top H_F^{-1}e_q 就是从逆 Hessian 里取出第 q 行第 q 列那一个数,即对角元素:
于是第 4 步的方程变成一个标量方程:
第 7 步 · 把 λ 代回,得到论文的补偿式
把第 6 步的 \lambda 代回第 3 步的 \delta_F=-\lambda H_F^{-1}e_q:
这正是论文公式 (2) 的第二部分(最优补偿)。
第 8 步 · 逐坐标验证它确实满足约束
把补偿写成逐分量形式:
当 j=q 时,分子里的 [H_F^{-1}]_{qq} 与分母抵消,得到 \delta_q^*=r_q——第 q 个权重准确落到量化格点,约束满足;当 j\ne q 时,\delta_j^* 就是第 j 个未量化权重为补偿这次量化而承担的位移。
4.3 把补偿代回,得到第一部分的选点分数
现在我们知道:一旦决定量化第 q 个权重,其他权重会以上面的最优方式补偿。那么这一步不可避免的最小损失是多少?把 \delta_F^* 代回二次目标 \Delta\mathcal L=\tfrac12\delta_F^\top H_F\delta_F:
A · 代入并利用 H_F H_F⁻¹=I
中间三项 H_F^{-1}H_FH_F^{-1}=H_F^{-1},于是化简为 e_q^\top H_F^{-1}e_q=[H_F^{-1}]_{qq}。
B · 约掉一个对角元素
这就是“量化 q、并允许其他权重做最佳补偿后,仍然躲不掉的最小输出损失”。
C · 去掉共同常数,得到选点判据
对每个候选 q,比较的都是这个最小损失。常数 \tfrac12 对所有候选都一样,不改变谁最小,所以论文把它省掉,选损失最小的那个:
这正是论文公式 (2) 的第一部分(贪心选点)。论文写成 w_q=\arg\min_{w_q}\cdots,但从语义看,它选的是索引 q^*。
分子 r_q^2
该权重距离量化格点有多远。越远,必须承受的坐标变化越大。
分母 [H_F^{-1}]_{qq}
在当前剩余自由度里,这个坐标变化有多大“可补偿空间”。越大,达到同样第 q 维位移的最低二次代价越小。
整列 (H_F^{-1})_{:,q}
各未量化权重应该朝哪个方向、移动多少,才能最有效地抵消 q 的量化误差。
概念边界
05为什么是最优,又为什么不是全局最优
固定 q:精确全局最优
若阻尼后的 H_F\succ0,目标是严格凸二次函数,约束是线性等式。KKT 条件充分且必要,求出的补偿唯一且全局最优。
选择下一项:单步最优
每个候选 q 的最小损失都已精确算出,再取最小者,所以这是当前一步的 greedy-optimal 选择。
完整离散量化:不保证全局最优
所有权重最后都要落到离散格点,不同步骤互相耦合。第一步最便宜,不代表最终整条决策路径是组合全局最优。
GPTQ 还进一步近似
OBQ 每行都贪心选 q;GPTQ 为让所有行共享顺序并高效批处理,改成固定列顺序。因此公式 (2) 是理论起点,不是 Algorithm 1 原封不动的执行顺序。
最准确的一句话
公式 (2) 证明的是:如果现在必须量化一个权重,那么它能给出每个候选的精确最低单步代价和对应的最佳连续补偿;它没有证明全部低比特权重的离散组合是全局最优。
手算验证
06一个 2×2 例子:补偿到底补了多少
设单行权重为 w=[1.30,0.80]^\top,校准数据给出的 Hessian 为:
量化第一个权重:1.30\to1.25,所以 r_1=-0.05。
按公式 (2) 补偿
第一个坐标准确落到 1.25;第二个尚未量化的权重临时从 0.80 移到 0.8333。代价变成:
结果
补偿把单步输出误差从 0.005 降到 0.00333,下降约 33.3%。它没有消灭第一个权重的取整误差,而是利用第二个权重的自由度,让两者在真实输入方向上造成的输出偏差部分相消。
算法落地
07从 OBQ 公式到 GPTQ Algorithm 1
朴素 OBQ 精度高,但每一行都要反复寻找当前最便宜的 q、更新有效逆 Hessian,扩展到大模型太慢。GPTQ 保留“量化一个位置后,让未量化位置吸收误差”的核心,做了三项关键改造。
固定列顺序
不再为每行做独立贪心排序,而按共同的列顺序处理。各输出行便能共享 Hessian 信息并向量化执行。
Lazy batch update
块内逐列立即修正,跨块的大范围更新先累积,块结束后用矩阵乘一次性写回,减少内存带宽瓶颈。
Cholesky reformulation
对阻尼后的逆 Hessian 信息做 Cholesky 分解,避免逐步删行列造成的数值误差,并高效提供递归更新所需因子。
逐行并行
同一列的所有输出行一起量化;每行误差不同,但共享输入曲率结构,适合 GPU 上的批量矩阵运算。

原论文 Figure 2:GPTQ quantization procedure。粗框是当前列块;块内递归逐列量化,块结束后批量更新右侧尚未量化的区域。图把固定顺序、lazy batch update 和 Cholesky 重构集中画在一起。
打开 arXiv 源码中的原始矢量 PDF。
概念上,量化第 i 列后对后续列 j 的更新仍可理解为公式 (2) 的矩阵化版本:
不要把概念式和伪代码中的符号机械逐项对照
论文 Algorithm 1 在 Cholesky reformulation 后复用
H^{-1} 这个符号表示分解后的因子信息,因此伪代码里的对角项形式与未经分解的完整逆 Hessian 概念式不同。两者表达同一误差传播逻辑,但中间表示已经改变。
论文公式 (3)–(5) 在整条链里的位置
| 原论文位置 | 作用 | 与公式 (1)(2) 的关系 |
| Eq. (1) | 定义层输出重构目标 | 回答“到底最小化什么” |
| Eq. (2) | OBQ 的贪心选点与最优补偿 | 回答“量化一个权重后怎样最小损失” |
| Eq. (3) | 某坐标被固定后,更新剩余逆 Hessian | 让下一轮继续在正确的有效子问题上工作 |
| Eq. (4)–(5) | 把逐列更新整理成块矩阵更新 | 减少反复访问大权重矩阵 |
| Algorithm 1 | 固定顺序 + 分块 + Cholesky 的完整 GPTQ | 把理论补偿变成可在超大模型上运行的算法 |
边界与实践
09GPTQ 的优势、局限与常见混淆
| 问题 | 结论 |
| 是否需要训练 | 不需要反向训练;需要少量校准数据做前向,收集各层输入激活。 |
| Hessian 是否来自模型训练 loss | 这里核心是层输出重构损失的 Hessian 2XX^\top,不是直接计算整个语言模型交叉熵的完整 Hessian。 |
| 是否真的显式求“大模型全 Hessian” | 不是。按层处理,并在一行权重的输入维度上构造共享的 Gram/Hessian 矩阵。 |
| 公式 (2) 是否等于 GPTQ 全部创新 | 不是。它来自 OBQ,是理论起点;GPTQ 的贡献在于把这套补偿通过固定顺序、分块和稳定分解扩展到超大模型。 |
| act-order / desc_act 是否来自原论文 Algorithm 1 | 不是原论文默认步骤,而是后续 GPTQ-for-LLaMa、AutoGPTQ 等生态常见扩展。 |
| group_size=128 是否是原论文默认 | 不是。原论文主设置采用 row-wise 网格,并额外展示 g1024/g128 消融;g128 是后续部署生态常见选择。 |
优势
低 bit 权重量化精度高;只需校准前向;4-bit GPU 推理生态成熟;对 RTN 在 3-bit 附近的崩塌有明显改善。
局限
依赖校准分布;逐层局部目标不等于端到端最优;量化阶段比简单 RTN/AWQ 搜索更重;主要处理权重误差,不直接解决低 bit 激活量化。
最终把整篇压缩成一条推导链
\|WX-\widehat WX\|^2(保护层输出) → 按行拆分 →
\frac12\delta^\top H\delta, H=2XX^\top(精确二次型) → 强制
\delta_q=r_q(量化约束) → 拉格朗日/KKT →
\delta^*=r_qH^{-1}_{:,q}/[H^{-1}]_{qq}(最佳补偿) →
\Delta L_q^*=r_q^2/(2[H^{-1}]_{qq})(单步最小损失) → 固定顺序、分块、Cholesky(GPTQ 工程化)。