AWQ 量化方案:激活感知的权重量化与工程实现全解析 AWQ 量化方案激活感知的权重量化与工程实现全解析一、为什么 GPTQ 在低精度场景下失效——AWQ 的差异化动机GPTQGPT Post-Training Quantization通过逐列的 OBQOptimal Brain Quantization校正在 INT4 权重量化上取得了接近 FP16 的困惑度。然而GPTQ 的校正过程仅考虑权重误差最小化完全忽略了激活值Activation对推理精度的杠杆效应。关键发现来自 AWQ 论文的实验权重的量级与激活的范数之间存在强正相关。在 LLaMA-7B 中激活值范数最高的 1% 通道承载了 70% 的输出信息。GPTQ 将量化误差均匀分配给所有通道而 AWQ 的核心策略是——对高激活通道施加更小的量化步长更高精度对低激活通道施加更大的量化步长更低精度在同等平均位宽下实现更好的输出保真度。二、AWQ 的等效变换通道级缩放因子的数学推导flowchart TD A[原始权重矩阵 Wbr/Per-Channel L2 Norm 差异显著] -- B[计算每通道激活值范数br/s mean#40;|X|#41; per channel] B -- C{缩放策略选择} C --|逐通道缩放| D[W W / sbr/X X × s] D -- E[量化 W 到 INT4br/反量化: W̃ Q#40;W#41; × S_quant] E -- F[推理时:br/Y W̃ × Xbr/等效于 Y WQ × X] G[关键性质] -- H[缩放因子 s 不改变矩阵乘法的结果br/W×X W×Xbr/但改变了权重的量化难度分布]AWQ 的数学本质是一个等效变换W·X (W/s)·(X·s)其中s是每通道的缩放因子。缩放后的权重W/s变得更加平滑——高激活通道的权重被缩小量化时相对误差更小低激活通道的权重被放大但因其激活范数低量化误差对最终输出的贡献微乎其微。三、AWQ 的核心算法流程import torch import torch.nn as nn def awq_quantize(linear: nn.Linear, calib_data: torch.Tensor, w_bit: int 4, group_size: int 128) - nn.Linear: AWQ 量化流程激活感知的逐通道缩放 逐组量化 Args: linear: 待量化的 nn.Linear 层 calib_data: 校准数据形状 (n_samples, in_features) w_bit: 权重量化位宽典型值 4 group_size: 分组尺寸每组内独立量化 weight linear.weight.data # (out_features, in_features) # Step 1: 用校准数据计算每通道激活范数 with torch.no_grad(): # linear(calib_data) 对应 Y X·W^T # 此处取激活 X 的每通道平均范数作为缩放系数依据 activation calib_data # (N, in_features) act_norm activation.abs().mean(dim0) # (in_features,) # Step 2: 计算逐通道缩放因子 s基于激活范数的幂次 alpha 0.5 # 搜索得到的最优缩放指数 scale act_norm.pow(alpha) # s ||X||^alpha # 约束s 不会改变输出值 数学上的等效变换 scale scale / scale.max() # 归一化后保持量化范围稳定 # Step 3: 等效变换——缩放权重反向缩放下一层或融合到输入中 # W W / s, X X * s —— 乘积不变 weight_scaled weight / scale.unsqueeze(0) # (out_f, in_f) / (1, in_f) # Step 4: 逐组量化每组 group_size 个输入通道独立计算 scale/zp q_weight torch.zeros_like(weight_scaled, dtypetorch.int8) scales_per_group torch.zeros(weight.shape[0], weight.shape[1] // group_size) for g in range(0, weight.shape[1], group_size): group weight_scaled[:, g:ggroup_size] g_max group.abs().max() g_scale g_max / (2 ** (w_bit - 1) - 1) # INT4: 7 q_weight[:, g:ggroup_size] torch.round(group / g_scale).clamp( -(2 ** (w_bit - 1)), (2 ** (w_bit - 1)) - 1) scales_per_group[:, g//group_size] g_scale # Step 5: 返回量化后的权重或构建 QuantLinear 层 # 推理时将 scale 反乘回激活输入侧 return QuantLinear(q_weight, scales_per_group, scale) class QuantLinear(nn.Module): 量化推理用 Linear 层——集成反量化步骤 def __init__(self, qw, scales, awq_scale): super().__init__() self.register_buffer(qweight, qw) # INT4 packed self.register_buffer(scales, scales) # per-group FP16 scales self.register_buffer(awq_scale, awq_scale) # per-channel scales def forward(self, x): # AWQ 缩放反乘将输入按 awq_scale 放缩 x_scaled x * self.awq_scale # 反量化权重 矩阵乘法 w_dequant self.qweight * self.scales.repeat_interleave(128, dim1) return torch.nn.functional.linear(x_scaled, w_dequant)四、AWQ 与同类方案的系统性对比维度AWQGPTQSmoothQuantGGUF (llama.cpp)核心策略通道级 Scale 变换OBQ 逐列校正激活→权重偏移迁移块级 K-quant校准数据需求128 样本128 样本512 样本无纯统计INT4 困惑度退化 0.15 0.10N/A仅 INT8 0.30量化时间7B~3 分钟~15 分钟~5 分钟~10 分钟推理框架vLLM, TGIvLLM, TGIvLLMllama.cpp硬件适配CUDA ≥ 7.0CUDA ≥ 7.0CUDA ≥ 7.0CPU/CUDA/MetalAWQ 在量化速度GPTQ 的 5 倍快因为不需要迭代列补偿和实现简洁性等效变换思想无需迭代上有明显优势。GPTQ 在极限精度INT4 下困惑度退化最小上略优但量化时间成本高。五、总结AWQ 的核心创新在于将量化误差重分配——不是均匀最小化权重误差而是将误差从高激活通道转移到低激活通道利用激活范数的信息不对称性来保护关键信息通道。等效变换W·X (W/s)·(X·s)是 AWQ 的数学基础它的优雅之处在于不改变网络输出值的前提下重构了权重的分布使量化误差集中于对输出贡献最小的权重维度上。工程化选型对量化速度敏感、需要频繁迭代的场景选 AWQ对极限精度有严格要求选 GPTQ仅需 INT8 部署选 SmoothQuant无需 4-bit kernel 的工程复杂度。vLLM 0.4 已原生支持 AWQ 量化模型加载部署时仅需添加--quantization awq参数。