AI Hero Club

大模型高效推理 · 第 5 章

已自行标记完成0 / 8

仅保存在当前浏览器;完成标记不代表通过项目验收。

本章提纲 6 个小节
全课目录 8 章
完整课程计划 ↗
大模型高效推理 / 课程计划 ↗

CHAPTER 05 / 8建议学习 120 分钟

量化:从舍入误差到模型质量边界

把权重舍入到少量刻度后,怎样估计误差,并区分伪量化与真正的整数执行?

本章要解决的 3 个问题
  • 推导对称量化的尺度、误差界与通道粒度
  • 以离群值和小间隔反例检查数值风险
  • 区分伪量化误差实验、压缩存储和整数内核
课程项目 ZIP ↓

主动改变函数,先声明近似目标

前面的缓存要求与参考模型表示同一个函数,量化则把部分实数权重替换为有限网格上的近似值。它的验收不能只写“程序能跑”或“输出形状没变”。本章先在标准库中定义一个确定的舍入映射,再在冻结模型副本上观察 logits、分布和损失变化。项目没有实现整数矩阵乘法,没有将整数打包后保存,也没有减少实际浮点参数存储。它是用于隔离误差来源的伪量化实验,不能据其推导真实量化内核的速度。

令位宽为 k,使用对称整数集合 [−qmax,qmax][-q_{max},q_{max}],其中 qmax=2k−1−1q_{max}=2^{k-1}-1。这故意不用有符号整数最负的一个编码,以便正负对称。给一组有限权重 wiw_i,峰值为 a=max⁡i∣wi∣a=\max_i|w_i|,若 a 非零则尺度 s=a/qmaxs=a/q_{max},整数 qiq_i 是 wi/sw_i/s 的最近整数并限制在范围内,恢复值为 w^i=sqi\hat w_i=sq_i。全零组约定尺度一、整数全零,避免除零。Python round 与 PyTorch round 对精确半整数采用偶数方向,本项目两端遵守同一约定。

qi=clip⁡(round⁡(wi/s),−qmax,qmax),w^i=sqiq_i=\operatorname{clip}(\operatorname{round}(w_i/s),-q_{max},q_{max}),\qquad \hat w_i=sq_i
无零点的对称量化;本章不实现非对称零点和整数核。

在不发生超范围截断时,最近舍入意味着 ∣wi/s−qi∣≤1/2|w_i/s-q_i|\leq1/2,乘上正尺度得到 ∣wi−w^i∣≤s/2|w_i-\hat w_i|\leq s/2。峰值定义的尺度让本组原始有限值恰好落在范围内,因此训练后静态权重可满足该界。若尺度来自校准范围而未来激活越界,clip 引入额外误差,这个半步长界就不再覆盖全部输入。必须在推导处写清前提,不能用权重固定范围的界承诺任意激活值都安全。

完整算例一:舍入与离群值

对一组权重零、一半、一,使用三位对称范围负三到三,尺度为三分之一。零映射为零,一映射为三并精确恢复;一半除以尺度为一点五,按偶数规则舍入到二,恢复为三分之二,误差六分之一,恰好达到半步长。此处最大误差界是实数近似界,而二进制浮点实现还会有微小表示误差,测试应允许机器精度量级的容差。位宽越小步长越大,这是局部误差变化,不直接等于全模型损失变化。

再看八位组零点一、零点二、一百,峰值一百,尺度约零点七八七。前两个数除以尺度都不到半,因而同时舍入为零;大值一百却能精确恢复。最大绝对误差仅零点二,若只看一百的相对误差会误以为全部很好。小权重可能对应关键方向,不能因为它绝对值小就断言不重要。将不相同范围的输出通道分开定尺度,可以避免某一通道的大值把所有通道的分辨率拖低,但同一通道内的离群值仍存在。

独立运行独立数值验证:半步误差界、半整数规则、全零与离群值。
def quantize(xs,bits):
    qmax=2**(bits-1)-1
    scale=max(map(abs,xs))/qmax if any(xs) else 1.
    qs=[max(-qmax,min(qmax,round(x/scale))) for x in xs]
    ys=[q*scale for q in qs]
    assert max(abs(x-y) for x,y in zip(xs,ys))<=scale/2+1e-12
    return scale,qs,ys
