LLM 大模型量化技术、QLoRA 及常用量化库详解
详细阐述了 LLM 大模型的量化技术,涵盖浮点数与定点数转换原理、PTQ 与 QAT 分类、线性与非线性量化方法。重点解析了 BnB、GPTQ、AWQ、HQQ 等主流量化算法的核心机制与适用场景,并结合 QLoRA 展示了如何在低资源环境下进行模型微调。此外,文章对比了 AutoGPTQ、Bitsandbytes、GGML 等常用量化库的性能特点与代码实践,帮助开发者根据显存限制与精度需求选择合适的量化方案。

详细阐述了 LLM 大模型的量化技术,涵盖浮点数与定点数转换原理、PTQ 与 QAT 分类、线性与非线性量化方法。重点解析了 BnB、GPTQ、AWQ、HQQ 等主流量化算法的核心机制与适用场景,并结合 QLoRA 展示了如何在低资源环境下进行模型微调。此外,文章对比了 AutoGPTQ、Bitsandbytes、GGML 等常用量化库的性能特点与代码实践,帮助开发者根据显存限制与精度需求选择合适的量化方案。

模型的推理过程是一个复杂函数的计算过程,这个计算一般以矩阵乘法为主,也就是涉及到了并行计算。一般来说,单核 CPU 可以进行的计算种类更多,速度更快,但一般都是单条计算;而显卡能进行的都是基础的并行计算,做矩阵乘法再好不过。如果把所有的矩阵都加载到显卡上,就会导致显卡显存的占用大量增加,尤其是 LLM 模型大小从 7b、14b、34b 到几百 b 不等,占用显存的大小就是惊人的数字。如何在减少运算量和显存占用的条件下,做到推理效果不下降太多呢?在这里需要引入浮点数和定点数的概念。
量化是将模型浮点数变为定点数运行的过程。
双精度浮点数:在 PyTorch 中用 torch.float64 表示,或者在其他语言中也称为 double 类型,在 LLM 训练中一般比较少用。
全精度浮点数:在 PyTorch 中用 torch.float32 表示。
低精度浮点数:在 PyTorch 中用 torch.bfloat16 和 torch.float16 表示。这两个浮点数的差别如下:
bfloat16 的小数部分较短,整数部分较长,这会有利于在训练中减少梯度爆炸的情况(即梯度累加值超过了最大值),但是这种数据类型是在 N 系列显卡 Ampere 系列才支持的,即 30 系列 显卡。float16 的小数部分较长,这意味着在精度控制上 float16 更好,但整数部分较短,比较容易梯度爆炸。那么是否有更加减少显存占用和计算量的数值表达方式呢?那么可以考虑是否把浮点数转换为定点数(整数),整数计算更快更省显存,如果计算精度下降不大就很完美了。这种用整数计算代替浮点数计算的方法就是量化。
量化的基本原理是根据每个 tensor 的浮点型最大值和最小值,将其映射为一个固定范围的整形数值集合,比如 [-127~127]。假设一个简单的公式:qweight=round(weight/scale),其中 qweight 代表量化后权重,weight 代表量化前权重,scale 代表缩放因子,可以看到在进行缩放后为了将浮点型转换为整数过程中增加了 round 操作丢失了小数部分。在后续计算或反量化为浮点型时存在无法完全还原的情况,这就是精度损失。
按照量化发生的步骤区分,可以划分为PTQ(训练后量化,或离线量化)和 QAT(训练感知型量化,或在线量化)。PTQ 量化可以分为 data-free 和 calibration 两种,前者不使用数据集进行校准直接计算量化因子,后者会根据少量真实数据进行统计分析并对量化因子进行额外校准,但耗费的时间更长。QAT 量化会先在待量化的算子上增加一个伪量化结构,并在训练时模拟量化过程并实时更新计算量化因子(类似反向传播过程)及原始权重。QAT 由于较为复杂一般作为辅助措施存在,用于改进 PTQ 量化的技术手段。
按照量化方法可以划分为线性量化、非线性量化(如对数量化)等多种方式,目前较为常用的是线性量化。其中线性量化又可以按照对称性划分为对称量化和非对称量化,非对称量化为了解决 weight 分布不均匀问题,其在公式中增加了 zero_point 项:qweight=round(weight/scale + zero_point),使稠密数据部分可以得到更宽泛的数值范围。
按照量化粒度划分可以分为**逐层量化(每层使用一套量化因子)、逐组量化(在每层中按照 group 使用一套量化因子)、逐通道量化(按 channel 划分量化因子)**等几种方式。
按照量化最大值的阈值区分,可以分为饱和量化和不饱和量化两种。不饱和量化按照浮点数最大值和量化后最大值的比例计算量化因子,由于原始 weight 的非均匀性会导致某些整形数值范围存在权重空缺。饱和量化会计算一个中间值以计算出量化因子,因此会舍弃一部分不重要数据,将重要数据尽量均匀的分布到量化数值范围内。
按照量化后的比特数划分,可以分为 2 比特量化,4 比特量化,8 比特量化等类型。
一般来说,PyTorch 中量化模块的 forward 过程会先对量化权重进行反量化后使用浮点数进行计算。
量化简单来说:将用小数计算结果的模型,转换成用整数计算,中间自然有精度损失(因为小数位没了,而且浮点数翻译成整形再转回来是有损压缩过程)。
有了这个定义,我们就可以继续下面要讲的部分。在继续下面的内容之前,还是建议大家把上面的模型量化基础读一遍。下面会基于之前的文章,侧重几个方面进行技术分析:
BnB 全称是 BitsAndBytes,是几乎最早集成到 transformers 框架中的量化算法。
我们回顾一下量化的基本思路:
bitsandbytes.LLM.int8() 算法也是基于上面的思路的,特殊之处在于,在分析 weights 矩阵的稀疏性质后,总结了下面的特性:
针对离群值的量化算法其实有很多方式,比如分段量化,BnB 采用了针对离群值保持低精度浮点数的做法:
在实际实验中,BnB 算法发现以 6 为尺度分割出离群值是最佳的。
由于 BnB 量化不需要任何校准数据集,因此其量化速度很快,这也是为什么在 QLoRA 训练时,会直接传入 BitsAndBytesConfig 直接对原始模型量化后训练。
而在 QLoRA 论文中,作者介绍了 4bit 量化、双重量化和分页 optimizer 的技术方案。
4bit 量化支持两种数据类型:fp4 和 nf4。fp4 是四 bit 浮点数,包含一位符号位,两位整数位和一位小数位。nf4 全称是 4-bit NormalFloat,和 fp4 类似,但是其数值分布并不均匀,呈现正态分布。这是因为一般 LLM 的矩阵参数概率密度也是呈现正态分布的。在 4bit 量化中,也更推荐使用 nf4 数据类型,因为可以比较好的契合参数特性。
nf4 的量化思路可以理解为:一般模型 weights 是均值为 0,标准差为σ的的分布,因此该分布可以转换为标准高斯分布。这样可以从标准高斯分布中取样一定分位数的量化间隔并设定量化值(该值采用两边分位数的均值),并且正则化到 [-1, 1] 区间中。后续就可以将模型 weights 通过 absmax 量化到该区间中。
双重量化指的是针对量化常数的二次量化。由于 BnB 的量化是块量化(block-wise),因此块级别的常数存储也会占用 GPU memory。对此,在一次量化后针对此类常数进行二次量化,进一步压缩显存空间。
说到 GPTQ,就要说起它的老祖先 OBD、OBS、OBC 等剪枝算法(否则无法理解 GPTQ)。本质上来说,参数剪枝是参数量化的一种特殊情况(把参数直接置为 0 这个特殊量化值)。
GPTQ 使用了泰勒级数分解,使用海森矩阵评估参数重要性以及更新量化后的参数,并利用现代 GPU 的特点,进行了并行计算,使显存占用和处理速度大大增加,但是它需要量化集辅助量化。
AWQ(Activation-aware Weight Quantization)认为部分参数更加重要,通过激活值尺度评估了重要参数后,对这些参数按组进行了缩放,达到了减小 Loss 的效果,由于需要激活值,因此 AWQ 也需要量化集辅助量化。
AWQ 是一种对模型权重进行低比特量化的方法,使用该方法可以将模型权重 (Weight) 量化为 4bit,并在计算激活值 (Activation) 时反量化为 FP16,即 W4A16。也可以基于 AWQ 方法将权重量化为 3bit/8bit,并在计算时是使用 4bit/8bit/16bit,由此衍生出 W4A4、W4A8 等一系列方法。作者在原文中指出,W4A16 可以在精度损失较小的情况下,大幅降低内存占用,且提升模型推理速度,是最常用的方法,因此 AWQ 和 W4A16 同镜率较高。
AWQ 的核心技术一是这个对激活和权重应用 scale 的方法,另外就是如何计算这个 scale tensor。因为激活是 fp16 不量化,对激活进行 scale 一般不会牺牲精度,因此可以对权重进行一些处理降低量化的难度。
HQQ 通过对零点量化的公式转换,将其分解为两个子问题分别求解,找到最优的 z,该迭代对输入无要求,因此不需要量化集。
前提:量化是把模型的浮点型参数转换为整形(至少是更低的 bit 数)的过程,减少显存占用。
LoRA 部分可以参考另外一篇文章。
简单来说,LoRA 是附着在模型上的额外参数矩阵,在训练时冻结原模型,仅训练 LoRA 部分。如果原模型是量化后的 weights(即左边的 Pretrained Weights 部分),那么和 LoRA 可以很匹配:原模型占用的显存大大减小了,LoRA 部分保持 fp16/bf16 可以正常 forward/backward。
除上面介绍的量化方法外,还有很多其他类型的量化方法,比如 AQLM、EETQ、GGUF 等,这么多的量化方式,一个一个了解使用太麻烦了,在不修改训练代码的情况下适配多种量化策略是非常重要的。
在这里使用了魔搭社区的 SWIFT 框架来进行量化训练。该框架在 github 上是开源的。
或者通过 pip 安装:
pip install ms-swift
#autoawq 和 cuda 版本有对应关系,请按照官方文档选择版本
pip install autoawq -U
#auto_gptq 和 cuda 版本有对应关系,请按照官方文档选择版本
pip install auto_gptq -U
#hqq 和 eetq 使用暂时需要从源码下载 transformers 和 peft
pip install git+https://github.com/huggingface/transformers
pip install git+https://github.com/huggingface/peft.git
#hqq
pip install hqq
#eetq
git clone https://github.com/NetEase-FuXi/EETQ.git
cd EETQ/
git submodule update --init --recursive
pip install .
回顾下上面提到的量化方式,bnb/hqq/eetq 是不需要量化数据集的,因此可以在训练前直接量化模型,速度很快。因此推荐即时量化后直接 QLoRA 训练模型:
swift sft --model_type llama3-8b-instruct --dataset alpaca-en --quantization_bit 8 --quant_method bnb --sft_type lora
也可以替换为 hqq 或者 eetq:
swift sft --model_type llama3-8b-instruct --dataset alpaca-en --quantization_bit 8 --quant_method eetq --sft_type lora
其中 bnb 支持 4/8 bit 量化,eetq 支持 8bit 量化,hqq 支持 1/2/3/4/8bit 量化。
而 GPTQ 和 AWQ 由于需要量化集的存在,且量化会花费较长时间,因此一般在训练后 (或者针对原始模型) 再单独量化:
#GPTQ
OMP_NUM_THREADS=14 swift export --model_type llama3-8b-instruct --quant_method gptq --dataset alpaca-zh alpaca-en sharegpt-gpt4-mini --quant_seqlen 4096 --quant_bits 4
#AWQ
swift export --model_type llama3-8b-instruct --quant_bits 4 --quant_method awq --quant_n_samples 64 --quant_seqlen 4096 --dataset alpaca-zh alpaca-en sharegpt-gpt4-mini
注意,实际使用 GPTQ 量化时需要指定 OMP_NUM_THREADS=N,否则会出现 CPU 占满阻塞的问题。
swift export 指令会使用指定的数据集对模型进行量化,并在本地保存量化后的模型,默认的保存路径为 {model_type}-{quant_method}-{quant_bits},也可以通过 --quant_output_dir 来指定。
QLoRA 可以支持 FSDP(完全分片数据并行技术),因此可以使用 BNB+LoRA 在两张 24G 显卡上运行一个 70B 模型的训练:
#源代码 clone
#cd examples/pytorch/llm
#vim fsdp.sh 并写入下面的内容
#pip install bitsandbytes>=0.43.0
nproc_per_node=2
CUDA_VISIBLE_DEVICES=0,1 \
accelerate launch --config_file "./scripts/llama2_70b_chat/qlora_fsdp/fsdp_offload.json" \
llm_sft.py \
--model_type llama2-70b-chat \
--model_revision master \
--sft_type lora \
--tuner_backend peft \
--template_type AUTO \
--dtype bf16 \
--output_dir output \
--dataset leetcode-python-en \
--train_dataset_sample -1 \
--num_train_epochs 1 \
--max_length 2048 \
--check_dataset_strategy warning \
--quantization_bit 4 \
--bnb_4bit_comp_dtype AUTO \
--bnb_4bit_quant_storage bfloat16 \
--lora_rank 8 \
--lora_alpha 32 \
--lora_dtype AUTO \
--lora_dropout_p 0.05 \
--lora_target_modules DEFAULT \
--gradient_checkpointing true \
--batch_size 1 \
--weight_decay 0.1 \
--learning_rate 1e-4 \
--gradient_accumulation_steps $(expr 16 / $nproc_per_node) \
--max_grad_norm 0.5 \
--warmup_ratio 0.03 \
--eval_steps 50 \
--save_steps 50 \
--save_total_limit 2 \
--logging_steps 10 \
如果只是想体验量化后的模型推理阶段,可以借助不需要校准数据集的量化方法,使用 swift infer 来量化模型并推理,大大减少模型推理所需的显存占用。
CUDA_VISIBLE_DEVICES=0 swift infer \
--model_type qwen1half-7b-chat \
--quant_method bnb \
--quantization_bit 4
CUDA_VISIBLE_DEVICES=0 swift infer \
--model_type qwen1half-7b-chat \
--quant_method hqq \
--quantization_bit 4
CUDA_VISIBLE_DEVICES=0 swift infer \
--model_type qwen1half-7b-chat \
--quant_method eetq \
--dtype fp16
AutoGPTQ 是一个易于使用的低延迟语言模型(LLM)量化软件包,具有用户友好的 API,基于 GPTQ 算法。一个基于 GPTQ 算法,简单易用且拥有用户友好型接口的大语言模型量化工具包。
以下结果通过脚本生成,文本输入的 batch size 为 1,解码策略为 beam search 并且强制模型生成 512 个 token,速度的计量单位为 tokens/s(越大越好)。
| model | GPU | num_beams | fp16 | gptq-int4 |
|---|---|---|---|---|
| llama-7b | 1xA100-40G | 1 | 18.87 | 25.53 |
| llama-7b | 1xA100-40G | 4 | 68.79 | 91.30 |
| moss-moon 16b | 1xA100-40G | 1 | 12.48 | 15.25 |
| moss-moon 16b | 1xA100-40G | 4 | OOM | 42.67 |
| moss-moon 16b | 2xA100-40G | 1 | 06.83 | 06.78 |
| moss-moon 16b | 2xA100-40G | 4 | 13.10 | 10.80 |
| gpt-j 6b | 1xRTX3060-12G | 1 | OOM | 29.55 |
| gpt-j 6b | 1xRTX3060-12G | 4 | OOM | 47.36 |
量化模型通过能够最大化推理速度的方式加载。
该库需要引入额外的校准数据集进行量化校准。相比 bitsandbytes 量化精度较高,推理速度较快,但训练后不支持合并 adapter。
from modelscope import AutoTokenizer, snapshot_download
from auto_gptq import AutoGPTQForCausalLM, BaseQuantizeConfig
import logging
import shutil
import os
logging.basicConfig(
format="%(asctime)s %(levelname)s [%(name)s] %(message)s", level=logging.INFO, datefmt="%Y-%m-%d %H:%M:%S"
)
pretrained_model_dir = snapshot_download("qwen/Qwen-1_8B-Chat")
quantized_model_dir = "qwen-1_8B-4bit"
shutil.rmtree(quantized_model_dir, ignore_errors=True)
shutil.copytree(pretrained_model_dir, quantized_model_dir)
for _file in os.listdir(quantized_model_dir):
if ".safetensors" in _file or ".bin" in _file:
os.remove(os.path.join(quantized_model_dir, _file))
tokenizer = AutoTokenizer.from_pretrained(pretrained_model_dir, use_fast=True, trust_remote_code=True)
examples = [
tokenizer(
"auto-gptq is an easy-to-use model quantization library with user-friendly apis, based on GPTQ algorithm."
)
]
quantize_config = BaseQuantizeConfig(
bits=4, # quantize model to 4-bit
group_size=128, # it is recommended to set the value to 128
desc_act=False, # set to False can significantly speed up inference but the perplexity may slightly bad
)
#load un-quantized model, by default, the model will always be loaded into CPU memory
model = AutoGPTQForCausalLM.from_pretrained(pretrained_model_dir, quantize_config, trust_remote_code=True).to(0)
#quantize model, the examples should be list of dict whose keys can only be "input_ids" and "attention_mask"
model.quantize(examples)
#save quantized model
model.save_quantized(quantized_model_dir)
#save quantized model using safetensors
model.save_quantized(quantized_model_dir, use_safetensors=True)
#load quantized model to the first GPU
model = AutoGPTQForCausalLM.from_quantized(quantized_model_dir, device="cuda:0", trust_remote_code=True)
#inference with model.generate
print(tokenizer.decode(model.generate(**tokenizer("auto_gptq is", return_tensors="pt").to(model.device))[0]))
在 SWIFT 中,可以使用已经量化好的 AutoGPTQ 模型直接进行训练:
swift sft --model_id_or_path qwen/Qwen-7B-Chat-Int4 --model_revision master --sft_type lora --tuner_backend swift --template_type qwen --dtype fp16 --output_dir output --dataset leetcode-python-en --train_dataset_sample -1 --num_train_epochs 1 --max_length 512 --check_dataset_strategy warning --lora_rank 8 --lora_alpha 32 --lora_dropout_p 0.05 --lora_target_modules ALL --gradient_checkpointing true --batch_size 1 --weight_decay 0.01 --learning_rate 1e-4
上面的命令行中,qwen/Qwen-7B-Chat-Int4 是已经量化好的 Qwen-7B-Chat 模型。
bitsandbytes 是一种 data-free 的量化库。该量化方法速度较快(因为其不需要数据校准),因此可以在模型加载时动态量化,且该方法训练速度较快,因此训练兼容性较好,一般用于 QLoRA 训练中,且训练后可以合并 adapter。当由于其没有数据校准过程,因此精度较 AutoGPTQ 较低。
from modelscope import AutoModelForCausalLM, AutoTokenizer
import torch
model = AutoModelForCausalLM.from_pretrained(
'qwen/Qwen-1_8B-Chat',
load_in_8bit=True,
trust_remote_code=True)
tokenizer = AutoTokenizer.from_pretrained('qwen/Qwen-1_8B-Chat', trust_remote_code=True)
print(model(**tokenizer('how are you?', return_tensors='pt')))
GGML 和 GGUF 是 C++ 推理库的两种量化格式,其中 GGUF 格式较新,可以保留模型版本等其他自定义信息。这两种格式也是 PTQ 形式的量化算法,但 GGML 和 GGUF 格式的量化算法更适配于 CPU 推理,因此在 CPU 上运行更快,而 GPTQ 量化对 GPU 更加友好,两者的推理精度相仿。因此,*.cpp 类型使用了 GGML 推理库的推理框架都更适配于 CPU 推理。
GGML 是一个专注于机器学习的 C 库。它由 Georgi Gerganov 创建,这就是缩写'GG'的含义。这个库不仅提供了机器学习的基础元素,如张量,而且还提供了一种独特的二进制格式来分发 LLM(Machine Learning Models)。最近,这个格式改为了 GGUF。这种新格式被设计为可扩展的,以便新功能不会影响现有模型的兼容性。
它还将所有的元数据集中到一个文件中,例如特殊标记、RoPE 缩放参数等等。简言之,它解决了一些历史上的痛点,并且应该具备未来兼容性。
接下来的文章中,我们将称之为'GGML 模型'的所有模型,无论是使用 GGUF 还是之前的格式。
GGML 是为与 Georgi Gerganov 创作的 llama.cpp 库一起使用而设计的。该库是用 C/C++ 编写的,用于高效地推断 Llama 模型。它可以加载 GGML 模型并在 CPU 上运行。最初,这是与 GPTQ 模型的主要区别,后者是在 GPU 上加载和运行的。然而,现在您可以使用 llama.cpp 将 LLM 的某些层卸载到 GPU 上。举个例子,7b 参数模型有 35 个层。这极大地加快了推断速度,并使您能够运行不适合 VRAM 的 LLM。
如果命令行工具是你的菜,llama.cpp 和 GGUF 支持已经集成到许多图形界面中,例如 oobabooga 的文本生成 Web 界面,koboldcpp,LM Studio 或 ctransformers。
你可以使用这些工具加载你的 GGML 模型并以类似 ChatGPT 的方式与它们进行交互。幸运的是,许多量化模型可以直接在 Hugging Face Hub 上获取。你很快就会注意到大部分模型都是由 LLM 社区的知名人物 TheBloke 进行量化的。
方式假设不是所有权重都影响模型性能,因此在量化过程中会对特殊权重进行特殊处理以减轻量化过程中的精度损失。因此在和 GPTQ 量化保持类似推理速度的同时可以具备更好的精度。
AWQ 是一种对模型权重进行低比特量化的方法,使用该方法可以将模型权重 (Weight) 量化为 4bit,并在计算激活值 (Activation) 时反量化为 FP16,即 W4A16。也可以基于 AWQ 方法将权重量化为 3bit/8bit,并在计算时是使用 4bit/8bit/16bit,由此衍生出 W4A4、W4A8 等一系列方法。作者在原文中指出,W4A16 可以在精度损失较小的情况下,大幅降低内存占用,且提升模型推理速度,是最常用的方法,因此 AWQ 和 W4A16 同镜率较高。
AWQ(Activation-aware Weight Quantization)方法由 MIT、SJTU、Tsinghua University 联合提出的方法,一种对大模型仅权重量化方法。该方法基于'权重并不同等重要'的观察,仅保护 1% 的显著权重(salient weight)可以大大减少量化误差。AWQ 不依赖于任何反向传播或重建,因此可以很好地保持 LLM 在不同领域和模式上的泛化能力,而不会过拟合到校准集;它也不依赖于任何数据布局重新排序,保持硬件效率。AWQ 在多种语言建模、常识问答和领域特定基准测试中优于现有工作。得益于更好的泛化能力,它在指令微调 LM 和首次实现多模态 LM 方面取得了出色的量化性能。论文还实现了有效的张量核心内核,以加速 AWQ 的无重新排序在线反量化,实现速度比 GPTQ 快 1.45 倍,比 cuBLAS FP16 实现快 1.85 倍。
目前 VLLM 对 AWQ 的支持较好,可以考虑在推理加速时使用 AWQ 量化方式。
AWQ 量化精度比 GPTQ 高一点,并且 AWQ 比 GPTQ 更容易实现,[计算性能] 更高。
相比 AWQ 采用 heuristic 的方法来寻找 [最佳的] scale 和 clip 系数,新的 OminiQuant 则采用训练的方式来获得相应的系数,论文数据比 AWQ 获得更高的量化准确度。
AWQ 的原理非常简单,就是计算一个 scale 系数 tensor,shape 为 [k],k 为矩阵乘的权重 reduce 的维度大小。对激活除以该 tensor,并对矩阵乘的权重乘以该 tensor,这降低了权重量化的难度,使得权重可以采用常规的 group 量化 (直接根据最大最小值计算 scale, zero point)。AWQ 的核心技术一是这个对激活和权重应用 scale 的方法,另外就是如何计算这个 scale tensor。因为激活是 fp16 不量化,对激活进行 scale 一般不会牺牲精度,因此可以对权重进行一些处理降低量化的难度。
虽然 AWQ 与 GPTQ 两者都采用 group 量化,对 shape 为 [k, n] 的矩阵乘权重都生成 (k/group) * n 套量化系数。但是 GPTQ 通常采用 act_order=True 选项,这个导致每一个 group 并非使用一组相同的 scale 和 zero point 系数,而是每个 k 位置对应的向量都对应不同的 scale 和 zero point(不同 k 位置共享一组系数,但是这个位置是随机的),每读取一个元素都要读取 scale 和 zero point,导致反量化效率很低。而 act_order=False 时,每一个向量 group size 元素都共享同一组 scale 和 zero point 系数,这样反量化只需要每隔 group size 个元素才需要重新读取一次 scale 和 zero point,反量化效率很高。AWQ 反量化跟 GPTQ act_order=False 是一样的,因此计算效率比较高。
另外 AWQ 虽然要对激活乘以一个 scale tensor,但是这个 tensor 通常可以合并到前面的 RMS NORM 上面,使得这个操作不会引入额外计算。
awq 量化例子 llama_example.sh 给了 4 个步骤
MODEL=llama-7b
#run AWQ search (optional; we provided the pre-computed results)
python -m awq.entry --model_path /dataset/llama-hf/$MODEL \
--w_bit 4 --q_group_size 128 \
--run_awq --dump_awq awq_cache/$MODEL-w4-g128.pt
#evaluate the AWQ quantize model (simulated pseudo quantization)
python -m awq.entry --model_path /dataset/llama-hf/$MODEL \
--tasks wikitext \
--w_bit 4 --q_group_size 128 \
--load_awq awq_cache/$MODEL-w4-g128.pt \
--q_backend fake
#generate real quantized weights (w4)
python -m awq.entry --model_path /dataset/llama-hf/$MODEL \
--w_bit 4 --q_group_size 128 \
--load_awq awq_cache/$MODEL-w4-g128.pt \
--q_backend real --dump_quant quant_cache/$MODEL-w4-g128-awq.pt
#load and evaluate the real quantized model (smaller gpu memory usage)
python -m awq.entry --model_path /dataset/llama-hf/$MODEL \
--tasks wikitext \
--w_bit 4 --q_group_size 128 \
--load_quant quant_cache/$MODEL-w4-g128-awq.pt
第一步生成 scale 和 clip 数据并保存文件。
第二步为加载第一步生成的量化系数,并评估量化性能。
第三步加载第一步生成的量化系数,对模型真实权重进行量化和保存量化模型权重。
第四步为评估真实量化模型。
当然这几个步骤是可以通过参数配置合并为一个的。
第一步会下载一个数据集,在 utils/calib_data.py。默认的数据集可能无法下载,可以进行替换,或者手动下载下来用本地路径进行替换。
AWQ 量化通过 auto_scale_block 和 auto_clip_block 方法对每个权重生成一组 scale 和 clip tensor,通过一个 list 存放到量化系数结果里面。
auto_scale_block 的核心为_auto_get_scale,基于当前 transformer layer 的输入,一个 module2inspect 层用于评估 loss,然后通过 grid search 的方式来搜索最佳的 scale 系数。
本文详细介绍了 LLM 大模型的量化技术,包括基本概念、主流量化算法(BnB、GPTQ、AWQ、HQQ)的原理与差异,以及 QLoRA 在微调中的应用实践。同时梳理了 AutoGPTQ、Bitsandbytes、GGML 等常用量化库的特性与使用场景。选择合适的量化方案需要在显存占用、推理速度和模型精度之间取得平衡,开发者应根据具体硬件环境和业务需求灵活选用。

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online
基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online
解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online