🤗 Transformers 中原生支持的量化方案概述
我们的目标是清晰地概述 transformers 中支持的每种量化方案的优缺点,以帮助您决定选择哪一种。
目前,模型量化主要用于两个目的:
- 在较小的设备上运行大型模型的推理
- 在量化模型之上微调适配器
到目前为止,Transformers 中已经 **原生** 支持两种集成方案:*bitsandbytes* 和 *auto-gptq*。请注意,🤗 optimum 库 中也支持一些额外的量化方案,但这不在本博客文章的讨论范围之内。
要了解有关每种受支持方案的更多信息,请参阅下面共享的资源之一。另请参阅文档中的相应部分。
另请注意,下面共享的详细信息仅适用于 PyTorch
模型,目前不适用于 Tensorflow 和 Flax/JAX 模型。
目录
资源
- GPTQ 博客文章——概述了 GPTQ 量化方法及其使用方法。
- bitsandbytes 4 位量化博客文章——此博客文章介绍了 4 位量化和 QLoRa,一种高效的微调方法。
- bitsandbytes 8 位量化博客文章——此博客文章解释了 8 位量化如何与 bitsandbytes 配合使用。
- GPTQ 的基本用法 Google Colab 笔记本——此笔记本展示了如何使用 GPTQ 方法量化 Transformers 模型、如何进行推理以及如何使用量化模型进行微调。
- bitsandbytes 的基本用法 Google Colab 笔记本——此笔记本展示了如何使用所有变体的 4 位模型进行推理,以及如何在免费的 Google Colab 实例上运行 GPT-neo-X(一个 20B 参数模型)。
- Merve 关于量化的博客文章——此博客文章提供了量化和 Transformers 中原生支持的量化方法的简要介绍。
比较 bitsandbytes 和 auto-gptq
在本节中,我们将介绍 bitsandbytes 和 gptq 量化的优缺点。请注意,这些是基于社区反馈得出的,并且随着这些功能在各自库的路线图中不断发展,它们可能会随时间而变化。
bitsandbytes 有何优点?
简易性:bitsandbytes 仍然是量化任何模型最简单的方法,因为它不需要使用输入数据校准量化模型(也称为零样本量化)。只要模型包含 torch.nn.Linear
模块,就可以开箱即用地量化任何模型。每当新的架构添加到 Transformers 中时,只要它们可以使用 accelerate 的 device_map="auto"
加载,用户就可以直接使用 bitsandbytes 量化,并且性能损失极小。量化在模型加载时执行,无需运行任何后处理或准备步骤。
跨模态互操作性:由于量化模型的唯一条件是包含 torch.nn.Linear
层,因此量化开箱即用于任何模态,从而可以开箱即用地以 8 位或 4 位加载 Whisper、ViT、Blip2 等模型。
合并适配器时性能零下降:(如果您不熟悉适配器和 PEFT,请参阅这篇博客文章)。如果您在量化基模型之上训练适配器,则可以将适配器合并到基模型之上以进行部署,而推理性能不会下降。您还可以将适配器合并到去量化模型之上!GPTQ 不支持此功能。
autoGPTQ 有何优点?
文本生成速度快:与 bitsandbytes 量化模型相比,GPTQ 量化模型在文本生成方面速度更快。我们将在适当的部分讨论速度比较。
n 位支持:GPTQ 算法可以将模型量化到 2 位!但是,这可能会导致严重的质量下降。推荐的位数为 4 位,这似乎是目前 GPTQ 的一个很好的权衡。
易于序列化:GPTQ 模型支持任意位数的序列化。只要安装了所需的软件包,就可以开箱即用地从 TheBloke 命名空间加载模型:https://huggingface.co/TheBloke(查找以 -GPTQ
后缀结尾的模型)。bitsandbytes 支持 8 位序列化,但目前不支持 4 位序列化。
AMD 支持:该集成应该开箱即用于 AMD GPU!
bitsandbytes 有哪些潜在改进空间?
文本生成速度慢于 GPTQ:使用 generate
时,bitsandbytes 4 位模型的速度慢于 GPTQ。
4 位权重不可序列化:目前,4 位模型无法序列化。这是社区的常见请求,我们相信 bitsandbytes 维护者很快就会解决这个问题,因为它在他们的路线图中!
autoGPTQ 有哪些潜在改进空间?
校准数据集:对校准数据集的需求可能会劝退一些用户使用 GPTQ。此外,量化模型可能需要几个小时(例如,根据论文第 2 节,175B 规模的模型需要 4 个 GPU 小时)。
目前仅适用于语言模型:截至今天,用于使用 auto-GPTQ 量化模型的 API 已设计为仅支持语言模型。应该可以使用 GPTQ 算法量化非文本(或多模态)模型,但原始论文或 auto-gptq 存储库中尚未阐述该过程。如果社区对此主题感兴趣,将来可能会考虑。
深入研究速度基准
我们决定为 bitsandbytes 和 auto-gptq 在不同硬件上进行推理和微调适配器进行广泛的基准测试。推理基准测试应该让用户了解我们提出的不同推理方法之间的速度差异,而适配器微调基准测试应该让用户在决定微调 bitsandbytes 和 GPTQ 基模型时使用哪种方法时有一个清晰的概念。
我们将使用以下设置:
- bitsandbytes:4 位量化,
bnb_4bit_compute_dtype=torch.float16
。请确保使用bitsandbytes>=0.41.1
以获得更快的 4 位核。 - auto-gptq:4 位量化,使用 exllama 核。您需要
auto-gptq>=0.4.0
才能使用 ex-llama 核。
推理速度(仅前向传播)
此基准仅测量预填充步骤,这对应于训练期间的前向传播。它在单个 NVIDIA A100-SXM4-80GB GPU 上运行,提示长度为 512。我们使用的模型是 meta-llama/Llama-2-13b-hf
。
批处理大小 = 1
量化 | act_order | 位 | group_size | 内核 | 加载时间(秒) | 每令牌延迟(毫秒) | 吞吐量(令牌/秒) | 峰值内存(MB) |
---|---|---|---|---|---|---|---|---|
fp16 | 无 | 无 | 无 | 无 | 26.0 | 36.958 | 27.058 | 29152.98 |
gptq | 否 (False) | 4 | 128 | exllama | 36.2 | 33.711 | 29.663 | 10484.34 |
bitsandbytes | 无 | 4 | 无 | 无 | 37.64 | 52.00 | 19.23 | 11018.36 |
批处理大小 = 16
量化 | act_order | 位 | group_size | 内核 | 加载时间(秒) | 每令牌延迟(毫秒) | 吞吐量(令牌/秒) | 峰值内存(MB) |
---|---|---|---|---|---|---|---|---|
fp16 | 无 | 无 | 无 | 无 | 26.0 | 69.94 | 228.76 | 53986.51 |
gptq | 否 (False) | 4 | 128 | exllama | 36.2 | 95.41 | 167.68 | 34777.04 |
bitsandbytes | 无 | 4 | 无 | 无 | 37.64 | 113.98 | 140.38 | 35532.37 |
从基准测试中可以看出,bitsandbytes 和 GPTQ 是等效的,对于大批量,GPTQ 略快。有关这些基准测试的更多详细信息,请查看此链接。
生成速度
以下基准衡量模型在推理期间的生成速度。可在此处找到基准脚本,以确保重现性:这里。
use_cache
让我们测试 use_cache
以更好地了解在生成过程中缓存隐藏状态的影响。
该基准在 A100 上运行,提示长度为 30,我们生成了精确的 30 个标记。我们使用的模型是 meta-llama/Llama-2-7b-hf
。
使用 use_cache=True
使用 use_cache=False
从这两个基准中,我们得出结论,正如预期的那样,当使用注意力缓存时,生成速度更快。此外,GPTQ 通常比 bitsandbytes 快。例如,在 batch_size=4
和 use_cache=True
的情况下,它的速度是两倍!因此,让我们在接下来的基准测试中使用 use_cache
。请注意,use_cache
将消耗更多内存。
硬件
在以下基准测试中,我们将尝试不同的硬件,以了解其对量化模型的影响。我们使用的提示长度为 30,并且精确生成了 30 个令牌。我们使用的模型是 meta-llama/Llama-2-7b-hf
。
使用 NVIDIA A100
使用 NVIDIA T4
使用 Titan RTX
从上面的基准测试中,我们可以得出结论,对于这三种 GPU,GPTQ 都比 bitsandbytes 快。
生成长度
在下面的基准测试中,我们将尝试不同的生成长度,以查看它们对量化模型的影响。它在 A100 上运行,我们使用了 30 个令牌的提示长度,并改变了生成的令牌数量。我们使用的模型是 meta-llama/Llama-2-7b-hf
。
生成 30 个令牌
生成 512 个令牌
从上面的基准测试中,我们可以得出结论,无论生成长度如何,GPTQ 都比 bitsandbytes 快。
适配器微调(前向 + 后向)
无法在量化模型上进行纯训练。但是,您可以通过利用参数高效微调方法 (PEFT) 并在其上训练适配器来微调量化模型。微调方法将依赖于一种名为“低秩适配器”(LoRA) 的最新方法:您无需微调整个模型,只需微调这些适配器并将其正确加载到模型中即可。让我们比较一下微调速度!
该基准在 NVIDIA A100 GPU 上运行,我们使用了来自 Hub 的 meta-llama/Llama-2-7b-hf
模型。请注意,对于 GPTQ 模型,我们不得不禁用 exllama 核,因为 exllama 不支持微调。
从结果来看,我们得出结论,bitsandbytes 在微调方面比 GPTQ 快。
性能下降
量化对于减少内存消耗非常有用。但是,它确实会带来性能下降。让我们使用 Open-LLM 排行榜 来比较性能!
使用 7b 模型
模型 ID | 平均分 | ARC | Hellaswag | MMLU | TruthfulQA |
---|---|---|---|---|---|
meta-llama/llama-2-7b-hf | 54.32 | 53.07 | 78.59 | 46.87 | 38.76 |
meta-llama/llama-2-7b-hf-bnb-4bit | 53.4 | 53.07 | 77.74 | 43.8 | 38.98 |
TheBloke/Llama-2-7B-GPTQ | 53.23 | 52.05 | 77.59 | 43.99 | 39.32 |
使用 13b 模型
模型 ID | 平均分 | ARC | Hellaswag | MMLU | TruthfulQA |
---|---|---|---|---|---|
meta-llama/llama-2-13b-hf | 58.66 | 59.39 | 82.13 | 55.74 | 37.38 |
TheBloke/Llama-2-13B-GPTQ (修订版 = 'gptq-4bit-128g-actorder_True') | 58.03 | 59.13 | 81.48 | 54.45 | 37.07 |
TheBloke/Llama-2-13B-GPTQ | 57.56 | 57.25 | 81.66 | 54.81 | 36.56 |
meta-llama/llama-2-13b-hf-bnb-4bit | 56.9 | 58.11 | 80.97 | 54.34 | 34.17 |
从以上结果可以看出,模型越大,性能下降越小。更有趣的是,性能下降是微乎其微的!
结论和总结
在这篇博客文章中,我们比较了 bitsandbytes 和 GPTQ 量化在多种设置下的表现。我们看到 bitsandbytes 更适合微调,而 GPTQ 更适合生成。从这个观察中,获得更好的合并模型的一种方法是:
- (1) 使用 bitsandbytes 量化基础模型(零样本量化)
- (2) 添加并微调适配器
- (3) 将训练好的适配器合并到基础模型或去量化模型之上!
- (4) 使用 GPTQ 量化合并后的模型并用于部署
我们希望这份概述能让大家更轻松地在其应用程序和用例中使用大型语言模型,我们期待看到大家将用它构建什么!
致谢
我们要感谢 Ilyas、Clémentine 和 Felix 在基准测试方面提供的帮助。
最后,我们要感谢 Pedro Cuenca 在撰写此博客文章方面提供的帮助。