s,q,y=quantize([0.,.5,1.],3)
assert q==[0,2,3]
assert quantize([.1,.2,100.],8)[1]==[0,0,127]
assert quantize([0.,0.],4)==(1.,[0,0],[0.,0.])
print(s,y)

从权重误差推到线性输出误差

设线性层某个输出为 yj=∑iwjixi+bjy_j=\sum_i w_{ji}x_i+b_j,输入固定、偏置不量化,则输出误差是 Δyj=∑iΔwjixi\Delta y_j=\sum_i\Delta w_{ji}x_i。由三角不等式得 ∣Δyj∣≤∑i∣Δwji∣∣xi∣|\Delta y_j|\leq\sum_i|\Delta w_{ji}||x_i|。若该输出行使用共同尺度 sjs_j,且各项无截断,进一步有 ∣Δyj∣≤(sj/2)∥x∥1|\Delta y_j|\leq(s_j/2)\|x\|_1。输入幅度会放大权重误差;经过多层非线性、归一化和残差后,局部界不能不加条件地直接相加为紧的端到端界。

∣Δyj∣≤sj2∑i∣xi∣|\Delta y_j|\leq \frac{s_j}{2}\sum_i|x_i|
逐输出通道、无截断且只量化权重时的局部上界。

例如某输出通道尺度零点零二,输入为三、负四,则界为零点零一乘七,即零点零七。若两项权重误差分别零点零零五、负零点零一,实际输出误差为零点零一五加零点零四,即零点零五五,低于该界。这个完整小例子同时说明符号可以同向累积,也可以抵消;平均权重误差接近零不能保证某特定输入的输出误差小。校准数据应覆盖真实输入范围,而本实验的随机词元只验证当前固定数值函数。

完整算例二:四位和八位的实际模型对照

项目逐输出通道量化所有 Linear 的权重,包括 Q、K、V、O、前馈和词表头;嵌入、归一化、偏置保持原样。恢复值仍写回双精度模型副本。固定二十四词元、批量二的相邻预测共有四十六个有效位置。八位最大 logit 差约零点零零三五九五,平均正向 KL 约 3.78×10−73.78\times10^{-7},四十六位置 argmax 全相同。四位最大差约零点零五三三四四,平均 KL 约零点零零零一一六三,argmax 一致率四十除以四十六,约百分之八十六点九六。

同次实验参考负对数似然为三点四六二一四七;八位约三点四六二零二二,四位约三点四五八四九五。四位在这串随机目标上的损失反而略低,不表示模型更懂语言,也不表示更低位宽一般更好。随机初始化没有训练语义,随机目标还可能偶然偏爱任意扰动。应将这些数字解释为近似函数的可复跑差异,若要评价语言质量,需要冻结训练好的检查点、独立真实文档、相同词表与评分协议,并报告不确定性。

在课程项目目录运行项目目录运行:副本近似与原模型不变检查;没有整数执行。
from lab import make_model,tokens,quant_report,state_hash
model=make_model();before=state_hash(model)
for bits in [8,4]:
    report=quant_report(model,tokens(24,2),bits)
    assert report['ledger']['actual_storage_unchanged']
    print(bits,report['maximum_logit_error'],report['argmax_agreement'])
assert state_hash(model)==before

不能把理想位数当作实际节省

本实验共近似二万五千五百六十八个 Linear 权重,有六百零七个输出通道尺度。若真按八位打包,理想权重载荷二万五千五百六十八字节;若四位紧密打包则一万二千七百八十四字节。假设每个尺度以四字节保存,还需二千四百二十八字节,另外未量化参数、对齐和容器都没有包含。当前代码没有打包:实际权重仍是每个八字节,尺度只用于生成恢复值。故报告 ideal_packed_bytes 是条件账本,actual_storage_unchanged 才描述本实现事实。

真实低位内核必须处理整数累加、尺度应用、可能的零点、分组与对齐,并证明没有溢出或错误广播。权重量化、激活量化、KV 量化又是不同位置的改变;本项目仅覆盖第一类的舍入恢复。SmoothQuant 和 GPTQ 分别提供更复杂的校准或补偿机制,属于原论文讨论的独立方法,本课程未实现它们,也不把简单逐行舍入冠以其名称。引用论文是说明深入方向和机制出处,不是借用它们在其他模型与硬件上的实验成绩。

