WangYu::Space

cat /dev/mind

大语言模型量化技术(二):GPTQ

分类:机器学习标签: LLM创建时间:2026-07-01 22:11:00

背景

常用的量化策略有两种:一种只量化模型权重,另一种同时量化权重和激活值。前者称为 Weight-Only Quantization,后者称为 Weight-and-Activation Quantization。你可能在博客或论文中见过 W8A8、W4A16、W4A8、W4A4 等表述:其中 W 代表权重(Weight),A 代表激活值(Activation),数字代表量化位宽。例如,W8A8 表示权重和激活值均量化为 8 bit;W4A16 表示权重量化为 4 bit,激活值保持为 16 bit。

本文介绍的 GPTQ(Generalized Pre-trained Transformer Quantization)只量化权重,并在模型训练完成后执行,属于后训练量化(Post-Training Quantization,PTQ)方法。名称中的 GPT 代表 Generalized Pre-trained Transformer,Q 代表 Quantization,即一种面向预训练 Transformer 模型的量化方法。

GPTQ 的基本原理

权重量化中最简单的方法是 Round-to-Nearest (RTN) 量化,它使用最朴素的量化原理,通过缩放因子将高精度浮点数映射为整数,量化的核心目标是让量化后的权重尽可能接近原始权重。经过量化后,权重与原始权重会存在差异,这必定会引入误差。假设权重为 WW,量化后的权重为 W^\hat{W},则量化误差可以表示为:

E=WW^F2E = \|W - \hat{W}\|_F^2

这里 F2\|\cdot\|_F^2 是 Frobenius 范数的平方,表示矩阵中所有元素的平方和(详见后文附录)。RTN 的目标是最小化 EE,即让量化后的权重尽可能接近原始权重。

GPTQ 采用了一种更为复杂的策略,它不仅考虑了权重自身的变化,还考虑到了权重的变化对输出的影响。GPTQ 使用一批输入数据来估计量化误差对模型输出的影响。设输入为 XX,则输出为 Y=WXY = W X,量化后的输出为 Y^=W^X\hat{Y} = \hat{W} X,则量化误差可以表示为:

E=(WW^)XF2E = \|(W - \hat{W}) X\|_F^2

GPTQ 通过最小化 EE 来优化量化参数,从而保证在实现量化的同时,模型的输出尽可能接近原始输出。

GPTQ 并非一次性对整个权重矩阵进行量化,而是采用逐列量化的方式。GPTQ 每次对权重矩阵中的一个列向量进行量化,并在量化过程中考虑当前列量化后引入的误差对输出的影响,并调整后续列的参数值,试图通过调整其他列的值来补偿当前列量化引入的误差。

GPTQ 的理论基础

GPTQ 的基本思路并不难理解,但要看懂其计算流程,还需要一些数学推导。本节介绍 GPTQ 所依赖的理论基础。

1. 量化误差的定义

以一个线性层 Y=WXY = W X 为例,其中,WRdout×dinW \in \mathbb{R}^{d_{\text{out}} \times d_{\text{in}}} 是原始权重,XRdin×nX \in \mathbb{R}^{d_{\text{in}} \times n} 是校准样本送入该层的激活,YY 是该层输出。

量化后的权重为 W^\hat{W},GPTQ 希望量化前后的输出尽可能接近,即最小化:

minW^YW^XF2=minW^(WW^)XF2\min_{\hat{W}} \|Y - \hat{W} X\|_F^2 = \min_{\hat{W}} \|(W - \hat{W}) X\|_F^2

令权重误差为:

ΔW=WW^\Delta W = W - \hat{W}

则优化目标可以写为:

minW^ΔWXF2\min_{\hat{W}} \|\Delta W X\|_F^2

这个目标的含义是让输出误差尽可能小。之所以使用输出误差的平方和,而非仅衡量权重误差,是因为即使权重变化很小,当输入 XX 的某些维度幅度较大时,输出误差仍可能很大。

2. 逐行量化

wrw_rWW 的第 rr 行,则:

ΔWXF2=r=1doutΔwrX22\|\Delta W X\|_F^2 = \sum_{r=1}^{d_{\text{out}}} \|\Delta w_r X\|_2^2

这意味着不同的行之间的量化误差是相互独立的,因此可以将问题分解为每一行的量化问题。

原论文从矩阵视角描述为按列量化:每一步固定权重矩阵 WW 的一列。等价地,也可以把它看作对每一行独立处理:每次量化行中的一个元素,再调整该行尚未量化的元素来补偿误差。采用逐行的视角更容易理解 GPTQ 的计算流程。

