☰
W8A8量化手把手教程:gemma-4-26B-A4B-it-w8a8-llmcompressor 的 LLM Compressor oneshot 代码逐行注释
2026/11/3 2:33:28 网站建设 项目流程

W8A8量化手把手教程:gemma-4-26B-A4B-it-w8a8-llmcompressor 的 LLM Compressor oneshot 代码逐行注释

前言:这篇教程能帮你做什么

W8A8量化可以让大模型体积直接减半:AMD 用LLM Compressor的oneshot函数,将 gemma-4-26B-A4B-it 从48.1 GiB 压缩到 25.3 GiB(约 47%),而 GSM8K 基准的精度恢复率高达98.95%。本教程对该仓库中量化脚本的每一行代码逐行注释,帮你完整复现 W8A8 量化流程,适合新手和普通开发者快速上手。

💡W8A8 是什么?“W8”指权重用 8 位整数(INT8)存储,“A8”指激活值也动态量化为 8 位。相比只量化权重(W8A16),W8A8 在 AMD EPYC CPU 推理时能充分利用 INT8 指令,算得更快。

模型速览:这份 W8A8 量化模型长什么样

这个仓库是 AMD 基于LLM Compressor v0.13.0对 gemma-4-26B-A4B-it(RedHatAI 版)做量化后的成品 checkpoint,主要服务于AMD EPYC CPU 推理(ZenDNN 加速栈),用 vLLM 加载。核心信息一览:

项目说明
架构Gemma4ForConditionalGeneration(多模态 MoE,30 层 × 128 路由专家,top-8 路由)
量化方案W8A8:权重 INT8 对称 / per-channel 静态,激活 INT8 对称 / per-token 动态
量化算法RTN(Round-to-Nearest,四舍五入最近取整)
量化产物格式compressed-tensors(int-quantized格式)
体积变化48.1 GiB → 25.3 GiB(约 47% 缩减)
推理引擎vLLM v0.29.0 + ZenDNN v6.1.0 + ZenTorch v2.13.0.2

其中“量化了哪些层、哪些层保留 BF16”是这份 W8A8 配方最关键的取舍,README.md 中给出了精确范围:

  • 被量化的层:30 层中每层的 128 个路由专家(experts.*.{gate,up,down}_proj)、共享 dense MLP(mlp.{gate,up,down}_proj)和自注意力(self_attn.{q,k,v,o}_proj);
  • 保留 BF16 的层:MoE 路由器(router.proj及其 scales)、视觉塔(vision tower)、多模态投影器(embed_vision)、lm_head、embed_tokens以及所有 LayerNorm。

⚠️为什么要保留这些层?路由器参数很小但对路由决策极其敏感,一旦量化导致“送错专家”,精度会明显受损;视觉塔和lm_head则直接影响多模态输入质量与最终输出分布。

复现 W8A8 量化:oneshot 代码逐行注释

下面是完整的量化脚本(源自 README.md 的 Quantization 部分),分 5 个步骤讲解。

第 1 步:安装依赖并导入模块

import torch import transformers from transformers import AutoConfig, AutoProcessor, AutoTokenizer from llmcompressor import oneshot from llmcompressor.modifiers.quantization import QuantizationModifier
  • AutoConfig/AutoProcessor/AutoTokenizer:transformers 的自动加载器,分别负责读配置、处理器、分词器;
  • oneshot:LLM Compressor 的核心入口函数,一次调用完成“量化 + 保存”,无需校准数据、无需训练循环,这就是它叫 oneshot 的原因;
  • QuantizationModifier:定义量化“配方(recipe)”的类,等价于下面仓库里 recipe.yaml 描述的内容。

版本要求(与 README.md 的 Requirements 一致):

torch==2.13.0.2 zentorch==2.13.0.2 vllm==0.29.0 llmcompressor==0.13.0

第 2 步:按原始架构加载 BF16 模型与分词器

