原文地址:https://huggingface.co/docs/transformers/main/en/main_classes/quantization
AutoGPTQ
集成 Transformers 已集成了 optimum
API 以对语言模型执行 GPTQ 量化。您可以在不大幅降低性能并提高推理速度的情况下,以 8、6、4 甚至 2 位加载并量化您的模型!大多数 GPU 硬件都支持这一功能。
要了解有关量化模型的更多信息,请查阅:
AutoGPTQ
库要运行下面的代码,您需要安装以下依赖库:
安装最新的 AutoGPTQ
库
pip install auto-gptq
从源安装最新的 optimum
pip install git+https://github.com/huggingface/optimum.git
从源安装最新的 transformers
pip install git+https://github.com/huggingface/transformers.git
安装最新的 accelerate
库
pip install --upgrade accelerate
目前,GPTQ 集成仅支持文本模型,对于视觉、语音或多模态模型,您可能会遇到意外的行为。
GPTQ 是一种量化方法,需要在使用量化模型之前进行权重校准。如果您想从头开始量化 transformers 模型,可能需要一些时间才能产生量化模型(在 Google colab 上为 facebook/opt-350m
模型大约需要 10 分钟)。
因此,您可能会遇到两种使用GPTQ-量化模型的场景。第一种情况是加载已经被其他用户量化并上传到Hub的模型;第二种情况是从零开始量化您自己的模型,并保存或上传到Hub,这样其他用户也能使用它。
为了加载并量化模型,您需要创建一个 [GPTQConfig
]。您需要传递 bits
的数量,一个 dataset
以校准量化和模型的 tokenizer
以准备数据集。
model_id = "facebook/opt-125m"
tokenizer = AutoTokenizer.from_pretrained(model_id)
gptq_config = GPTQConfig(bits=4, dataset = "c4", tokenizer=tokenizer)
请注意,您可以将自己的数据集作为字符串列表传递。但强烈建议使用 GPTQ 论文中的数据集。
dataset = ["auto-gptq 是一个基于 GPTQ 算法的易于使用的模型量化库,具有用户友好的 api。"]
quantization = GPTQConfig(bits=4, dataset = dataset, tokenizer=tokenizer)
您可以通过使用 from_pretrained
并设置 quantization_config
来量化模型。
from transformers import AutoModelForCausalLM
model = AutoModelForCausalLM.from_pretrained(model_id, quantization_config=gptq_config)
请注意,您需要一个GPU来进行模型的量化。我们会将模型放置在CPU中,并在GPU和CPU之间来回移动各个模块以进行量化。
如果您想在使用CPU offload的同时最大化您的GPU使用率,您可以设置 device_map = "auto"
。
from transformers import AutoModelForCausalLM
model = AutoModelForCausalLM.from_pretrained(model_id, device_map="auto", quantization_config=gptq_config)
请注意,不支持磁盘 offload。此外,如果由于数据集而导致内存不足,您可能需要在 from_pretained
中传递 max_memory
。查看此指南以了解有关 device_map
和 max_memory
的更多信息。
您可以使用 push_to_hub
将量化模型推送到 Hub,就像任何 模型一样。量化配置将与模型一起保存并推送。
quantized_model.push_to_hub("opt-125m-gptq")
tokenizer.push_to_hub("opt-125m-gptq")
如果您想将您的量化模型保存到本地计算机,您也可以使用 save_pretrained
:
quantized_model.save_pretrained("opt-125m-gptq")
tokenizer.save_pretrained("opt-125m-gptq")
如果您已使用device_map
量化了您的模型,在保存之前,请确保将整个模型移动到您的GPU之一或cpu
上。
quantized_model.to("cpu")
quantized_model.save_pretrained("opt-125m-gptq")
您可以使用from_pretrained
从Hub加载量化模型。
确保已推送的权重已量化,通过检查模型配置对象中是否存在quantization_config
属性。
from transformers import AutoModelForCausalLM
model = AutoModelForCausalLM.from_pretrained("{your_username}/opt-125m-gptq")
如果您希望更快地加载模型并且不分配比所需更多的内存,device_map
参数也适用于量化模型。确保您已安装accelerate
库。
from transformers import AutoModelForCausalLM
model = AutoModelForCausalLM.from_pretrained("{your_username}/opt-125m-gptq", device_map="auto")
对于4位模型,您可以使用exllama核心以获得更快的推理速度。它默认是激活的。您可以通过在[GPTQConfig
]中传递disable_exllama
来改变这种行为。这将覆盖存储在配置中的量化配置。请注意,您只能覆盖与核心相关的属性。此外,如果您想使用exllama核心,您需要将整个模型放在gpu上。
import torch
gptq_config = GPTQConfig(bits=4, disable_exllama=False)
model = AutoModelForCausalLM.from_pretrained("{your_username}/opt-125m-gptq", device_map="auto", quantization_config = gptq_config)
请注意,现在只支持4位模型。此外,如果您正在使用peft微调量化模型,建议禁用exllama核心。
借助Hugging Face生态系统中对适配器的官方支持,您可以微调已使用GPTQ量化的模型。
请查看peft
库以获取更多详细信息。
查看Google Colab 笔记本 以学习如何使用GPTQ量化您的模型以及如何使用peft微调量化模型。
[[autodoc]] GPTQConfig
bitsandbytes
集成 Transformers与bitsandbytes
上最常用的模块紧密集成。您只需几行代码即可以8位精度加载模型。
自0.37.0
版本发布以来,大多数GPU硬件都支持此功能。
在LLM.int8() 论文或关于合作的博客文章中了解更多关于量化方法的信息。
自其0.39.0
版本发布以来,您可以使用4位量化加载任何支持device_map
的模型,利用FP4数据类型。
如果您想量化自己的pytorch模型,请查看来自 Accelerate库的文档。
以下是您可以使用bitsandbytes
集成完成的操作:
只要您的模型支持使用 Accelerate加载并包含torch.nn.Linear
层,您就可以在调用[~PreTrainedModel.from_pretrained
]方法时使用load_in_8bit
或load_in_4bit
参数来量化模型。这应适用于任何模式。
from transformers import AutoModelForCausalLM
model_8bit = AutoModelForCausalLM.from_pretrained("facebook/opt-350m", load_in_8bit=True)
model_4bit = AutoModelForCausalLM.from_pretrained("facebook/opt-350m", load_in_4bit=True)
默认情况下,所有其他模块(例如torch.nn.LayerNorm
)将转换为torch.float16
,但如果您想更改其dtype
,则可以覆盖torch_dtype
参数:
>>> import torch
>>> from transformers import AutoModelForCausalLM
>>> model_8bit = AutoModelForCausalLM.from_pretrained("facebook/opt-350m", load_in_8bit=True, torch_dtype=torch.float32)
>>> model_8bit.model.decoder.layers[-1].final_layer_norm.weight.dtype
torch.float32
在运行以下任何代码片段之前,请确保已经安装了以下要求。
最新的 bitsandbytes
库
pip install bitsandbytes>=0.39.0
安装最新的 accelerate
pip install --upgrade accelerate
安装最新的 transformers
pip install --upgrade transformers
高级使用: 参考这个Google Colab笔记本以了解4位量化的高级用法以及所有可能的选项。
batch_size=1
的更快推理: 从bitsandbytes的0.40.0
版本开始,对于batch_size=1
,你可以受益于快速推理。查看这些发布说明,确保版本大于0.40.0
,以便开箱即用地使用此功能。
训练: 根据QLoRA论文,对于训练4位基础模型(例如使用LoRA适配器),应使用bnb_4bit_quant_type='nf4'
。
推理: 对于推理,bnb_4bit_quant_type
对性能影响不大。但为了与模型权重的一致性,请确保使用相同的bnb_4bit_compute_dtype
和torch_dtype
参数。
使用load_in_4bit=True
调用 .from_pretrained
方法时,您可以将内存使用量减少4倍(大致)。
# pip install transformers accelerate bitsandbytes
from transformers import AutoModelForCausalLM, AutoTokenizer
model_id = "bigscience/bloom-1b7"
tokenizer = AutoTokenizer.from_pretrained(model_id)
model = AutoModelForCausalLM.from_pretrained(model_id, device_map="auto", load_in_4bit=True)
请注意,一旦以4位加载了模型,目前无法将量化权重推送到Hub。还要注意,目前还不支持训练4位权重。但是您可以使用4位模型来训练额外的参数,这将在下一节中介绍。
您可以通过使用load_in_8bit=True
参数调用 .from_pretrained
方法大致将内存需求减半。
# pip install transformers accelerate bitsandbytes
from transformers import AutoModelForCausalLM, AutoTokenizer
model_id = "bigscience/bloom-1b7"
tokenizer = AutoTokenizer.from_pretrained(model_id)
model = AutoModelForCausalLM.from_pretrained(model_id, device_map="auto", load_in_8bit=True)
然后,像通常使用[PreTrainedModel
]一样使用你的模型。
你可以使用get_memory_footprint
方法检查你的模型的内存占用。
print(model.get_memory_footprint())
通过这种集成,我们能够在较小的设备上加载大型模型并毫无问题地运行它们。
请注意,一旦模型已经以8位加载,目前无法将量化权重推送到Hub,除非您使用最新的transformers
和bitsandbytes
。还要注意,目前还不支持训练8位权重。但是您可以使用8位模型来训练额外的参数,这将在下一节中介绍。
还要注意,device_map
是可选的,但是设置device_map = 'auto'
是推荐的,因为它会高效地将模型分派到可用的资源上。
在这里,我们将介绍您可以使用FP4量化执行的一些高级用例。
计算数据类型用于改变计算期间使用的数据类型。例如,隐藏状态可以是float32
,但计算可以设置为bf16以加速。默认情况下,计算数据类型设置为float32
。
import torch
from transformers import BitsAndBytesConfig
quantization_config = BitsAndBytesConfig(load_in_4bit=True, bnb_4bit_compute_dtype=torch.bfloat16)
你还可以使用NF4数据类型,这是一种新的4位数据类型,适用于使用正态分布初始化的权重。为此运行:
from transformers import BitsAndBytesConfig
nf4_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4",
)
model_nf4 = AutoModelForCausalLM.from_pretrained(model_id, quantization_config=nf4_config)
我们还建议用户使用嵌套量化技术。这可以节省更多的内存,而不需要额外的性能 - 根据我们的经验观察,这使得在NVIDIA-T4 16GB上以序列长度为1024、批量大小为1和梯度积累步骤为4进行微调llama-13b模型成为可能。
from transformers import BitsAndBytesConfig
double_quant_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_use_double_quant=True,
)
model_double_quant = AutoModelForCausalLM.from_pretrained(model_id, quantization_config=double_quant_config)
您可以通过简单地使用 push_to_hub
方法将一个量化模型推送到 Hub。这将首先推送量化配置文件,然后推送量化的模型权重。确保使用 bitsandbytes>0.37.2
(在撰写本文时,我们在 bitsandbytes==0.38.0.post1
上测试过)来使用此功能。
from transformers import AutoModelForCausalLM, AutoTokenizer
model = AutoModelForCausalLM.from_pretrained("bigscience/bloom-560m", device_map="auto", load_in_8bit=True)
tokenizer = AutoTokenizer.from_pretrained("bigscience/bloom-560m")
model.push_to_hub("bloom-560m-8bit")
强烈建议将8位模型推送到 Hub,尤其是大型模型。这将允许社区从内存占用减少中受益,并例如在 Google Colab 上加载大型模型。
您可以使用 from_pretrained
方法从 Hub 加载一个量化模型。确保推送的权重是量化的,通过检查模型配置对象中是否存在 quantization_config
属性。
from transformers import AutoModelForCausalLM, AutoTokenizer
model = AutoModelForCausalLM.from_pretrained("{your_username}/bloom-560m-8bit", device_map="auto")
注意,在这种情况下,您不需要指定 load_in_8bit=True
参数,但您需要确保已安装 bitsandbytes
和 accelerate
。同样注意,device_map
是可选的,但设置 device_map = 'auto'
在推理时是首选,因为它会有效地将模型分派到可用的资源上。
本节面向希望探索除了加载和运行8位模型之外还可以做什么的高级用户。
cpu
和 gpu
之间进行卸载这其中的一个高级用例是能够加载一个模型并在 CPU
和 GPU
之间分派权重。请注意,将在 CPU 上分派的权重不会被转换为8位,因此保持为 float32
。此功能面向希望适应非常大的模型并在 GPU 和 CPU 之间分派模型的用户。
首先,从 transformers
加载一个 [BitsAndBytesConfig
],并将属性 llm_int8_enable_fp32_cpu_offload
设置为 True
:
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
quantization_config = BitsAndBytesConfig(llm_int8_enable_fp32_cpu_offload=True)
假设您想加载 bigscience/bloom-1b7
模型,而您的 GPU RAM 只足够适应整个模型,除了 lm_head
。因此,如下所示编写一个自定义的 device_map:
device_map = {
"transformer.word_embeddings": 0,
"transformer.word_embeddings_layernorm": 0,
"lm_head": "cpu",
"transformer.h": 0,
"transformer.ln_f": 0,
}
然后如下加载您的模型:
model_8bit = AutoModelForCausalLM.from_pretrained(
"bigscience/bloom-1b7",
device_map=device_map,
quantization_config=quantization_config,
)
就是这样!尽情享受您的模型吧!
llm_int8_threshold
进行玩耍您可以使用 llm_int8_threshold
参数更改离群值的阈值。"离群值"是一个隐藏状态值,大于某个阈值。这对应于 LLM.int8()
论文中描述的离群值检测的离群值阈值。任何超过此阈值的隐藏状态值都将被视为离群值,这些值上的操作将以 fp16 进行。值通常呈正态分布,即大多数值在范围 [-3.5, 3.5] 内,但对于大型模型,有一些特殊的系统性离群值分布非常不同。这些离群值通常在区间 [-60, -6] 或 [6, 60] 内。Int8 量化对于大约为5的值工作得很好,但超过此值,性能将受到重大影响。一个好的默认阈值是6,但更不稳定的模型(小模型,微调)可能需要较低的阈值。这个参数可能会影响模型的推理速度。我们建议您玩弄这个参数,找
到最适合您用例的值。
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
model_id = "bigscience/bloom-1b7"
quantization_config = BitsAndBytesConfig(
llm_int8_threshold=10,
)
model_8bit = AutoModelForCausalLM.from_pretrained(
model_id,
device_map=device_map,
quantization_config=quantization_config,
)
tokenizer = AutoTokenizer.from_pretrained(model_id)
有些模型有几个模块需要不转换为8位以确保稳定性。例如 Jukebox 模型有几个 lm_head
模块应该被跳过。使用 llm_int8_skip_modules
进行玩耍:
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
model_id = "bigscience/bloom-1b7"
quantization_config = BitsAndBytesConfig(
llm_int8_skip_modules=["lm_head"],
)
model_8bit = AutoModelForCausalLM.from_pretrained(
model_id,
device_map=device_map,
quantization_config=quantization_config,
)
tokenizer = AutoTokenizer.from_pretrained(model_id)
凭借 Hugging Face 生态系统对适配器的官方支持,您可以微调已加载为8位的模型。这使得在单个 Google Colab 中微调大型模型,如 flan-t5-large
或 facebook/opt-6.7b
成为可能。请查看 peft
库以获取更多详细信息。
注意,加载模型进行训练时,您不需要传递 device_map
。它将自动在您的 GPU 上加载您的模型。如有需要,您还可以将 device map 设置为特定的设备(例如 cuda:0
、0
、torch.device('cuda:0')
)。请注意,device_map=auto
仅用于推理。
[[autodoc]] BitsAndBytesConfig
optimum
进行量化请查看 Optimum 文档 以了解 optimum
支持的量化方法,并查看这些是否适用于您的用例。