3. 逐元素量化

对于某一行权重 wRdinw \in \mathbb{R}^{d_{\text{in}}},对应一个输出通道:

y=wXy = wX

设量化后该行权重为 w^\hat{w},则输出误差为:

minw^yw^X22=minw^(ww^)X22\min_{\hat{w}} \|y - \hat{w}X\|_2^2 = \min_{\hat{w}} \|(w - \hat{w})X\|_2^2

定义权重误差为:

e=ww^e = w - \hat{w}

则误差可以写为:

wXw^X22=eX22\|wX - \hat{w}X\|_2^2 = \|e X\|_2^2

一个向量的二范数平方就是它自身乘以它的转置:

eX22=eXXTeT\|e X\|_2^2 = e X X^T e^T

H=XXTH = X X^T,则:

eX22=eHeT\|e X\|_2^2 = e H e^T

可以看出,eX22\|e X\|_2^2 是关于 ee 的二次型,其中 HH 是该二次型对应的 din×dind_{\text{in}} \times d_{\text{in}} 对称矩阵。

现在我们需要找到一个量化后的权重 w^\hat{w},使得 e=ww^e = w - \hat{w} 能让 eX22\|e X\|_2^2 最小。

因为 eHeTe H e^T 是一个二次型函数,所以我们可以将这个问题转化为一个二次型优化问题。很显然这里的最优解是 e=0e = 0,即 w^=w\hat{w} = w

ww 的第 ii 个元素 wiw_i 已经量化,w^i\hat{w}_i 被固定为量化后的值,因此需要在这一约束下寻找最优解。

w^i\hat{w}_i 是量化后的值,与原始值 wiw_i 的差异 ei=wiw^ie_i = w_i - \hat{w}_i,则我们需要在 eie_i 固定的情况下,最小化 eX22=eHeT\|e X\|_2^2 = e H e^T

4. 二次型优化问题

dd 为量化后第 ii 个元素的误差,即 d=ei=wiw^id = e_i = w_i - \hat{w}_i,则我们需要在约束条件 ei=de_i = d 下最小化二次型 eHeTe H e^T,即:

mineeHeTs.t. ei=d\min_e e H e^T \quad \text{s.t. } e_i = d

uiu_i 是标准基向量,其中第 ii 个元素为 1,其余元素为 0,例如:

u1=(1000),u2=(0100),,udin=(0001)u_1 = \begin{pmatrix} 1 \\ 0 \\ 0 \\ \vdots \\ 0 \end{pmatrix}, \quad u_2 = \begin{pmatrix} 0 \\ 1 \\ 0 \\ \vdots \\ 0 \end{pmatrix}, \quad \dots, \quad u_{d_{\text{in}}} = \begin{pmatrix} 0 \\ 0 \\ 0 \\ \vdots \\ 1 \end{pmatrix}

则约束条件可以写为:

uiTeT=du_i^T e^T = d

我们可以使用拉格朗日乘子法来求解这个约束优化问题。设拉格朗日乘子为 λ\lambda,可以构造如下拉格朗日函数:

L(e,λ)=12eHeTλ(uiTeTd)\mathcal{L}(e, \lambda) = \frac{1}{2} e H e^T - \lambda (u_i^T e^T - d)

ee 求偏导数并令其为零:

Le=Heλui=0\frac{\partial \mathcal{L}}{\partial e} = He - \lambda u_i = 0

因此:

He=λuiHe = \lambda u_i

两边同时左乘 H1H^{-1},得到:

e=λH1uie = \lambda H^{-1} u_i

H1uiH^{-1} u_iH1H^{-1} 的第 ii 列,则:

e=λ[H1]:,ie = \lambda [H^{-1}]_{:,i}

由约束条件 ei=de_i = d 可得:

ei=λ[H1]i,i=de_i = \lambda [H^{-1}]_{i,i} = d

因此:

λ=dHi,i1\lambda = \frac{d}{H^{-1}_{i,i}}

其中 Hi,i1H^{-1}_{i,i}H1H^{-1} 的第 ii 个对角元素。

最终得到最优的权重误差:

e=d[H1]i,i[H1]:,ie^{\star} = \frac{d}{[H^{-1}]_{i,i}} [H^{-1}]_{:,i}

计算出 ee^{\star} 后,我们可以更新权重:

w^=we\hat{w} = w - e^{\star}

随后继续量化该行的下一个元素,重复上述过程,直到该行的所有元素都被量化。

GPTQ 的实现

GPTQ 的原文给出了 GPTQ 的伪代码:

