案例8 模型量化
案例八:量化
模型量化(Quantization)是一种通过降低神经网络权重精度来压缩模型大小的技术。对于大型语言模型(LLM)而言,量化技术尤其重要。研究表明,尽管神经网络的训练和推理过程中某些步骤需要高精度计算,但在许多其他情况下,使用较低精度(如INT8)计算不仅能显著减小模型体积,还能够让模型在硬件性能较弱的设备上运行,同时保持可接受的性能和准确性。
在实际应用中,模型量化可以分为以下几种类型:
- 后训练量化(Post-training Quantization):在模型训练完成后,对权重进行离线量化处理,简单易用但精度下降可能较大。
- 量化感知训练(Quantization Aware Training, QAT):在训练阶段引入量化模拟,训练出的模型对量化后的误差更鲁棒,精度更高。
- 动态量化(Dynamic Quantization):在推理阶段对权重进行量化,适合推理为主的轻量部署场景。
模型推理过程本质上是大量复杂数学运算的组合,尤其依赖于矩阵运算,这恰恰是并行计算的优势所在。尽管单核CPU能够执行多种计算任务并且在处理单一任务时表现较为高效,但其更适合顺序执行的任务。相比之下,GPU(图形处理单元)最初是为图形计算设计的,因此它特别擅长并行处理多个简单任务,尤其是大规模矩阵乘法,而这正是深度学习模型训练和推理过程中的常见计算操作。
然而,将整个模型加载到GPU中往往会大幅提高显存的占用量。尤其是对于大型语言模型(如参数量达到7B、14B、34B甚至数百B的模型),这会导致显存需求急剧增加。因此,在实际应用中,必须精心设计数据加载策略,例如采用混合精度训练、模型并行化或分布式训练等方式,以优化资源使用,确保在充分利用GPU并行计算能力的同时,不会因为显存不足而影响模型性能。
在深度学习中,不同的数值精度类型在计算性能与模型表现之间存在权衡,常见的包括:
双精度浮点数:(torch.float64):用于数值精度要求极高的场景,如科学计算,但由于显存开销大、计算速度慢,在大型语言模型(LLM)训练中使用较少。
全精度浮点数:(torch.float32):是深度学习中最常用的浮点数类型,兼顾了计算效率与精度,是训练大多数模型的默认精度。
低精度浮点数:
- bfloat16:具有较长的指数位和较短的小数位,能较好地保持数值范围,减少梯度爆炸风险。但其硬件支持受限,仅在如 NVIDIA Ampere 架构及以上的设备上原生支持。
- float16:小数位更多,精度更高,但由于指数位短,容易发生数值溢出或梯度爆炸。在训练过程中通常需要配合梯度缩放等技术来稳定训练。
为了进一步降低显存占用并提升计算效率,可以将浮点数转换为更低位宽的定点整数类型。因为整数计算在硬件上更高效、占用更少资源,这种转换正是模型**量化(Quantization)**的核心思想。
⚙️ 量化的基本原理如下:
量化的目标是将原始张量中的浮点数压缩映射到较小范围内的整数(如 INT8),其基本流程包括:
- 缩放:利用一个缩放因子 scale 将浮点值映射到整数区间;
- 舍入:对映射后的值进行舍入以获取整数;
- 截断:限制整数值在固定的量化范围(如 [−128, 127])内;
- 反量化(dequantization):在推理过程中,将整数值还原为近似的浮点值。
由于中间的舍入步骤会丢弃小数部分信息,反量化后的值无法完全恢复为原始数据,这种误差被称为量化误差或精度损失。简而言之,量化是用空间换取性能的权衡过程,适用于对精度容忍度较高、资源受限的模型部署场景。
🧩 PyTorch 中常见量化方法及代码示例
PyTorch 提供了三种主要的量化方式:
1. 静态量化(Post-Training Static Quantization)
适用于训练后部署,需要对模型进行校准(calibration)以估计量化参数。
import torch
from torch.quantization import quantize_static, get_default_qconfig, prepare, convert
# 示例模型
model = MyModel()
model.eval()
# 设置量化配置
model.qconfig = get_default_qconfig('fbgemm') # 适用于x86架构
prepare(model, inplace=True)
# 使用校准数据前向传播一次,收集激活的量化范围
with torch.no_grad():for inputs in calibration_loader:model(inputs)
# 转换为量化模型
convert(model, inplace=True)
2. 动态量化(Dynamic Quantization)
适用于仅量化权重,激活值在运行时动态量化。无需校准数据。
import torch
from torch.quantization import quantize_dynamicmodel = MyModel()
quantized_model = quantize_dynamic(model,{torch.nn.Linear}, # 通常量化线性层dtype=torch.qint8
)
优点:操作简单、无需重新训练
缺点:精度可能略有下降,主要适合推理阶段
3. 量化感知训练(Quantization Aware Training, QAT)
训练阶段模拟量化行为,提升最终模型的量化精度。
import torch
from torch.quantization import prepare_qat, convert, get_default_qat_qconfigmodel.train()
model.qconfig = get_default_qat_qconfig('fbgemm')
prepare_qat(model, inplace=True)
# 常规训练流程
for epoch in range(num_epochs):for inputs, targets in train_loader:outputs = model(inputs)loss = loss_fn(outputs, targets)loss.backward()optimizer.step()optimizer.zero_grad()
# 最终量化
model.eval()
convert(model, inplace=True)
8.1 量化分类
量化方法可从三个主要角度进行分类,一是按量化引入的时机,二是按数值映射的方式,三是按量化粒度分类。前者决定量化是在训练前后进行,后者决定浮点数如何映射到整数。
📌 一、按引入时机分类
1. 训练后量化(PTQ, Post-Training Quantization)
PTQ 是在模型训练完成后,对已有的全精度模型进行量化。通常只需模型权重和少量校准数据,无需重新训练,适合模型快速部署。
优点:
-
无需重新训练,部署成本低;
-
可直接应用于现有预训练模型;
-
实施简单,工程集成性好。
缺点:
-
精度下降可能较明显;
-
对分布复杂、非线性的模型,校准数据难以精确估计量化参数。
根据是否使用校准数据,PTQ 又可分为:
✅ 无数据校准(Data-Free Quantization)
仅依赖模型权重或结构本身进行量化,例如通过假设分布、最大最小值估计缩放因子。
✅ 有数据校准(Calibration-Based Quantization)
使用小规模样本集,通过统计分析激活分布,确定更精确的缩放因子和零点,能显著提升精度表现,代价是增加一定校准时间。
2. 训练感知量化(QAT, Quantization-Aware Training)
QAT 在训练阶段引入量化仿真模块,模拟推理过程中的量化行为,使模型在训练中逐步适应精度损失,通常能获得与原始模型接近的精度。
优点:
- 精度保持更好,适合对精度敏感的任务;
- 模型学到的权重本身就已适应量化过程。
缺点:
-
训练复杂度更高,需更改训练流程;
-
增加了训练时间与计算资源消耗。
📌 二、按数值映射方式分类
1. 线性量化(Linear Quantization)
线性量化通过线性变换将浮点数 x x x 映射为整数值 q q q,其计算公式如下:
q = round ( x − zero_point scale ) q = \text{round}\left( \frac{x - \text{zero\_point}}{\text{scale}} \right) q=round(scalex−zero_point)
其中: x x x 是原始浮点值; scale \text{scale} scale:为缩放因子,用于将浮点数映射到整数范围; zero_point \text{zero\_point} zero_point 是零点,用于调整偏移,使量化后的数值对称分布; round ( ⋅ ) \text{round}(\cdot) round(⋅) 为四舍五入函数。
根据零点设定方式的不同,可进一步分为:
-
对称量化(Symmetric Quantization)
假设浮点值分布关于零对称,因此固定零点为 0,仅需要一个缩放因子(scale)。 -
非对称量化(Asymmetric Quantization)
不假设对称性,允许任意零点,能够更准确适配非对称分布(如激活值常偏正)。
📌 对比说明:
类型 | 零点 | 精度 | 适用场景 |
---|---|---|---|
对称量化 | 固定为0 | 较高 | 权重分布对称时 |
非对称量化 | 可变 | 更好 | 激活值不对称时 |
2. 非线性量化(Non-Linear Quantization)
非线性量化使用非线性函数对数值进行映射,更好地拟合实际权重/激活的分布,适用于分布集中、动态范围较大的模型。
常见非线性方法包括:
-
对数量化(Log Quantization)
将值转换为对数域以保留小值信息,适合动态范围大的特征。 -
指数量化(Exponential Quantization)
将值映射到指数级数值,常用于稀疏或权重分布极不均匀的模型中。
✅ 小结
✅ 模型量化分类方式及特点对比
分类方式 | 类别 | 特点 |
---|---|---|
按引入时机 | PTQ | 快速部署,简单实用,但精度可能损失较大 |
QAT | 精度更高,训练代价较大,适合精度敏感任务 | |
按映射方式 | 线性量化 | 计算高效,适用于大多数模型 |
非线性量化 | 拟合性更强,适合分布复杂场景 |
📌 三、按按量化粒度分类
除了按“时机”和“方式”分类,**量化粒度(granularity)**也是一个重要的分类维度,决定了量化参数在张量中的共享范围,影响精度与效率的权衡。
1. 按通道量化(Per-Channel Quantization)
-
为每个通道单独计算 scale 和 zero point。
-
常用于卷积权重或 Transformer 中的投影矩阵。
-
能显著提高精度,特别是在 PTQ 场景下。
qconfig = torch.quantization.get_default_qconfig('fbgemm')
model.qconfig = torch.quantization.QConfig(activation=qconfig.activation,weight=torch.quantization.PerChannelWeightObserver.with_args(dtype=torch.qint8, qscheme=torch.per_channel_symmetric)
)
2. 按张量量化(Per-Tensor Quantization)
-
整个张量使用一个统一的 scale 和 zero point。
-
实现简单,计算效率高,适合激活量化。
-
精度略逊于按通道量化。
8.2 常用量化技术
8.2.1. BitsAndBytes(BnB):适用于动态加载的高效量化
BitsAndBytes(简称 BnB) 是最早集成进 transformers 框架的量化工具之一,是一种 无需校准数据(data-free) 的动态量化方法。其优势在于:
-
无需校准集,部署简单。
-
支持 模型加载时的动态量化,尤其适用于大模型在线部署。
-
常用于 QLoRA 微调 场景,可与 adapter 合并使用。
-
量化速度快、训练兼容性好,但精度略逊于 AutoGPTQ 等方法。
**核心原理:**针对离群值保留低精度浮点处理,其余部分采用 INT8 量化,主要流程如下:
-
从隐藏状态中按列提取离群值。
-
离群值使用低精度浮点数计算矩阵乘法,非离群值使用 INT8 计算。
-
将非离群值部分进行反量化,与离群值部分相加得到最终输出。
8.2.2. AWQ:关注激活分布的高精度量化
AWQ(Activation-aware Weight Quantization)认为大模型中仅有少部分权重对精度影响显著,提出仅保留约 1% 的显著权重即可显著降低误差。
方法特点:
-
不直接依赖权重信息,而是基于激活分布识别“显著通道”。
-
不需要反向传播或重构过程,具有较强的跨模态、跨任务泛化能力。
-
保留显著权重为 FP16 虽然能提高精度,但对硬件友好性差,因此 AWQ 进一步对这部分权重进行专门量化。
适合场景: 对精度要求较高的模型推理任务。
8.2.3. GPTQ:基于二阶信息的高精度离线量化
GPTQ(Gradient Post-Training Quantization) 是一种高精度、训练后量化(Post-Training Quantization, PTQ)方法,能将权重从 FP16 压缩至 INT4、INT3 等低比特格式,在保持模型精度的同时大幅降低计算与存储需求。
核心原理:
-
基于泰勒展开式,引入 Hessian 二阶矩阵 评估权重重要性。
-
支持任意顺序量化,简化实现且对性能影响较小。
-
延迟批量更新机制 避免频繁内存访问,提升效率。
-
使用 Cholesky 分解 稳定 Hessian 求逆,提高数值鲁棒性。
🎯 GPTQ 的核心数学原理与公式
GPTQ 的目标是在保持模型性能的同时,将一个全精度权重矩阵 W W W 量化为一个低精度矩阵 W ^ \hat{W} W^,从而最小化由于量化引起的模型损失增长。
📌 1. 基于泰勒展开的目标函数
GPTQ 采用了 一阶或二阶泰勒展开 近似损失函数,以衡量量化误差的影响:
二阶泰勒展开形式:
对模型损失函数 L ( W ) L(W) L(W),在权重 W W W 附近展开:
L ( W ^ ) ≈ L ( W ) + 1 2 ( W ^ − W ) T H ( W ^ − W ) \mathcal{L}(\hat{W}) \approx \mathcal{L}(W) + \frac{1}{2}(\hat{W} - W)^T H (\hat{W} - W) L(W^)≈L(W)+21(W^−W)TH(W^−W)
其中: L \mathcal{L} L:原始损失函数; W W W:原始模型参数; W ^ \hat{W} W^:量化后的模型参数; H H H:Hessian 矩阵(二阶导数)
假设梯度项为零(模型已收敛),则目标简化为 最小化如下误差:
min W ^ ( W ^ − W ) T H ( W ^ − W ) \min_{\hat{W}} (\hat{W} - W)^T H (\hat{W} - W) W^min(W^−W)TH(W^−W)
这被称为Hessian 加权的平方误差最小化问题,核心思想是让量化误差在模型损失敏感方向上尽量小。
📌 2. 分块权重矩阵的量化
由于直接对整个矩阵求解代价高,GPTQ 将参数按列(或块)逐列量化。令第 j j j 列的误差为:
e j = W ^ j − W j e_j = \hat{W}_j - W_j ej=W^j−Wj
则损失增加可表示为:
Δ L j = e j ⊤ H j e j \Delta L_j = e_j^\top H_j e_j ΔLj=ej⊤Hjej
其中 H ( j ) H_(j) H(j) 是对应列的 Hessian 子矩阵(一般通过输入数据 X X X 估计)。
📌 3. 延迟批量更新(Lazy Batch Updates)
为了避免每次量化都更新 Hessian,GPTQ 引入延迟批量更新:
-
一次性量化多列后,再对整体误差进行矩阵更新,避免频繁读取内存。
-
更新公式如下:
假设量化了第 k k k 列后,更新下一个列的梯度信息:
g i + 1 = g i + H i , k ( W k − W ^ k ) g_{i+1} = g_i + H_{i,k}(W_k - \hat{W}_k) gi+1=gi+Hi,k(Wk−W^k)
其中 g g g 是损失梯度估计, H i , k H_{i,k} Hi,k 是海森矩阵中第 i i i 行和第 k k k 列的交互项, W k W_k Wk 为原始第 k k k 列权重, W ^ k \hat{W}_k W^k 是该列量化后的权重, ( W k − W ^ k ) (W_k - \hat{W}_k) (Wk−W^k) 为当前列的量化误差。
📌 4. Cholesky 分解:稳定求逆
由于需要求解 Hessian 子矩阵的逆(或近似逆):
H − 1 H^{-1} H−1
GPTQ 使用 Cholesky 分解:
H = L L T H = LL^T H=LLT
从而求解:
H − 1 = ( L − 1 ) T L − 1 H^{-1} = (L^{-1})^T L^{-1} H−1=(L−1)TL−1
这种方法在数值上更加稳定,特别适合处理大型矩阵,避免直接求逆引发的数值不稳定问题。
📌 5. 量化搜索策略
对于每一列权重 W j W_j Wj,GPTQ 会在一个候选值集合 QuantSet 中寻找能最小化泰勒展开损失的最优值:
W ^ j = arg min w ∈ QuantSet ( w − W j ) T H j ( w − W j ) \hat{W}_j = \arg\min_{w \in \text{QuantSet}} (w - W_j)^T H_j (w - W_j) W^j=argw∈QuantSetmin(w−Wj)THj(w−Wj)
其中 W ^ j \hat{W}_j W^j 是第 j j j 列量化后的权重, W j W_j Wj 是原始权重列, H j H_j Hj 是与该列相关的 Hessian 子矩阵;
QuantSet 是量化值集合,例如 INT3 或 INT4 可表达的所有值。
典型示例代码:
from auto_gptq import AutoGPTQForCausalLM, BaseQuantizeConfig
quantize_config = BaseQuantizeConfig(bits=4,group_size=128,desc_act=False,
)
model = AutoGPTQForCausalLM.from_pretrained("facebook/opt-6.7b",quantize_config=quantize_config
)
适用场景: 大模型的离线量化部署,对精度要求极高的场合。
8.2.4. HQQ:无需校准数据的零数据高效量化方法
HQQ(Half-Quadratic Quantization) 是一种新颖的半二次优化方法,强调权重量化误差最小化,不关注激活误差,从而规避校准数据带来的偏差。
数据校准的方法会有以下问题
-
校准数据偏差:根据提供的校准数据,量化质量可能会受到负面影响。
-
量化时间:校准可能是一个繁重的计算过程,尤其是对于非常大的模型
HQQ方法特别关注最小化权重误差而不是层激活。通过结合稀疏性促进损失通过超拉普拉斯分布有效地对异常值进行建模。HQQ量化的问题定义在如何在零点量化中取得最优的z和s(零点和缩放倍数)该方法和输入无关,因此不需要量化集。
8.2.5 总结
- BnB 量化:通过设置阈值区分离群点和非离群点,离群点保持高精度,非离群点进行 8 位量化。4 位量化时使用 nf4 格式,数值分布为正态分布,更好地适应 LLM 的参数分布。
- AWQ:通过评估激活值尺度确定重要参数,并对这些参数按组进行缩放,减少重要参数的量化损失,提高模型精度,同样需要量化集辅助量化。
- GPTQ:使用泰勒级数分解和海森矩阵评估参数重要性,通过并行计算减少显存占用和提高处理速度,但需要量化集辅助量化。
- HQQ:通过对零点量化的公式进行转换,将其分解为两个子问题分别求解,找到最优的零点 z,对输入数据无特殊要求,不需要量化集辅助量化。
📊 表格对比五种主流量化方法
方法 | 是否需校准数据 | 精度表现 | 速度 | 应用场景 |
---|---|---|---|---|
BnB | ❌ 无需 | 中 | 快 | 动态量化、QLoRA |
AWQ | ✅ 需要 | 高 | 中 | 精度优先场景 |
GPTQ | ✅ 需要 | 非常高 | 中 | 大模型离线部署 |
HQQ | ❌ 无需 | 高 | 非常快 | 数据缺失场景 |
QLoRA(结合BnB) | ❌ 无需 | 中等 | 快 | 微调场景 |
8.3 LLM量化
Swift 支持通过 AWQ、GPTQ、BNB、HQQ、EETQ 等技术对模型进行量化。这些量化方法各有特点,选择合适的量化方法可以优化模型的性能和推理速度。具体来说:
- AWQ 和 GPTQ 量化方法需要使用校准数据集,量化性能较好,但量化过程较慢,且支持 vLLM 推理加速。
- BNB、HQQ 和 EETQ 量化方法不需要校准数据,量化速度较快,适用于快速部署。
这五种量化方法都支持通过 QLoRA 微调来进一步优化模型。
- AWQ 和 GPTQ 需要使用
swift export
命令进行量化 - BNB、HQQ 和 EETQ 则可以在
sft
和infer
阶段进行快速量化。
提示:如果在进行 AWQ 或 GPTQ 量化时遇到报错,建议尝试安装
vllm
(具体内容请参考案例九)。
-
根据选择的量化方法,安装相应的依赖库:
# 使用awq量化: pip install autoawq -U# 使用gptq量化: pip install auto_gptq optimum -U# 使用bnb量化: pip install bitsandbytes -U# 使用hqq量化: pip install hqq
-
下载量化训练数据集
进入
LLM/data
目录,并创建quantization
文件夹以存放量化数据集。# 进入 LLM/data 目录 cd ~/LLM/data# 创建quantization目录 mkdir quantization# 下载数据集alpaca_zh git clone https://www.modelscope.cn/datasets/llamafactory/alpaca_zh.git
-
使用
AWQ
量化对于
AWQ
量化,我们使用transformers
库来进行量化。以下是相关步骤:# 进入LLM目录 cd ~/LLM# 创建autoAWQ.py量化处理程序 vim src/autoAWQ.py# 运行程序 CUDA_VISIBLE_DEVICES=0 python src/autoAWQ.py
autoAWQ.py
文件的具体内容如下:import json from awq import AutoAWQForCausalLM from transformers import AutoTokenizer from datasets import load_datasetdef qwen_preprocess(lora_data_, tokenizer_, max_len_):messages = []for item in lora_data_:temp = [{"role": "system", "content": item['instruction']},{"role": "user", "content": item['input']},{"role": "assistant", "content": item['output']}]messages.append(temp)data = []for msg in messages:text = tokenizer_.apply_chat_template(msg, tokenize=False, add_generation_prompt=False)data.append(text)return data # 定义原始模型路径,这里注意需要修改为自己的模型路径 model_path = 'model/Qwen2.5-1.5B-Instruct' # model_path = 'output/sft_full/qwen2_5-1_5b-instruct/v3-20241101-225043/checkpoint-13930' # 量化后模型的输出路径 quant_path = 'output/model/Qwen2.5-1.5B-Instruct-awq-int4-2' # quant_path = 'output/sft_full/qwen2_5-1_5b-instruct/v3-20241101-225043/checkpoint-13930-awq-int4-2' print(quant_path) # 量化的配置 quant_config = { "zero_point": True, "q_group_size": 128, "w_bit": 4, "version": "GEMM" }# 加载模型 model = AutoAWQForCausalLM.from_pretrained(model_path, **{"low_cpu_mem_usage": True, "use_cache": False} ) # 加载分词器 tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=True) # 加载量化数据集 quantize_dataset_path = 'data/quantization/alpaca_zh/alpaca_data_zh_51k.json' with open(quantize_dataset_path, 'r', encoding='utf-8') as f:lora_data = json.load(f) max_len = 1024 data = qwen_preprocess(lora_data, tokenizer, max_len)# 对模型进行量化 model.quantize(tokenizer, quant_config=quant_config, calib_data=data)# 保存量化后的模型 model.save_quantized(quant_path) tokenizer.save_pretrained(quant_path)print(f'Model is quantized and saved at "{quant_path}"')
如果量化过程顺利完成,将显示如下信息:
Model is quantized and saved at "output/qwen2_5-1_5b-instruct-awq-int4"
接下来,使用swift对量化模型进行部署并测试性能,部署命令如下:
CUDA_VISIBLE_DEVICES=2 swift deploy --model_type qwen2_5-1_5b-instruct --model_id_or_path output/Qwen2.5-1.5B-Instruct-awq-int4
示例输出(未量化和量化后的对比):
没有经过量化版本: 问:我肚子不是很舒服怎么办? 答:如果您感到不适,可以尝试以下方法:\n\n1. 休息:找一个安静的地方躺下或坐下,放松身体。\n\n2. 喝水:喝一些温水可以帮助缓解胃部不适。\n\n3. 饮食调整:避免食用油腻、辛辣、刺激性食物,多吃易消化的食物如米粥、面条等。\n\n4. 按摩:轻轻按摩腹部有助于促进肠胃蠕动,缓解腹胀和疼痛。\n\n5. 药物治疗:如果症状严重 ,可以考虑服用一些药物,但最好先咨询医生的意见。\n\n如果您的症状持续时间较长或者伴随其他症状(如呕吐、腹泻等),建议及时就医。量化后: 问:我肚子不是很舒服怎么办? 答:如果您感到肚子不舒服,可以尝试以下方法:\n\n1. 休息:找一个安静的地方躺下或坐下,放松身体。\n\n2. 喝水:喝一些温水可以帮助缓解胃部不适。\n\n3. 饮食调整:避免食用油腻、辛辣、刺激性食物和饮料。可以选择清淡易消化的食物,如米粥、面条等。\n\n4. 药物治疗:如果症状严重,可以考虑服用一些药物,如抗酸药、止泻药等。\n\n5. 就医:如果症状持续时间较长或者伴随其他症状(如呕吐、腹泻、发热等),建议及时就医。\n\n请注意,以上方法仅供参考,具体应根据个人情况选择适合自己的方法。如果症状加重或出现其他异常,请尽快就医。
接下来,我们可以使用
swift
命令进行量化部署。# AWQ 基座模型量化 CUDA_VISIBLE_DEVICES=0 swift export \--quant_bits 4 \--model_type qwen2_5-1_5b-instruct \--model_id_or_path ./model/Qwen2.5-1.5B-Instruct/ \--dataset data/quantization/alpaca_en/alpaca_data_en_52k.json data/quantization/alpaca_zh/alpaca_data_zh_51k.json \--quant_method awq# AWQ 微调模型量化 CUDA_VISIBLE_DEVICES=0 swift export \--quant_bits 4 \--dataset data/quantization/alpaca_en/alpaca_data_en_52k.json data/quantization/alpaca_zh/alpaca_data_zh_51k.json \--quant_method awq \--ckpt_dir ./output/sft_full/qwen2_5-1_5b-instruct/v3-20241101-225043/checkpoint-13930 \--merge_lora true # 如果是LoRA微调模型,需要添加此参数# 部署脚本 # AWQ 基座模型量化部署 CUDA_VISIBLE_DEVICES=0 swift deploy --model_type qwen2_5-1_5b-instruct --model_id_or_path qwen2_5-1_5b-instruct-awq-int4# AWQ 微调模型量化部署 CUDA_VISIBLE_DEVICES=0 swift deploy --model_type qwen2_5-1_5b-instruct --ckpt_dir output/sft_full/qwen2_5-1_5b-instruct/v3-20241101-225043/checkpoint-13930-awq-int4
-
使用
GPTQ
量化对于
GPTQ
量化,我们同样使用swift export
命令进行量化。以下是相关命令:# GPTQ 基座模型量化 CUDA_VISIBLE_DEVICES=0 swift export \--model_type qwen2_5-1_5b-instruct \--model_id_or_path ./model/Qwen2.5-1.5B-Instruct/ \--quant_bits 4 \--dataset data/quantization/alpaca_en/alpaca_data_en_52k.json data/quantization/alpaca_zh/alpaca_data_zh_51k.json \--quant_method gptq# GPTQ 微调模型量化 CUDA_VISIBLE_DEVICES=0 swift export \--quant_bits 4 \--dataset data/quantization/alpaca_en/alpaca_data_en_52k.json data/quantization/alpaca_zh/alpaca_data_zh_51k.json \--quant_method gptq \--ckpt_dir ./output/sft_full/qwen2_5-1_5b-instruct/v3-20241101-225043/checkpoint-13930
量化后出现下述结果即量化成功:
[INFO:swift] Saving quantized weights... [INFO:swift] Successfully quantized the model and saved in /home/wangcong/LLM/qwen2_5-1_5b-instruct-gptq-int4. [INFO:swift] End time of running main: 2024-11-23 16:09:35.720813
部署查看效果:
# GPTQ 基座模型量化部署 CUDA_VISIBLE_DEVICES=0 swift deploy --model_type qwen2_5-1_5b-instruct --model_id_or_path qwen2_5-1_5b-instruct-gptq-int4 # GPTQ 微调模型量化部署 CUDA_VISIBLE_DEVICES=0 swift deploy --model_type qwen2_5-1_5b-instruct --ckpt_dir output/sft_full/qwen2_5-1_5b-instruct/v3-20241101-225043/checkpoint-13930-gptq-int4
结果展示:
没有经过量化版本: 问:我肚子不是很舒服怎么办? 答:如果您感到不适,可以尝试以下方法:\n\n1. 休息:找一个安静的地方躺下或坐下,放松身体。\n\n2. 喝水:喝一些温水可以帮助缓解胃部不适。\n\n3. 饮食调整:避免食用油腻、辛辣、刺激性食物,多吃易消化的食物如米粥、面条等。\n\n4. 按摩:轻轻按摩腹部有助于促进肠胃蠕动,缓解腹胀和疼痛。\n\n5. 药物治疗:如果症状严重 ,可以考虑服用一些药物,但最好先咨询医生的意见。\n\n如果您的症状持续时间较长或者伴随其他症状(如呕吐、腹泻等),建议及时就医。量化后: 问:我肚子不是很舒服怎么办? 答:如果你感到肚子不舒服,可以尝试以下方 法缓解症状:\n\n1. 休息:找一个安静的地方坐下或躺下,尽量放松身体和心情。\n\n2. 喝水:喝一些温开水可以帮助舒缓胃部不适。\n\n3. 避免刺激性食物:避免食用辛辣、油腻等容易引起肠胃不适的食物。\n\n4. 舒适的姿势:保持舒适的坐姿或躺卧姿势,避免弯腰驼背。\n\n5. 温暖的饮料: 喝些温暖的牛奶或者姜茶有助于缓解胃部不适。\n\n6. 观察症状:如果症状持续不减或者加重,请及时就医。如果出现严重的腹痛、呕吐、腹泻等症状,应立即寻求医疗帮助。\n\n请注意,以上建议不能替代专业医生的诊断和治疗。如果情况严重或持续恶化,请尽快联系医疗机构进行专业的检查和治 疗。
-
使用
BNB
量化对于
BNB
,我们需要使用swift infer
或swift deploy
来进行快速量化并推理。对于基座模型使用
swift infer
:# bnb 基座模型量化 CUDA_VISIBLE_DEVICES=0 swift deploy \--model_type qwen2_5-1_5b-instruct \--model_id_or_path ./model/Qwen2.5-1.5B-Instruct/ \--quant_method bnb \--quantization_bit 4
对于微调后的模型使用
swift deploy
:# bnb 微调模型量化 CUDA_VISIBLE_DEVICES=0 swift deploy \--quant_method bnb \--quantization_bit 4 \--ckpt_dir ./output/sft_full/qwen2_5-1_5b-instruct/v3-20241101-225043/checkpoint-13930
两个模型的结果如下所示:
没有经过量化版本: 问:我肚子不是很舒服怎么办? 答:如果您感到不适,可以尝试以下方法:\n\n1. 休息:找一个安静的地方躺下或坐下,放松身体。\n\n2. 喝水:喝一些温水可以帮助缓解胃部不适。\n\n3. 饮食调整:避免食用油腻、辛辣、刺激性食物,多吃易消化的食物如米粥、面条等。\n\n4. 按摩:轻轻按摩腹部有助于促进肠胃蠕动,缓解腹胀和疼痛。\n\n5. 药物治疗:如果症状严重 ,可以考虑服用一些药物,但最好先咨询医生的意见。\n\n如果您的症状持续时间较长或者伴随其他症状(如呕吐、腹泻等),建议及时就医。量化后: 问:我肚子不是很舒服怎么办? 答:如果您感到不适,可以尝试以下方法:\n\n1. 休息:找一个安静的地方躺下或坐下,放松身体。\n\n2. 喝水:喝一些温水可以帮助缓解胃部不适。\n\n3. 饮食调整:避免食用油腻、辛辣、刺激性食物和饮料。可以选择清淡易消化的食物,如米粥、面条等。\n\n4. 药物治疗:如果症状严重,可以考虑服用一些药物,如抗酸药、止泻药等。\n\n5. 就医:如果症状持续时间较长或者加重,请及时就医。\n\n请注意,以上建议仅供参考,如有需要请咨询医生的建议。
-
使用
HQQ
量化对于
HQQ
我们同样使用swift infer
或swift deploy
来进行快速量化并推理。对于基座模型:
# hqq 基座模型量化 CUDA_VISIBLE_DEVICES=0 swift deploy \--model_type qwen2_5-1_5b-instruct \--model_id_or_path ./model/Qwen2.5-1.5B-Instruct/ \--quant_method hqq \--quantization_bit 4
对于微调后的模型:
# hqq 微调模型量化 CUDA_VISIBLE_DEVICES=0 swift deploy \--quant_method hqq \--quantization_bit 4 \--ckpt_dir ./output/sft_full/qwen2_5-1_5b-instruct/v3-20241101-225043/checkpoint-13930
结果展示:
没有经过量化版本: 问:我肚子不是很舒服怎么办? 答:如果您感到不适,可以尝试以下方法:\n\n1. 休息:找一个安静的地方躺下或坐下,放松身体。\n\n2. 喝水:喝一些温水可以帮助缓解胃部不适。\n\n3. 饮食调整:避免食用油腻、辛辣、刺激性食物,多吃易消化的食物如米粥、面条等。\n\n4. 按摩:轻轻按摩腹部有助于促进肠胃蠕动,缓解腹胀和疼痛。\n\n5. 药物治疗:如果症状严重 ,可以考虑服用一些药物,但最好先咨询医生的意见。\n\n如果您的症状持续时间较长或者伴随其他症状(如呕吐、腹泻等),建议及时就医。量化后: 问:我肚子不是很舒服怎么办? 答:如果您感到不适,可以尝试以下方法:\n\n1. 休息:找一个安静的地方躺下或坐下,放松身体。\n\n2. 喝水:喝一些温水可以帮助缓解胃部不适。\n\n3. 饮食调整:避免食用辛辣、油腻和刺激性食物,可以选择清淡易消化的食物。\n\n4. 按摩:轻轻按摩腹部有助于促进肠胃蠕动,缓解腹胀等症状。\n\n如果症状持续或加重,请及时就医。
swift export
的参数解析--to_peft_format
: 默认为False
. 将lora的swift format(--tuner_backend swift
)转成peft format.--merge_lora
: 默认为False
. 该参数已在InferArguments中定义, 不属于新增参数. 是否将lora权重merge到基模型中, 并保存完整的权重. 权重会保存在ckpt_dir
的同级目录中, e.g.'/path/to/your/vx-xxx/checkpoint-xxx-merged'
目录下.--quant_bits
: 量化的bits数. 默认为0
, 即不进行量化. 如果你设置了--quant_method awq
, 你可以设置为4
进行4bits量化. 如果你设置了--quant_method gptq
, 你可以设置为2
,3
,4
,8
进行对应bits的量化. 如果对原始模型进行量化, 权重会保存在f'{args.model_type}-{args.quant_method}-int{args.quant_bits}'
目录中. 如果对微调后模型进行量化, 权重会保存在ckpt_dir
的同级目录中, e.g.f'/path/to/your/vx-xxx/checkpoint-xxx-{args.quant_method}-int{args.quant_bits}'
目录下.--quant_method
: 量化方法, 默认为'awq'
. 你可以选择为’awq’, ‘gptq’, ‘bnb’.--dataset
: 该参数已在InferArguments中定义, 在export时含义为量化数据集. 默认为[]
.--quant_n_samples
: 量化参数, 默认为256
. 当设置为--quant_method awq
时, 如果出现量化的时候OOM, 可以适度降低--quant_n_samples
和--quant_seqlen
.--quant_method gptq
通常不会出现量化OOM.--quant_seqlen
: 量化参数, 默认为2048
.--quant_batch_size
: 量化数据集的batch_size,默认为1
.--quant_device_map
: 默认为None
. 你可以指定为’cuda:0’, ‘auto’, 'cpu’等, 表示量化时模型导入的设备.--quant_output_dir
: 默认为None
, 默认的quant_output_dir会被打印在命令行中.--push_to_hub
: 默认为False
. 是否将最后的ckpt_dir
push到ModelScope Hub中. 如果你指定了merge_lora
, 则将推送全量参数; 如果你还指定了quant_bits
, 则将推送量化后的模型.--hub_model_id
: 默认为None
. 推送到的ModelScope Hub的model_id. 如果push_to_hub
设置为True, 该参数必须被设置.--hub_token
: 默认为None
. 具体的参数介绍可以在sft命令行参数
中查看.--hub_private_repo
: 默认为False
. 具体的参数介绍可以在sft命令行参数
中查看.--commit_message
: 默认是'update files'
.--to_ollama
: 转为ollama导出.--ollama_output_dir
: ollama输出目录. 默认存储在当前目录下的模型类型-ollama
文件夹内.