Hugging Face 在 Transformers 中集成 AutoGPTQ,支持 8/4/3/2-bit 量化
Making LLMs lighter with AutoGPTQ and transformers
Hugging Face 将 AutoGPTQ 库集成进 Transformers,用户可用 GPTQ 算法以 8、4、3 甚至 2-bit 精度量化并运行模型,同时支持 Nvidia GPU 和 RoCm 架构的 AMD GPU。
官方集成说明给出了 4-bit 量化的内存收益、推理延迟对比和 TGI 部署示例,读者可据此评估是否迁移现有部署方案。
大型语言模型在理解和生成类人文本方面展现出了非凡的能力,彻底改变了各个领域的应用。然而,它们对消费级硬件在训练和部署上的需求变得越来越难以满足。
🤗 Hugging Face 的核心使命是使优秀的机器学习普及化,这包括让大型模型尽可能地对所有人可访问。本着与我们的 bitsandbytes 合作相同的精神,我们刚刚在 Transformers 中集成了 AutoGPTQ 库,使用户能够使用 GPTQ 算法(Frantar 等人,2023)以 8、4、3 甚至 2 位精度量化和运行模型。4 位量化的精度下降可以忽略不计,对于小批量大小,推理速度可与 fp16 基线相媲美。请注意,GPTQ 方法与 bitsandbytes 提出的训练后量化方法略有不同,因为它需要传递校准数据集。
此集成既适用于 Nvidia GPU,也适用于搭载 RoCm 的 AMD GPU。
目录
- 资源
- GPTQ 论文简要概述
- AutoGPTQ 库——为 LLM 高效利用 GPTQ 的一站式库
- 🤗 Transformers 中对 GPTQ 模型的原生支持
- 使用 Optimum 库量化模型
- 通过 Text-Generation-Inference 运行 GPTQ 模型
- 使用 PEFT 微调量化模型
- Room for improvement
- 结论与结语
- 致谢
资源
本博客文章和发布附带了多个资源,帮助您开始使用 GPTQ 量化:
- 原始论文
- 基本用法 Google Colab 笔记本 - 此笔记本展示了如何使用 GPTQ 方法量化您的 transformers 模型,如何进行推理,以及如何对量化模型进行微调。
- Transformers 集成文档
- Optimum 集成文档
- The Bloke 的仓库,包含兼容的 GPTQ 模型。
GPTQ 论文简要概述
量化方法通常属于以下两类之一:
- 训练后量化(PTQ):我们使用适度的资源(如校准数据集和几小时的计算)对预训练模型进行量化。
- 量化感知训练(QAT):量化在训练或进一步微调之前进行。
GPTQ 属于 PTQ 类别,这对于大型模型尤其有趣,因为完整模型训练甚至微调可能非常昂贵。
具体来说,GPTQ 采用混合 int4/fp16 量化方案,其中权重被量化为 int4,而激活值保持为 float16。在推理过程中,权重被即时反量化,实际计算以 float16 进行。
这种方案的好处是双重的:
- int4 量化可节省近 4 倍的内存,因为反量化在融合内核中靠近计算单元进行,而不是在 GPU 全局内存中。
- 由于权重使用较低的位宽,节省了数据通信时间,因此可能带来速度提升。
GPTQ 论文解决了逐层压缩问题:
给定一个层 ll,其权重矩阵为 WlW_{l},层输入为 XlX_{l},我们希望找到权重的量化版本 W^l\hat{W}_{l},以最小化均方误差(MSE):
W^l∗=argminWl^∥WlX−W^lX∥22{\hat{W}_{l}}^{*} = argmin_{\hat{W_{l}}} \|W_{l}X-\hat{W}_{l}X\|^{2}_{2}
一旦逐层解决此问题,通过组合各层的解即可获得全局问题的解。
为了解决这个逐层压缩问题,作者使用了最优脑量化框架(Frantar et al 2022)。OBQ 方法始于这样一个观察:上述方程可以写成 WlW_{l} 每一行的平方误差之和。
∑i=0drow∥Wl[i,:]X−W^l[i,:]X∥22 \sum_{i=0}^{d_{row}} \|W_{l[i,:]}X-\hat{W}_{l[i,:]}X\|^{2}_{2}
这意味着我们可以独立地量化每一行。这称为逐通道量化。对于每一行 Wl[i,:]W_{l[i,:]},OBQ 一次量化一个权重,同时始终更新所有尚未量化的权重,以补偿量化单个权重所产生的误差。对选定权重的更新具有闭式公式,利用了 Hessian 矩阵。
GPTQ 论文通过引入一系列优化改进了该框架,在保持模型精度的同时降低了量化算法的复杂度。
与 OBQ 相比,GPTQ 的量化步骤本身也更快:使用 OBQ 量化一个 BERT 模型(336M)需要 2 个 GPU 小时,而使用 GPTQ,一个 Bloom 模型(176B)可以在不到 4 个 GPU 小时内完成量化。
要了解确切的算法以及关于困惑度和加速的不同基准测试,请查看原始论文。
AutoGPTQ 库——为 LLM 高效利用 GPTQ 的一站式库
AutoGPTQ 库使用户能够使用 GPTQ 方法量化 🤗 Transformers 模型。虽然诸如 GPTQ-for-LLaMa、Exllama 和 llama.cpp 等社区并行工作严格针对 Llama 架构实现量化方法,但 AutoGPTQ 因其对广泛 transformer 架构的平滑覆盖而广受欢迎。
由于 AutoGPTQ 库覆盖了更多的 transformers 模型,我们决定提供一个集成的 🤗 Transformers API,使每个人都能更容易地进行 LLM 量化。目前,我们已经集成了最常见的优化选项,例如 CUDA 内核。对于 Triton 内核或融合注意力兼容性等更高级的选项,请查看 AutoGPTQ 库。
🤗 Transformers 中对 GPTQ 模型的原生支持
在安装 AutoGPTQ 库和 optimum(pip install optimum)之后,在 Transformers 中运行 GPTQ 模型现在就像这样简单:
from transformers import AutoModelForCausalLM
model = AutoModelForCausalLM.from_pretrained("TheBloke/Llama-2-7b-Chat-GPTQ", torch_dtype=torch.float16, device_map="auto")
查看 Transformers 文档以了解有关所有功能的更多信息。
我们的 AutoGPTQ 集成具有许多优势:
- 量化模型可序列化,并可在 Hub 上共享。
- GPTQ 大幅降低了运行 LLM 的内存需求,而推理延迟与 FP16 推理相当。
- AutoGPTQ 支持适用于广泛架构的 Exllama 内核。
- 该集成原生支持 AMD GPU 的 RoCm。
- 可使用PEFT 进行微调。
你可以在 Hub 上查看你喜欢的模型是否已经被量化。TheBloke 是 Hugging Face 顶级贡献者之一,他用 AutoGPTQ 量化了大量模型并分享在 Hugging Face Hub 上。我们合作确保这些仓库能够与我们的集成开箱即用。
这是 batch size = 1 情况下的基准测试样本。基准测试在单张 NVIDIA A100-SXM4-80GB GPU 上运行。我们使用 512 的 prompt 长度,并精确生成 512 个新 token。第一行是未量化的 fp16 基线,其他行则展示了使用不同 AutoGPTQ kernel 时的内存消耗和性能。
| gptq | act_order | bits | group_size | kernel | 加载时间(秒) | 每 token 延迟(毫秒) | 吞吐量(tokens/s) | 峰值内存(MB) |
|---|---|---|---|---|---|---|---|---|
| False | None | None | None | None | 26.0 | 36.958 | 27.058 | 29152.98 |
| True | False | 4 | 128 | exllama | 36.2 | 33.711 | 29.663 | 10484.34 |
| True | False | 4 | 128 | autogptq-cuda-old | 36.2 | 46.44 | 21.53 | 10344.62 |
更全面的可复现基准测试见此处。
使用 Optimum 库量化模型
为了将 AutoGPTQ 无缝集成到 Transformers 中,我们使用了 AutoGPTQ API 的极简版本,该版本可在 Optimum 中使用,这是 Hugging Face 用于训练和推理优化的工具包。通过这种方式,我们实现了与 Transformers 的轻松集成,同时允许人们在想要量化自己的模型时使用 Optimum API!如果你想量化自己的 LLM,请查看 Optimum 文档。
使用 GPTQ 方法量化 🤗 Transformers 模型只需几行代码:
from transformers import AutoModelForCausalLM, AutoTokenizer, GPTQConfig
model_id = "facebook/opt-125m"
tokenizer = AutoTokenizer.from_pretrained(model_id)
quantization_config = GPTQConfig(bits=4, dataset = "c4", tokenizer=tokenizer)
model = AutoModelForCausalLM.from_pretrained(model_id, device_map="auto", quantization_config=quantization_config)
量化模型可能需要很长时间。请注意,对于 175B 模型,如果使用大型数据集(例如 `"c4"``),至少需要 4 个 GPU 小时。如上所述,Hugging Face Hub 上已经有许多 GPTQ 模型可用,这在大多数用例中免去了你自己量化模型的需要。不过,你也可以使用适合你正在处理的特定领域的数据集来量化模型。
通过 Text-Generation-Inference 运行 GPTQ 模型
在将 GPTQ 集成到 Transformers 的同时,GPTQ 支持也被添加到了 Text-Generation-Inference 库(TGI)中,该库旨在生产环境中服务大型语言模型。现在,GPTQ 可以与动态批处理、分页注意力和 flash attention 等功能一起用于广泛的架构。
例如,这种集成允许在单张 A100-80GB GPU 上服务 70B 模型!使用 fp16 checkpoint 无法做到这一点,因为它超出了可用的 GPU 内存。
你可以在文档中了解有关 TGI 中 GPTQ 用法的更多信息。
请注意,TGI 中集成的 kernel 在较大 batch size 下扩展性不太好。尽管这种方法节省内存,但在较大 batch size 下预计会出现速度下降。
使用 PEFT 微调量化模型
你无法使用常规方法进一步训练量化模型。但是,通过利用 PEFT 库,你可以在其上训练 adapter!为此,我们冻结量化模型的所有层,并添加可训练的 adapter。以下是一些如何将 PEFT 与 GPTQ 模型一起使用的示例:colab notebook 和 finetuning 脚本。
改进空间
我们的 AutoGPTQ 集成已经带来了令人印象深刻的好处,而在预测质量上的代价很小。无论是在量化技术还是内核实现方面,都仍有改进的空间。
首先,尽管据我们所知,AutoGPTQ 集成了来自 exllama 实现 的性能最佳的 W4A16 内核(权重为 int4,激活为 fp16),但该内核仍有很大的改进可能。来自 Kim 等人 和 MIT Han Lab 的其他有前景的实现看起来也很有希望。此外,根据内部基准测试,似乎仍然没有用 Triton 编写的开源高性能 W4A16 内核,这可能是一个值得探索的方向。
在量化方面,让我们再次强调,这种方法仅量化权重。针对 LLM 量化,还提出了其他方法,可以在预测质量代价很小的情况下同时量化权重和激活,例如 LLM-QAT,其中可以使用混合 int4/int8 方案,以及对键值缓存的量化。这项技术的一大优势是能够使用实际的整数运算进行计算,例如 Nvidia Tensor Cores 支持 int8 计算。然而,据我们所知,目前还没有开源的 W4A8 量化内核可用,但这很可能是一个值得探索的有趣方向。
在内核方面,为更大的批量大小设计高性能的 W4A16 内核仍然是一个未解决的挑战。
支持的模型
在这个初始实现中,仅支持具有仅解码器或仅编码器架构的大型语言模型。这听起来可能有点限制,但它涵盖了大多数最先进的 LLM,例如 Llama、OPT、GPT-Neo、GPT-NeoX。
目前不支持非常大的视觉、音频和多模态模型。
结论和最后的话
在这篇博文中,我们介绍了在 Transformers 中集成 AutoGPTQ 库,使得可以使用 GPTQ 方法量化 LLM,让社区中的任何人都能更容易地使用它们,并使他们能够用 LLM 构建令人兴奋的工具和应用程序。
此集成既适用于 Nvidia GPU,也适用于搭载 RoCm 的 AMD GPU,这是朝着为更广泛的 GPU 架构普及量化模型迈出的一大步。
与 AutoGPTQ 团队的合作非常富有成果,我们非常感谢他们的支持以及他们在这个库上的工作。
我们希望这次集成能让每个人更容易地在他们的应用程序中使用 LLM,我们期待看到您将用它构建什么!
不要错过上面分享的有用资源,以便更好地理解集成以及如何快速开始使用 GPTQ 量化。
- 原始论文
- 基本用法 Google Colab 笔记本 - 此笔记本展示了如何使用 GPTQ 方法量化您的 transformers 模型、如何进行推理以及如何对量化模型进行微调。
- Transformers 集成文档
- Optimum 集成文档
- The Bloke 的仓库,包含兼容的 GPTQ 模型。
致谢
我们要感谢 William 的支持,他在出色的 AutoGPTQ 库上的工作,以及他在集成方面的帮助。 我们还要感谢 TheBloke 使用 AutoGPTQ 量化了许多模型并在 Hub 上分享,以及他在集成方面的帮助。 我们还要感谢 qwopqwop200 对 AutoGPTQ 库的持续贡献,以及他为扩展该库以支持 CPU 所做的工作,这将在 AutoGPTQ 的下一个版本中发布。
最后,我们要感谢 Pedro Cuenca 在撰写这篇博文时的帮助。
来源:Hugging Face:Blog(RSS) · huggingface.co