在计算时,每次对矩阵中一个 drow×Bd_{\text{row}} \times B 的子矩阵进行量化,其中 drowd_{\text{row}} 是行数,BB 是列数。量化后还需要更新权重矩阵的后续列;分块可以让这个子矩阵保存在 GPU 的 shared memory 中,减少显存访问。完成该子矩阵的量化后,再将结果写回显存并更新权重矩阵,然后处理下一个子矩阵,直到所有列都被量化。

此外,上述算法使用 Cholesky 分解处理 H1H^{-1}。为避免 XXTXX^T 不可逆,GPTQ 会在其对角线上加入阻尼项 λ\lambda,使 HH 正定且可逆。原论文的实现中,阻尼系数通常取 HH 对角线元素均值的 1%。

总结

GPTQ 是一种针对预训练 Transformer 模型的权重量化方法,它通过最小化量化误差对输出的影响来优化量化参数。GPTQ 采用逐列量化的方式,每次对权重矩阵中的一个列向量进行量化,并在量化过程中考虑当前列量化后引入的误差对输出的影响,并调整后续列的参数值,试图通过调整其他列的值来补偿当前列量化引入的误差。

附录

GPTQ 的推导涉及不少数学背景知识。若对这些概念不熟悉,理解其原理会比较困难。下面列出 GPTQ 中涉及的几个知识点,并给出简要说明。

1. Frobenius 范数

对于任意矩阵 ARm×n\boldsymbol{A} \in \mathbb{R}^{m\times n},其 Frobenius 范数为:

AF=i=1mj=1nAij2\|\boldsymbol{A}\|_F = \sqrt{\sum_{i=1}^m \sum_{j=1}^n A_{ij}^2}

含义:矩阵所有元素平方和开根号。

2. 二范数

对于任意向量 xRn\boldsymbol{x} \in \mathbb{R}^n,其二范数为:

x2=i=1nxi2\|\boldsymbol{x}\|_2 = \sqrt{\sum_{i=1}^n x_i^2}

含义:向量各元素平方和开根号。

3. 二次型

二次型的定义

x1,x2,,xnx_1,x_2,\dots,x_nnn 个变元,二次型是指形如:

f(x1,,xn)=i=1nj=1naijxixjf(x_1,\dots,x_n)=\sum_{i=1}^n\sum_{j=1}^n a_{ij}x_ix_j

的多项式,其中 aij=ajia_{ij}=a_{ji}

比如:

f(x1,x2)=ax12+bx1x2+cx22f(x_1,x_2)=ax_1^2+bx_1x_2+cx_2^2

就是一个二次型,其中 x12x_1^2x1x2x_1x_2x22x_2^2 均为二次项,整个式子不含一次项和常数项。

二次型的矩阵表示

任意二次型可以写成矩阵乘积形式:

f(x)=xTAxf(\boldsymbol{x}) = \boldsymbol{x}^T A \boldsymbol{x}

其中:

x=(x1x2xn)\boldsymbol{x}=\begin{pmatrix}x_1\\x_2\\\vdots\\x_n\end{pmatrix}

AA 是对称矩阵,满足 AT=AA^T=A,称为二次型的矩阵。AA 的对角元 aiia_{ii}xi2x_i^2 的系数,非对角元 aij=ajia_{ij}=a_{ji} 是交叉项 xixjx_ix_j 系数的一半。

比如下面的二次型:

f(x1,x2)=x12+6x1x2+2x22f(x_1,x_2)=x_1^2+6x_1x_2+2x_2^2

可以写成如下矩阵形式:

xTAx=(x1x2)(1332)(x1x2)=x12+6x1x2+2x22\boldsymbol{x}^T A\boldsymbol{x}= \begin{pmatrix}x_1 & x_2\end{pmatrix} \begin{pmatrix}1 & 3 \\ 3 & 2\end{pmatrix} \begin{pmatrix}x_1\\x_2\end{pmatrix} =x_1^2+6x_1x_2+2x_2^2

标准二次型

只有平方项,无交叉项:

f=d1y12+d2y22++dnyn2f=d_1y_1^2+d_2y_2^2+\dots+d_ny_n^2

比如正则项 L2=w2=wTIwL_2=\|\boldsymbol{w}\|^2=\boldsymbol{w}^T I \boldsymbol{w} 就是标准二次型。

Jacobian 矩阵

Jacobian 矩阵是向量值函数的一阶导数矩阵。

设输入向量为:

x=[x1x2xn]Rn\boldsymbol{x} = \begin{bmatrix} x_1 \\ x_2 \\ \dots \\ x_n \end{bmatrix} \in \mathbb{R}^n

