Transformers documentation
Bitsandbytes
Bitsandbytes
Thư viện bitsandbytes cung cấp các công cụ lượng tử hóa cho LLM thông qua một lớp bọc Python nhẹ nhàng quanh các hàm của bộ tăng tốc phần cứng. Nó cho phép làm việc với các mô hình lớn bằng tài nguyên tính toán hạn chế thông qua việc giảm dung lượng bộ nhớ của chúng.
Về cốt lõi, bitsandbytes cung cấp:
- Tầng Linear đã lượng tử hóa: các tầng
Linear8bitLtvàLinear4bitthay thế các tầng linear chuẩn của PyTorch bằng các phương án lượng tử hóa tiết kiệm bộ nhớ - Trình tối ưu được tối ưu hóa: các phiên bản 8-bit của các trình tối ưu phổ biến thông qua module
optim, cho phép huấn luyện các mô hình lớn với yêu cầu bộ nhớ thấp hơn - Nhân ma trận: Các thao tác nhân ma trận được tối ưu hóa, tận dụng định dạng lượng tử hóa
bitsandbytes cung cấp hai tính năng lượng hóa chính:
LLM.int8() - Phương pháp lượng tử hóa 8-bit giúp suy luận dễ tiếp cận hơn mà không gây suy giảm hiệu suất đáng kể. Khác với lượng tử hóa đơn giản, LLM.int8() động giữ lại độ chính xác cao hơn cho các phép tính quan trọng, ngăn ngừa mất thông tin ở những phần nhạy cảm của mô hình.
QLoRA - Kỹ thuật lượng tử hóa 4-bit nén mô hình sâu hơn nữa trong khi vẫn duy trì khả năng huấn luyện bằng cách chèn một tập hợp nhỏ các trọng số thích ứng hạng thấp (LoRA) có thể huấn luyện được.
Lưu ý: Để có trải nghiệm lượng tử hóa thân thiện với người dùng, bạn có thể sử dụng không gian cộng đồng của
bitsandbytes.
Chạy lệnh bên dưới để cài đặt bitsandbytes.
pip install --upgrade transformers accelerate bitsandbytes
Để biên dịch từ mã nguồn, hãy làm theo các hướng dẫn trong hướng dẫn cài đặt bitsandbytes.
Tương thích phần cứng
bitsandbytes được hỗ trợ trên GPU NVIDIA cho các phiên bản CUDA 11.8 - 13.0, Intel XPU, Intel Gaudi (HPU) và CPU. Hiện có nỗ lực đang diễn ra để hỗ trợ thêm các nền tảng khác. Nếu bạn quan tâm đến việc cung cấp phản hồi hoặc kiểm thử, hãy xem kho bitsandbytes để biết thêm thông tin.
GPU NVIDIA (CUDA)
Backend này được hỗ trợ trên các nền tảng Linux x86-64, Linux aarch64 và Windows.
| Tính năng | Yêu cầu phần cứng tối thiểu |
|---|---|
| Trình tối ưu hóa 8-bit | GPU NVIDIA Pascal (dòng GTX 10X0, P100) hoặc mới hơn * |
| LLM.int8() | GPU NVIDIA Turing (dòng RTX 20X0, T4) hoặc mới hơn |
| Lượng tử hóa NF4/FP4 | GPU NVIDIA Pascal (dòng GTX 10X0, P100) hoặc mới hơn * |
GPU Intel (XPU)
Backend này được hỗ trợ trên các nền tảng Linux x86-64 và Windows x86-64.
Intel Gaudi (HPU)
Backend này được hỗ trợ trên Linux x86-64 cho Gaudi2 và Gaudi3.
CPU
Backend này được hỗ trợ trên các nền tảng Linux x86-64, Linux aarch64 và Windows x86-64.
Ví dụ về Lượng tử hóa
Thực hiện lượng tử hóa một mô hình bằng cách truyền BitsAndBytesConfig vào from_pretrained(). Cách này hoạt động với bất kỳ mô hình nào thuộc bất kỳ chế độ nào, miễn là mô hình đó hỗ trợ Accelerate và chứa các lớp torch.nn.Linear.
from transformers import AutoModelForCausalLM, BitsAndBytesConfig
quantization_config = BitsAndBytesConfig(load_in_8bit=True)
model_8bit = AutoModelForCausalLM.from_pretrained(
"bigscience/bloom-1b7",
device_map="auto",
quantization_config=quantization_config
)Mặc định, tất cả các module khác như torch.nn.LayerNorm được đặt thành dtype torch mặc định. Bạn có thể thay đổi kiểu dữ liệu của các module này bằng tham số dtype. Đặt dtype="auto" sẽ tải mô hình với kiểu dữ liệu được định nghĩa trong tệp config.json của mô hình.
import torch
from transformers import AutoModelForCausalLM, BitsAndBytesConfig
quantization_config = BitsAndBytesConfig(load_in_8bit=True)
model_8bit = AutoModelForCausalLM.from_pretrained(
"facebook/opt-350m",
device_map="auto",
quantization_config=quantization_config,
dtype="auto"
)
model_8bit.model.decoder.layers[-1].final_layer_norm.weight.dtypeKhi một model đã được lượng tử hóa xuống 8-bit, bạn không thể đẩy các trọng số đã lượng tử hóa lên Hub trừ khi bạn đang sử dụng phiên bản mới nhất của Transformers và bitsandbytes. Nếu bạn có các phiên bản mới nhất, bạn có thể đẩy model 8-bit lên Hub bằng push_to_hub(). File cấu hình lượng tử hóa config.json sẽ được đẩy trước, sau đó là các trọng số model đã lượng tử hóa.
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
quantization_config = BitsAndBytesConfig(load_in_8bit=True)
model = AutoModelForCausalLM.from_pretrained(
"bigscience/bloom-560m",
device_map="auto",
quantization_config=quantization_config
)
model.push_to_hub("bloom-560m-8bit")from transformers import AutoModelForCausalLM, BitsAndBytesConfig
quantization_config = BitsAndBytesConfig(load_in_4bit=True)
model_4bit = AutoModelForCausalLM.from_pretrained(
"bigscience/bloom-1b7",
device_map="auto",
quantization_config=quantization_config
)Mặc định, tất cả các module khác như torch.nn.LayerNorm sẽ được chuyển đổi sang torch.float16. Bạn có thể thay đổi kiểu dữ liệu của các module này bằng tham số dtype. Đặt dtype="auto" sẽ tải mô hình với kiểu dữ liệu được định nghĩa trong tệp config.json của mô hình.
import torch
from transformers import AutoModelForCausalLM, BitsAndBytesConfig
quantization_config = BitsAndBytesConfig(load_in_4bit=True)
model_4bit = AutoModelForCausalLM.from_pretrained(
"facebook/opt-350m",
device_map="auto",
quantization_config=quantization_config,
dtype="auto"
)
model_4bit.model.decoder.layers[-1].final_layer_norm.weight.dtypeHãy đảm bảo bạn đã cài đặt phiên bản bitsandbytes mới nhất để có thể serialize các mô hình 4-bit và đẩy chúng lên Hub bằng push_to_hub(). Sử dụng save_pretrained() để lưu mô hình 4-bit cục bộ.
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
quantization_config = BitsAndBytesConfig(load_in_4bit=True)
model = AutoModelForCausalLM.from_pretrained(
"bigscience/bloom-560m",
device_map="auto",
quantization_config=quantization_config
)
model.push_to_hub("bloom-560m-4bit")Huấn luyện 8-bit và 4-bit chỉ được hỗ trợ cho việc huấn luyện các tham số thêm.
Kiểm tra mức sử dụng bộ nhớ của bạn bằng get_memory_footprint.
print(model.get_memory_footprint())Tải các mô hình đã lượng tử hóa bằng from_pretrained() mà không cần quantization_config.
from transformers import AutoModelForCausalLM, AutoTokenizer
model = AutoModelForCausalLM.from_pretrained("{your_username}/bloom-560m-8bit", device_map="auto")LLM.int8
Phần này khám phá một số tính năng cụ thể của lượng tử hóa 8-bit, chẳng hạn như offloading, ngưỡng ngoại lệ, bỏ qua chuyển đổi module và finetuning.
Offloading
Các mô hình 8-bit có thể chuyển đổi trọng số giữa CPU và GPU để đưa các mô hình rất lớn vào bộ nhớ. Các trọng số được chuyển đến CPU được lưu ở dạng float32 và không được chuyển đổi sang 8-bit. Ví dụ, hãy bật tính năng offload cho bigscience/bloom-1b7 thông qua BitsAndBytesConfig.
from transformers import AutoModelForCausalLM, BitsAndBytesConfig
quantization_config = BitsAndBytesConfig(llm_int8_enable_fp32_cpu_offload=True)Thiết kế một bản đồ thiết bị tùy chỉnh để đặt mọi thứ lên GPU của bạn, ngoại trừ lm_head, phần này sẽ được điều phối sang CPU.
device_map = {
"transformer.word_embeddings": 0,
"transformer.word_embeddings_layernorm": 0,
"lm_head": "cpu",
"transformer.h": 0,
"transformer.ln_f": 0,
}Bây giờ hãy tải mô hình của bạn với device_map tùy chỉnh và quantization_config.
model_8bit = AutoModelForCausalLM.from_pretrained(
"bigscience/bloom-1b7",
dtype="auto",
device_map=device_map,
quantization_config=quantization_config,
)Ngưỡng ngoại lai
Một “outlier” là giá trị trạng thái ẩn lớn hơn một ngưỡng nhất định, và các giá trị này được tính toán ở fp16. Mặc dù các giá trị thường có phân phối chuẩn ([-3.5, 3.5]), nhưng phân phối này có thể rất khác nhau đối với các mô hình lớn ([-60, 6] hoặc [6, 60]). Lượng tử hóa 8-bit hoạt động tốt cho các giá trị ~5, nhưng vượt quá mức đó, sẽ có sự suy giảm hiệu suất đáng kể. Một giá trị ngưỡng mặc định tốt là 6, nhưng có thể cần một ngưỡng thấp hơn cho các mô hình kém ổn định hơn (mô hình nhỏ hoặc finetuning).
Để tìm ngưỡng tối ưu cho mô hình của bạn, hãy thử nghiệm với tham số llm_int8_threshold trong BitsAndBytesConfig. Ví dụ, đặt ngưỡng thành 0.0 sẽ tăng tốc độ suy luận đáng kể, với chi phí tiềm ẩn là một phần độ chính xác.
from transformers import AutoModelForCausalLM, BitsAndBytesConfig
model_id = "bigscience/bloom-1b7"
quantization_config = BitsAndBytesConfig(
llm_int8_threshold=0.0,
llm_int8_enable_fp32_cpu_offload=True
)
model_8bit = AutoModelForCausalLM.from_pretrained(
model_id,
dtype="auto",
device_map=device_map,
quantization_config=quantization_config,
)Bỏ qua chuyển đổi module
Đối với một số mô hình, chẳng hạn như Jukebox, bạn không cần phải lượng tử hóa mọi module xuống 8-bit vì điều này thực sự có thể gây ra sự bất ổn. Với Jukebox, có một số module lm_head nên được bỏ qua bằng cách sử dụng tham số llm_int8_skip_modules trong BitsAndBytesConfig.
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,
dtype="auto",
device_map="auto",
quantization_config=quantization_config,
)Tinh chỉnh
Thư viện PEFT hỗ trợ tinh chỉnh các mô hình lớn như flan-t5-large và facebook/opt-6.7b với lượng tử hóa 8-bit. Bạn không cần truyền tham số device_map cho quá trình huấn luyện vì nó tự động tải mô hình của bạn lên GPU. Tuy nhiên, bạn vẫn có thể tùy chỉnh bản đồ thiết bị bằng tham số device_map (device_map="auto" chỉ nên được sử dụng cho suy luận).
QLoRA
Phần này khám phá một số tính năng cụ thể của lượng tử hóa 4-bit, chẳng hạn như thay đổi kiểu dữ liệu tính toán, kiểu dữ liệu Normal Float 4 (NF4) và lượng tử hóa lồng nhau.
Loại dữ liệu tính toán
Thay đổi kiểu dữ liệu từ float32 (giá trị mặc định) sang bf16 trong BitsAndBytesConfig để tăng tốc độ tính toán.
import torch
from transformers import BitsAndBytesConfig
quantization_config = BitsAndBytesConfig(load_in_4bit=True, bnb_4bit_compute_dtype=torch.bfloat16)Float 4 thông thường (NF4)
NF4 là kiểu dữ liệu 4-bit từ bài báo QLoRA, được điều chỉnh cho các trọng số được khởi tạo từ phân phối chuẩn. Bạn nên sử dụng NF4 để huấn luyện các mô hình cơ bản 4-bit.
from transformers import BitsAndBytesConfig
nf4_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4",
)
model_nf4 = AutoModelForCausalLM.from_pretrained(model_id, dtype="auto", quantization_config=nf4_config)Đối với suy luận, bnb_4bit_quant_type không có tác động lớn đến hiệu suất. Tuy nhiên, để nhất quán với trọng số của mô hình, bạn nên sử dụng các giá trị bnb_4bit_compute_dtype và dtype.
Lượng tử hóa lồng nhau
Lượng tử hóa lồng nhau có thể tiết kiệm thêm bộ nhớ mà không làm tăng chi phí hiệu năng. Tính năng này thực hiện lượng tử hóa lần hai đối với các trọng số đã được lượng tử hóa để tiết kiệm thêm 0,4 bit/tham số. Ví dụ, với lượng tử hóa lồng nhau, bạn có thể tinh chỉnh một mô hình Llama-13b trên GPU NVIDIA T4 16GB với độ dài chuỗi là 1024, kích thước lô là 1, và bật tích lũy gradient với 4 bước.
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-chat-hf", dtype="auto", quantization_config=double_quant_config)Khử lượng hóa các mô hình bitsandbytes
Sau khi lượng tử hóa, bạn có thể dequantize() một mô hình về độ chính xác ban đầu, nhưng điều này có thể dẫn đến một số suy giảm chất lượng. Hãy đảm bảo bạn có đủ bộ nhớ GPU để chứa mô hình đã khử lượng tử hóa.
from transformers import AutoModelForCausalLM, BitsAndBytesConfig, AutoTokenizer
model = AutoModelForCausalLM.from_pretrained("facebook/opt-125m", BitsAndBytesConfig(load_in_4bit=True))
model.dequantize()Tài nguyên
Tìm hiểu thêm về các chi tiết của lượng tử hóa 8-bit trong A Gentle Introduction to 8-bit Matrix Multiplication for transformers at scale using Hugging Face Transformers, Accelerate and bitsandbytes.
Thử nghiệm lượng tử hóa 4-bit trong notebook này và tìm hiểu thêm về các chi tiết của nó trong Making LLMs even more accessible with bitsandbytes, 4-bit quantization and QLoRA.
Update on GitHub