model_id = "RedHatAI/gemma-4-26B-A4B-it" output_dir = "./gemma-4-26B-A4B-it-w8a8-llmcompressor-v0.13.0" # Step 1: Load the BF16 model and tokenizer. This is a composite multimodal MoE # model, so load via the architecture named in its own config: # AutoModelForCausalLM would demote config.json to the text-only Gemma4TextConfig # and produce a checkpoint vLLM rejects. config = AutoConfig.from_pretrained(model_id, trust_remote_code=True) model_cls = getattr(transformers, config.architectures[0]) model = model_cls.from_pretrained( model_id, dtype=torch.bfloat16, device_map="cpu", trust_remote_code=True, ) tokenizer = AutoTokenizer.from_pretrained(model_id, trust_remote_code=True)

逐行注释:

代码注释
model_id = "RedHatAI/gemma-4-26B-A4B-it"源 BF16 模型地址(多模态 MoE 原版)
output_dir = "..."量化后 checkpoint 的输出目录
AutoConfig.from_pretrained(...)读取 config.json,拿到architectures[0](即Gemma4ForConditionalGeneration)
model_cls = getattr(transformers, config.architectures[0])动态取出与架构名对应的模型类
model_cls.from_pretrained(...)以 BF16 精度加载到CPU(device_map="cpu"),量化在 CPU 上完成

⚠️新手最容易踩的坑:不要用AutoModelForCausalLM加载!它是“复合多模态 MoE”模型,AutoModelForCausalLM会把配置降级为纯文本的Gemma4TextConfig,产出的 checkpoint 会被 vLLM 直接拒绝。必须先读 config.json 中声明的architectures再按名加载(本仓库的 config.json 里可以看到"architectures": ["Gemma4ForConditionalGeneration"])。

第 3 步:定义 W8A8 量化配方(核心)

# Step 2: Define the W8A8 recipe. The routed experts are quantized along with # the shared MLP and attention; only the router, vision path and lm_head are # skipped. recipe = QuantizationModifier( scheme="W8A8", targets=["Linear"], ignore=[ "lm_head", r"re:.*lm_head", # MoE router: tiny and extremely sensitive, wrong routing wrecks accuracy. r"re:.*router\.proj$", # Vision tower and multimodal projector must stay BF16. r"re:.*vision_tower.*", r"re:.*embed_vision.*", r"re:.*embed_audio.*", ], )
参数注释
scheme="W8A8"直接选用内置 W8A8 方案:权重 8 位对称 + 激活 8 位动态,无需手动指定每个量化参数
targets=["Linear"]量化对象:所有nn.Linear层(即专家投影、MLP、注意力投影)
ignore=[...]豁免清单,用正则(re:前缀)按层名跳过:lm_head、MoE 路由器router.proj、视觉塔vision_tower、视觉/音频嵌入embed_vision/embed_audio

这份 Python 配方与仓库中 recipe.yaml 完全对应:

default_stage: default_modifiers: QuantizationModifier: targets: [Linear] ignore: [lm_head, 're:.*lm_head', 're:.*router\.proj$', 're:.*vision_tower.*', 're:.*embed_vision.*', 're:.*embed_audio.*'] scheme: W8A8 requires_calibration_data: false

可以看到requires_calibration_data: false——RTN 算法不需要校准数据集,这是 oneshot 量化相对 QAT/GPTQ 类方法的显著优势。

第 4 步:调用 oneshot 完成量化并保存

# Step 3: One-shot quantize and save in compressed-tensors format oneshot( model=model, recipe=recipe, tokenizer=tokenizer, output_dir=output_dir, trust_remote_code_model=True, )
  • model/recipe/tokenizer:三要素缺一不可,tokenizer 用于在保存时写入分词配置;
  • output_dir:输出目录,oneshot 会把量化后的权重按compressed-tensors格式写入model.safetensors分片,并更新config.json中的quantization_config(本仓库 config.json 的quantization_config字段就是这一步的产物:weights.strategy="channel"、input_activations.strategy="token"且dynamic=true);
  • trust_remote_code_model=True:允许加载依赖自定义代码的模型架构。