f(x)f(\boldsymbol{x}) 是一个从 Rn\mathbb{R}^nR\mathbb{R} 的标量函数,即 f:RnRf: \mathbb{R}^n \to \mathbb{R}

则它对输入 x\boldsymbol{x} 的一阶偏导数组成梯度向量:

f(x)=[fx1fx2fxn]Rn\nabla f(\boldsymbol{x}) = \begin{bmatrix} \frac{\partial f}{\partial x_1} \\ \frac{\partial f}{\partial x_2} \\ \vdots \\ \frac{\partial f}{\partial x_n} \end{bmatrix} \in \mathbb{R}^n

考虑一个向量值函数 f(x)\boldsymbol{f}(\boldsymbol{x}),它将一个 nn 维向量映射到一个 mm 维向量:

f(x)=(f1(x)f2(x)fm(x))\boldsymbol{f}(\boldsymbol{x})= \begin{pmatrix} f_1(\boldsymbol{x})\\ f_2(\boldsymbol{x})\\ \vdots\\ f_m(\boldsymbol{x}) \end{pmatrix}

给定输入向量 x=(x1,x2,,xn)\boldsymbol{x}=(x_1,x_2,\dots,x_n)f(x)\boldsymbol{f}(\boldsymbol{x}) 的输出是一个 mm 维向量,其中每一个 fi(x)f_i(\boldsymbol{x}) 都是 x\boldsymbol{x} 的函数。所以每一个 fif_i 都可以对 x\boldsymbol{x} 的每一个分量求偏导数,得到一个 1×n1 \times n 的行向量。将所有的 fif_i 的偏导数组合起来,就得到了一个 m×nm \times n 的矩阵,这个矩阵就是 Jacobian 矩阵。

Jacobian 矩阵定义为:

Jf(x)=(f1x1f1x2f1xnf2x1f2x2f2xnfmx1fmx2fmxn)J_{\boldsymbol{f}}(\boldsymbol{x})= \begin{pmatrix} \frac{\partial f_1}{\partial x_1} & \frac{\partial f_1}{\partial x_2} & \cdots & \frac{\partial f_1}{\partial x_n} \\ \frac{\partial f_2}{\partial x_1} & \frac{\partial f_2}{\partial x_2} & \cdots & \frac{\partial f_2}{\partial x_n} \\ \vdots & \vdots & \ddots & \vdots \\ \frac{\partial f_m}{\partial x_1} & \frac{\partial f_m}{\partial x_2} & \cdots & \frac{\partial f_m}{\partial x_n} \end{pmatrix}

Jacobian 矩阵的每一行对应一个输出分量对输入向量的偏导数,每一列对应所有输出分量对某一个输入分量的偏导数。

Hessian 矩阵

Hessian 矩阵是二阶偏导数矩阵,它描述了一个标量值函数在某一点的局部曲率。设标量函数 f:RnRf: \mathbb{R}^n \to \mathbb{R},其 Hessian 矩阵定义为:

Hf(x)=(2fx122fx1x22fx1xn2fx2x12fx222fx2xn2fxnx12fxnx22fxn2)H_f(\boldsymbol{x})= \begin{pmatrix} \frac{\partial^2 f}{\partial x_1^2} & \frac{\partial^2 f}{\partial x_1 \partial x_2} & \cdots & \frac{\partial^2 f}{\partial x_1 \partial x_n} \\ \frac{\partial^2 f}{\partial x_2 \partial x_1} & \frac{\partial^2 f}{\partial x_2^2} & \cdots & \frac{\partial^2 f}{\partial x_2 \partial x_n} \\ \vdots & \vdots & \ddots & \vdots \\ \frac{\partial^2 f}{\partial x_n \partial x_1} & \frac{\partial^2 f}{\partial x_n \partial x_2} & \cdots & \frac{\partial^2 f}{\partial x_n^2} \end{pmatrix}

ff 的二阶偏导数连续时,满足:

2fxixj=2fxjxi\frac{\partial^2 f}{\partial x_i \partial x_j} = \frac{\partial^2 f}{\partial x_j \partial x_i}

所以 Hessian 矩阵是实对称矩阵,即 Hf(x)=Hf(x)TH_f(\boldsymbol{x}) = H_f(\boldsymbol{x})^T

泰勒展开式

f(x)f(x)x0x_0 无穷阶可导,则:

f(x)=f(x0)+f(x0)(xx0)+f(x0)2!(xx0)2+f(x0)3!(xx0)3++f(n)(x0)n!(xx0)n+Rn(x)f(x) = f(x_0) + f'(x_0)(x-x_0) + \frac{f''(x_0)}{2!}(x-x_0)^2 +\frac{f'''(x_0)}{3!}(x-x_0)^3+\dots +\frac{f^{(n)}(x_0)}{n!}(x-x_0)^n + R_n(x)

一阶近似

只保留到一次项:

f(x0+Δx)f(x0)+f(x0)Δxf(x_0+\Delta x)\approx f(x_0)+f'(x_0)\Delta x

二阶近似

保留到二次项:

f(x0+Δx)f(x0)+f(x0)Δx+12f(x0)(Δx)2f(x_0+\Delta x)\approx f(x_0)+f'(x_0)\Delta x + \frac12 f''(x_0)(\Delta x)^2

多元标量函数二阶泰勒展开

设多元函数 f(x),xRnf(\boldsymbol{x}),\boldsymbol{x}\in\mathbb{R}^n,在点 x\boldsymbol{x} 处给微小偏移 Δx\Delta\boldsymbol{x},则:

f(x+Δx)f(x)+fTΔx+12ΔxTHΔxf(\boldsymbol{x}+\Delta\boldsymbol{x}) \approx f(\boldsymbol{x}) + \nabla f^T \Delta\boldsymbol{x} + \frac12 \Delta\boldsymbol{x}^T \mathbf{H} \Delta\boldsymbol{x}

其中:

  1. f(x)f(\boldsymbol{x}) 常数项
  2. fTΔx\nabla f^T \Delta\boldsymbol{x} 一阶项,对应 f(x)Δxf'(x)\Delta x
  3. 12ΔxTHΔx\frac12 \Delta\boldsymbol{x}^T \mathbf{H}\Delta\boldsymbol{x} 二阶二次型项,对应 12f(x)(Δx)2\frac12 f''(x)(\Delta x)^2

使用 Hessian 矩阵判断极值

多元函数 f(x)f(\boldsymbol{x}) 的二阶泰勒展开式为:

f(x+Δx)f(x)+fTΔx+12ΔxTHΔxf(\boldsymbol{x}+\Delta\boldsymbol{x}) \approx f(\boldsymbol{x}) + \nabla f^T \Delta\boldsymbol{x} + \frac12 \Delta\boldsymbol{x}^T \mathbf{H} \Delta\boldsymbol{x}

ff 的变化量 Δf\Delta f 可以近似表示为:

ΔffTΔx+12ΔxTHΔx\Delta f \approx \nabla f^T \Delta\boldsymbol{x} + \frac12 \Delta\boldsymbol{x}^T \mathbf{H} \Delta\boldsymbol{x}

在驻点 x0\boldsymbol{x}_0(即梯度为零的点)处,f=0\nabla f = 0,因此:

Δf12ΔxTHΔx\Delta f \approx \frac12 \Delta\boldsymbol{x}^T \mathbf{H} \Delta\boldsymbol{x}

此时可以通过 Hessian 矩阵判断极值类型:

  1. Hf(x0)H_f(\boldsymbol{x}_0) 正定,则 x0\boldsymbol{x}_0 是局部极小值;
  2. Hf(x0)H_f(\boldsymbol{x}_0) 负定,则 x0\boldsymbol{x}_0 是局部极大值;
  3. Hf(x0)H_f(\boldsymbol{x}_0) 既非正定也非负定,则 x0\boldsymbol{x}_0 是鞍点。

拉格朗日乘子法

拉格朗日乘子法用于求解带等式约束的极值问题。设有目标函数 f(x)f(\boldsymbol{x}) 和约束条件 g(x)=0g(\boldsymbol{x})=0,构造拉格朗日函数:

L(x,λ)=f(x)λg(x)\mathcal{L}(\boldsymbol{x},\lambda) = f(\boldsymbol{x}) - \lambda g(\boldsymbol{x})

求解驻点条件:

xL=f(x)λg(x)=0\nabla_{\boldsymbol{x}} \mathcal{L} = \nabla f(\boldsymbol{x}) - \lambda \nabla g(\boldsymbol{x}) = 0 Lλ=g(x)=0\quad \frac{\partial \mathcal{L}}{\partial \lambda} = - g(\boldsymbol{x}) = 0

第一个式子表示目标函数的梯度与约束函数的梯度在驻点处是线性相关的,第二个式子保证约束条件被满足。通过解这组方程,可以找到在约束条件下的极值点。

评论 评论内容仅博主可见,不会公开显示)