Transformers 4.37 中文文档(八)(3)https://developer.aliyun.com/article/1563210
bitsandbytes
bitsandbytes是将模型量化为 8 位和 4 位的最简单选择。8 位量化将 fp16 中的异常值与 int8 中的非异常值相乘,将非异常值转换回 fp16,然后将它们相加以返回 fp16 中的权重。这减少了异常值对模型性能的降级影响。4 位量化进一步压缩模型,通常与QLoRA一起用于微调量化的 LLM。
要使用 bitsandbytes,请确保已安装以下库:
8 位 4 位
pip install transformers accelerate bitsandbytes>0.37.0
现在您可以使用 from_pretrained()方法中的load_in_8bit
或load_in_4bit
参数来量化模型。只要模型支持使用 Accelerate 加载并包含torch.nn.Linear
层,这对任何模态的模型都适用。
8 位 4 位
将模型量化为 8 位可以减半内存使用量,对于大型模型,设置device_map="auto"
以有效地使用可用的 GPU:
from transformers import AutoModelForCausalLM model_8bit = AutoModelForCausalLM.from_pretrained("bigscience/bloom-1b7", device_map="auto", load_in_8bit=True)
默认情况下,所有其他模块(如torch.nn.LayerNorm
)都会转换为torch.float16
。如果需要,您可以使用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
一旦模型被量化为 8 位,除非您使用最新版本的 Transformers 和 bitsandbytes,否则无法将量化的权重推送到 Hub。如果您有最新版本,则可以使用 push_to_hub()方法将 8 位模型推送到 Hub。首先推送量化的 config.json 文件,然后是量化的模型权重。
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 位和 4 位权重进行训练额外参数。
您可以使用get_memory_footprint
方法检查内存占用情况:
print(model.get_memory_footprint())
可以从 from_pretrained()方法中加载量化模型,无需指定load_in_8bit
或load_in_4bit
参数:
from transformers import AutoModelForCausalLM, AutoTokenizer model = AutoModelForCausalLM.from_pretrained("{your_username}/bloom-560m-8bit", device_map="auto")
8 位
在这篇博客文章中了解更多关于 8 位量化的细节!
本节探讨了 8 位模型的一些特定功能,如转移、异常值阈值、跳过模块转换和微调。
转移
8 位模型可以在 CPU 和 GPU 之间转移权重,以支持将非常大的模型适配到内存中。发送到 CPU 的权重实际上是以float32存储的,并且不会转换为 8 位。例如,要为bigscience/bloom-1b7模型启用转移,请首先创建一个 BitsAndBytesConfig:
from transformers import AutoModelForCausalLM, BitsAndBytesConfig quantization_config = BitsAndBytesConfig(llm_int8_enable_fp32_cpu_offload=True)
设计一个自定义设备映射,将所有内容都适配到 GPU 上,除了lm_head
,这部分将发送到 CPU:
device_map = { "transformer.word_embeddings": 0, "transformer.word_embeddings_layernorm": 0, "lm_head": "cpu", "transformer.h": 0, "transformer.ln_f": 0, }
现在使用自定义的device_map
和quantization_config
加载您的模型:
model_8bit = AutoModelForCausalLM.from_pretrained( "bigscience/bloom-1b7", device_map=device_map, quantization_config=quantization_config, )
异常值阈值
“异常值”是大于某个阈值的隐藏状态值,这些值是在 fp16 中计算的。虽然这些值通常是正态分布的([-3.5, 3.5]),但对于大型模型([-60, 6]或[6, 60]),这种分布可能会有很大不同。8 位量化适用于值约为 5,但超过这个值,会有显著的性能损失。一个很好的默认阈值是 6,但对于更不稳定的模型(小模型或微调),可能需要更低的阈值。
为了找到您的模型的最佳阈值,我们建议尝试在 BitsAndBytesConfig 中使用llm_int8_threshold
参数进行实验:
from transformers import AutoModelForCausalLM, 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, )
跳过模块转换
对于一些模型,如 Jukebox,您不需要将每个模块量化为 8 位,这实际上可能会导致不稳定性。对于 Jukebox,有几个lm_head
模块应该使用 BitsAndBytesConfig 中的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="auto", quantization_config=quantization_config, )
微调
使用PEFT库,您可以使用 8 位量化微调大型模型,如flan-t5-large和facebook/opt-6.7b。在训练时不需要传递device_map
参数,因为它会自动将您的模型加载到 GPU 上。但是,如果您想要,仍然可以使用device_map
参数自定义设备映射(device_map="auto"
仅应用于推断)。
4 位
在这个notebook中尝试 4 位量化,并在这篇博客文章中了解更多细节。
本节探讨了 4 位模型的一些特定功能,如更改计算数据类型、使用 Normal Float 4 (NF4)数据类型和使用嵌套量化。
计算数据类型
为了加速计算,您可以将数据类型从 float32(默认值)更改为 bf16,使用 BitsAndBytesConfig 中的bnb_4bit_compute_dtype
参数:
import torch from transformers import BitsAndBytesConfig quantization_config = BitsAndBytesConfig(load_in_4bit=True, bnb_4bit_compute_dtype=torch.bfloat16)
Normal Float 4 (NF4)
NF4 是来自QLoRA论文的 4 位数据类型,适用于从正态分布初始化的权重。您应该使用 NF4 来训练 4 位基础模型。这可以通过 BitsAndBytesConfig 中的bnb_4bit_quant_type
参数进行配置:
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)
对于推断,bnb_4bit_quant_type
对性能没有太大影响。但是,为了保持与模型权重一致,您应该使用bnb_4bit_compute_dtype
和torch_dtype
值。
嵌套量化
嵌套量化是一种技术,可以在不增加性能成本的情况下节省额外的内存。此功能对已经量化的权重执行第二次量化,以节省额外的 0.4 位/参数。例如,使用嵌套量化,您可以在 16GB 的 NVIDIA T4 GPU 上微调Llama-13b模型,序列长度为 1024,批量大小为 1,并启用梯度累积 4 步。
from transformers import BitsAndBytesConfig double_quant_config = BitsAndBytesConfig( load_in_4bit=True, bnb_4bit_use_double_quant=True, ) model_double_quant = AutoModelForCausalLM.from_pretrained("meta-llama/Llama-2-13b", quantization_config=double_quant_config)
Optimum
Optimum库支持 Intel、Furiosa、ONNX Runtime、GPTQ 和较低级别的 PyTorch 量化功能。如果您正在使用像 Intel CPU、Furiosa NPU 或像 ONNX Runtime 这样的模型加速器这样的特定和优化的硬件,请考虑使用 Optimum 进行量化。
基准测试
要比较每种量化方案的速度、吞吐量和延迟,请查看从optimum-benchmark库获得的以下基准测试。该基准测试在 NVIDIA A1000 上运行,用于TheBloke/Mistral-7B-v0.1-AWQ和TheBloke/Mistral-7B-v0.1-GPTQ模型。这些还与 bitsandbytes 量化方法以及本机 fp16 模型进行了测试。
前向峰值内存/批处理大小
每批生成峰值内存/批处理大小
每批生成吞吐量/批处理大小
前向延迟/批处理大小
基准测试表明,AWQ 量化在推理、文本生成方面是最快的,并且在文本生成方面具有最低的峰值内存。然而,AWQ 在每个批处理大小上具有最大的前向延迟。要了解每种量化方法的优缺点的更详细讨论,请阅读🤗 Transformers 中本地支持的量化方案概述博客文章。
融合 AWQ 模块
TheBloke/Mistral-7B-OpenOrca-AWQ模型在batch_size=1
下进行了基准测试,有无融合模块。
未融合模块
批处理大小 | 预填充长度 | 解码长度 | 预填充标记/秒 | 解码标记/秒 | 内存(VRAM) |
1 | 32 | 32 | 60.0984 | 38.4537 | 4.50 GB (5.68%) |
1 | 64 | 64 | 1333.67 | 31.6604 | 4.50 GB (5.68%) |
1 | 128 | 128 | 2434.06 | 31.6272 | 4.50 GB (5.68%) |
1 | 256 | 256 | 3072.26 | 38.1731 | 4.50 GB (5.68%) |
1 | 512 | 512 | 3184.74 | 31.6819 | 4.59 GB (5.80%) |
1 | 1024 | 1024 | 3148.18 | 36.8031 | 4.81 GB (6.07%) |
1 | 2048 | 2048 | 2927.33 | 35.2676 | 5.73 GB (7.23%) |
融合模块
批处理大小 | 预填充长度 | 解码长度 | 预填充标记/秒 | 解码标记/秒 | 内存(VRAM) |
1 | 32 | 32 | 81.4899 | 80.2569 | 4.00 GB (5.05%) |
1 | 64 | 64 | 1756.1 | 106.26 | 4.00 GB (5.05%) |
1 | 128 | 128 | 2479.32 | 105.631 | 4.00 GB (5.06%) |
1 | 256 | 256 | 1813.6 | 85.7485 | 4.01 GB (5.06%) |
1 | 512 | 512 | 2848.9 | 97.701 | 4.11 GB (5.19%) |
1 | 1024 | 1024 | 3044.35 | 87.7323 | 4.41 GB (5.57%) |
1 | 2048 | 2048 | 2715.11 | 89.4709 | 5.57 GB (7.04%) |
融合和未融合模块的速度和吞吐量也经过了optimum-benchmark库的测试。
前向峰值内存/批处理大小
每批生成吞吐量/批处理大小
Transformers 4.37 中文文档(八)(5)https://developer.aliyun.com/article/1563212