第一类验证是局部数学性质:全零恢复、整数范围、无截断半步长界以及局部线性误差界。第二类是端到端函数检查:原模型哈希不变、候选确实改变、同输入的分布差异、目标损失与决策变化。局部界通过不能替代端到端检查;argmax 一致也不能证明概率校准相同。下一章将建立这几类证据如何共同组成验收门槛,并用更小的决策间隔反例说明“看起来一样”仍然不足。

对称映射还隐含了零点为零的语义。若整数乘法想直接代替浮点乘法,在只有权重量化且输入浮点时,需要将每个输出通道的累加结果按相应尺度恢复;若输入也量化,尺度变成输入尺度与权重尺度的乘积。非零零点则要求在累加中校正偏移项。不同算子与硬件对这些步骤的融合能力不同,因此理论载荷下降并不自动产生低延迟。当前实验刻意在前向前恢复浮点值,使误差研究不混入内核差异,代价是没有真实存储和计算节省。

还可从通道轴检查错误实现:PyTorch Linear 的 weight 形状为输出宽乘输入宽,所以每输出通道应沿输入轴求峰值,尺度形状为输出宽乘一。若沿输出轴求峰值,得到的是每输入通道尺度,仍然能广播运行,却变成另一个算法。应以一个各行范围明显不同的小矩阵检查,例如第一行峰值一、第二行峰值一百,确认两行步长不同。测试形状成功并不足以证明粒度正确;这类轴语义应随公式写进代码审查。

练习与项目增量

TRY IT YOURSELF

基础:尺度和误差界

四位对称量化一组峰值1.4的权重,qmax、尺度与无截断最大舍入误差界各是多少?

提示 1
四位对称有符号范围按本课qmax约定确定,再由峰值定尺度。
提示 2
最近舍入误差不超过半个网格间距;该界前提是无截断且映射约定未变。
对照参考解答
qmax=7,尺度1.4/7=0.2,半步界0.1。使用的整数范围为−7到7;若改用非对称编码或截断校准范围,应重新定义映射和误差分析。

TRY IT YOURSELF

进阶:局部线性界

某行尺度0.04,输入(2,−3,5)。只量化权重时输出误差的保守界是什么?

提示 1
输出误差是各权重误差乘输入后的和,可先用三角不等式上界。
提示 2
每项权重误差界取s/2,再乘输入绝对值总和;无需额外假设误差独立或零均值。
对照参考解答
输入一范数为10,界为0.04/2×10=0.2。该界不需要误差项独立或均值为零;这些统计假设若没有证据,不能用来随意缩小确定性上界。

TRY IT YOURSELF

挑战:存储与能力两重错误

同学从本项目四位载荷12784字节且NLL下降,写“已实现小四倍、质量更好的中文模型”。逐项改写。

提示 1
先分别查实际存储dtype与评价目标来源,别由“四位”名称推真实压缩。
提示 2
理想载荷、尺度元数据、未量化参数与浮点恢复分账;随机目标NLL不能说明中文质量。
对照参考解答
实际浮点存储未压缩,12784只是量化Linear权重的理想打包载荷,未计尺度及其余参数。NLL来自随机初始化和固定随机目标,不能说明中文能力。可写:四位逐行恢复实验在该数值夹具上改变了分布,最大logit差约0.0533,argmax一致40/46;真实压缩和语言质量均未验证。

本章增量是 symmetric、pseudoquant 与 quant_report,交付中保留八位和四位的完整层级误差账本。没有提交一个以“量化”名义实际仍等价的空操作,也没有把浮点恢复方案的速度当成整数核优势。后继章节沿用同一模型哈希和相同输入,分别讨论正确性门槛与性能统计。

CHECK YOUR UNDERSTANDING

检验理解

先作答,再决定是否展开解析。选择题用于发现理解缺口;独立实现与迁移任务仍需另行检验。

1. 无截断最近舍入的误差界?

查看解析距离最近网格点不超过半步长。
2. 本项目量化后的参数实际dtype?

查看解析恢复值写回浮点副本,没有整数打包和内核。
3. 随机目标NLL略降可以证明?

查看解析没有训练语义与独立语料,不能推广能力。
4. 逐输出通道尺度主要隔离什么?

查看解析不同通道分开定尺度,但同通道内部离群值仍可能损害小值分辨率。

自行标记用于记录学习进度,不代表通过项目验收。