第 5 步:补存 Processor 并冒烟测试

# Step 4: Save the processor; oneshot does not write it and vLLM needs it processor = AutoProcessor.from_pretrained(model_id, trust_remote_code=True) processor.save_pretrained(output_dir) # Smoke test inputs = tokenizer("What are we having for dinner?", return_tensors="pt") output = model.generate(**inputs, max_new_tokens=30) print(tokenizer.decode(output[0], skip_special_tokens=True))
  • 注意:oneshot 只保存模型和分词器,不会写processor_config.json,而 vLLM 加载多模态模型时必须要它,所以要手动save_pretrained(对应仓库中的 processor_config.json);
  • 冒烟测试:用 tokenizer 编码一句英文问题,model.generate生成最多 30 个 token 并解码打印,只要输出是通顺的自然语言,就说明量化后模型权重完整可用。

量化效果验证:GSM8K 评测 98.95% 恢复率

按 README.md 的评测流程(lm_eval+ vLLM 引擎,5-shot),W8A8 量化模型相对 BF16 基线的表现:

BenchmarkBF16 基线W8A8(本模型)恢复率
GSM8K (5-shot)0.94620.936398.95%

也就是说,体积减少近一半的同时,数学推理能力几乎无损——这正是 W8A8 + RTN 在这类 MoE 模型上的理想结果。

量化产物怎么用:vLLM 快速启动

量化完成后,用 vLLM 加载(来自 README.md Quick Start 部分):

from vllm import LLM, SamplingParams model = LLM( model="amd/gemma-4-26B-A4B-it-w8a8-llmcompressor-v0.13.0", dtype="bfloat16", ) sampling_params = SamplingParams(temperature=0.7, max_tokens=256) outputs = model.generate(["Hello, how are you?"], sampling_params) print(outputs[0].outputs[0].text)

OpenMP 环境变量(性能优化):CPU 推理前建议先设置LD_PRELOAD指向libomp.so(LLVM OpenMP)或libiomp5.so(Intel OpenMP),再启动 vLLM:

export LD_PRELOAD=$(find /path/to/env -name "libomp.so" | head -1)

⚠️ 两个使用限制(见 README.md Limitations):该模型版本锁定(ZenDNN v6.1.0 / ZenTorch v2.13.0.2 / PyTorch v2.13.0.2),其他版本可能无法正确加载;且仅面向AMD EPYC CPU 推理,不是为 GPU 推理准备的。

仓库文件速查表

文件说明
README.md模型卡:量化细节、oneshot 脚本、vLLM 用法、评测与限制
recipe.yaml量化配方:W8A8 方案、targets 与 ignore 清单
config.json模型架构 +quantization_config(compressed-tensors 量化元信息、ignore 层列表)
generation_config.json生成默认参数(temperature、top_k=64、top_p=0.95 等)
processor_config.json多模态处理器配置(图像/视频/音频)
tokenizer_config.json / tokenizer.json分词器配置与词表(含<image>、<video>等多模态特殊 token)
chat_template.jinja对话模板
model-00001-of-00002.safetensors / model-00002-of-00002.safetensors / model.safetensorsINT8 量化权重(分片)与合并权重,共约 25.3 GiB
model.safetensors.index.json权重分片索引
LICENSE / NOTICE.txt许可证与版权声明

总结

用 LLM Compressor 复现 W8A8 量化的完整流程其实只有 5 步:读配置 → 按架构名加载 BF16 模型 → 定义 QuantizationModifier 配方(scheme + targets + ignore)→ 调用 oneshot 一键量化 → 补存 Processor 并冒烟测试。关键在于两处细节:一是对复合多模态 MoE 模型必须用config.architectures[0]指定类加载,二是 MoE 路由器、视觉塔和lm_head必须保留 BF16。按本教程操作,你就能得到与 gemma-4-26B-A4B-it-w8a8-llmcompressor 相同规格的量化模型——体积减半、精度近乎无损。

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询