Transformers documentation
Bitsandbytes
Bitsandbytes
bitsandbytes 라이브러리는 하드웨어 가속기 함수를 감싼 경량 Python 래퍼를 통해 LLM을 위한 양자화 도구를 제공합니다. 이를 통해 메모리 사용량을 줄여 제한된 계산 리소스로도 대규모 모델을 다룰 수 있습니다.
bitsandbytes의 핵심 기능은 다음과 같습니다:
- 양자화 Linear 레이어: 표준 PyTorch linear 레이어를 메모리 효율적인 양자화 대안으로 대체하는
Linear8bitLt및Linear4bit레이어 - 최적화된 옵티마이저:
optim모듈을 통해 일반적인 옵티마이저의 8-bit 버전을 제공하여, 메모리 요구 사항을 줄여 대규모 모델을 학습할 수 있습니다 - 행렬 곱셈: 양자화 형식을 활용하는 최적화된 행렬 곱셈 연산
bitsandbytes는 두 가지 주요 양자화 기능을 제공합니다:
LLM.int8() - 성능 저하 없이 추론을 보다 쉽게 사용할 수 있도록 하는 8비트 양자화 방법입니다. 단순한 양자화와 달리 LLM.int8()는 중요한 계산에 대해 동적으로 더 높은 정밀도를 유지하여 모델의 민감한 부분에서 정보 손실을 방지합니다.
QLoRA - 학습 가능한 소수의 저순위 적응(LoRA) 가중치를 삽입하여 학습 가능성을 유지하면서 모델을 더욱 압축하는 4-bit 양자화 기법.
참고: 사용자 친화적인 양자화 경험을 위해
bitsandbytes커뮤니티 스페이스를 사용할 수 있습니다.
bitsandbytes를 설치하려면 아래 명령을 실행하세요.
pip install --upgrade transformers accelerate bitsandbytes
소스에서 컴파일하려면 bitsandbytes 설치 가이드의 지침을 따르세요.
하드웨어 호환성
bitsandbytes는 CUDA 버전 11.8 - 13.0을 사용하는 NVIDIA GPU, Intel XPU, Intel Gaudi (HPU), CPU에서 지원됩니다. 추가 플랫폼에 대한 지원 작업이 진행 중입니다. 피드백 제공이나 테스트에 관심이 있으시다면, 자세한 내용은 bitsandbytes 저장소를 확인해 보세요.
NVIDIA GPU (CUDA)
이 백엔드는 Linux x86-64, Linux aarch64, Windows 플랫폼에서 지원됩니다.
| 기능 | 최소 하드웨어 요구 사항 |
|---|---|
| 8-bit 옵티마이저 | NVIDIA Pascal (GTX 10X0 시리즈, P100) 또는 더 새로운 GPU * |
| LLM.int8() | NVIDIA Turing(RTX 20X0 시리즈, T4) 또는 더 새로운 GPU |
| NF4/FP4 양자화 | NVIDIA Pascal (GTX 10X0 시리즈, P100) 또는 더 새로운 GPU * |
Intel GPU(XPU)
이 백엔드는 Linux x86-64 및 Windows x86-64 플랫폼에서 지원됩니다.
Intel Gaudi (HPU)
이 백엔드는 Gaudi2와 Gaudi3에서 Linux x86-64를 지원합니다.
CPU
이 백엔드는 Linux x86-64, Linux aarch64, Windows x86-64 플랫폼에서 지원됩니다.
양자화 예제
BitsAndBytesConfig를 from_pretrained()에 전달하여 모델을 양자화합니다. Accelerate를 지원하고 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
)기본적으로 torch.nn.LayerNorm과 같은 다른 모든 모듈은 torch의 기본 dtype으로 설정됩니다. dtype 매개변수를 사용하여 이러한 모듈의 데이터 유형을 변경할 수 있습니다. dtype="auto"로 설정하면 모델의 config.json 파일에 정의된 데이터 유형으로 모델을 로드합니다.
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.dtype모델이 8-bit으로 양자화되면, push_to_hub()를 통해 양자화된 가중치를 Hub에 올릴 수 있습니다. 단, 최신 버전의 Transformers와 bitsandbytes를 사용해야 합니다. 최신 버전을 사용하고 있다면, 8-bit 모델을 Hub에 올릴 수 있으며, 양자화 config.json 파일이 먼저 업로드된 후 양자화된 모델 가중치가 업로드됩니다.
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
)기본적으로 torch.nn.LayerNorm과 같은 모든 다른 모듈은 torch.float16으로 변환됩니다. dtype 파라미터를 사용하여 이러한 모듈의 데이터 유형을 변경할 수 있습니다. dtype="auto"로 설정하면 모델의 config.json 파일에 정의된 데이터 유형으로 모델을 로드합니다.
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.dtype4-bit 모델을 직렬화하여 push_to_hub()로 Hub에 올릴 수 있도록 최신 버전의 bitsandbytes를 설치했는지 확인하세요. 4-bit 모델을 로컬에 저장하려면 save_pretrained()를 사용하세요.
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")8비트 및 4비트 학습은 추가 파라미터 학습에만 지원됩니다.
get_memory_footprint을 사용하여 메모리 사용량을 확인하세요.
print(model.get_memory_footprint())quantization_config 없이 from_pretrained()로 양자화 모델을 로드합니다.
from transformers import AutoModelForCausalLM, AutoTokenizer
model = AutoModelForCausalLM.from_pretrained("{your_username}/bloom-560m-8bit", device_map="auto")LLM.int8
이 섹션에서는 오프로딩, 아웃라이어 임계값, 모듈 변환 스킵, 파인튜닝과 같은 8-bit 양자화의 특정 기능을 살펴봅니다.
오프로딩
8-bit 모델은 CPU와 GPU 사이에서 가중치를 오프로드하여 매우 큰 모델을 메모리에 적재할 수 있습니다. CPU로 전달된 가중치는 float32로 저장되며 8-bit로 변환되지 않습니다. 예를 들어, BitsAndBytesConfig를 통해 bigscience/bloom-1b7에 대한 오프로딩을 활성화할 수 있습니다.
from transformers import AutoModelForCausalLM, BitsAndBytesConfig
quantization_config = BitsAndBytesConfig(llm_int8_enable_fp32_cpu_offload=True)lm_head를 제외하고 모든 것을 GPU에 배치하도록 커스텀 device map을 설계합니다. lm_head는 CPU로 dispatch됩니다.
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",
dtype="auto",
device_map=device_map,
quantization_config=quantization_config,
)이상치 임계값
“outlier”는 특정 임계값을 초과하는 hidden state 값을 의미하며, 이러한 값은 fp16로 계산됩니다. 일반적으로 값은 정규 분포([-3.5, 3.5])를 따르지만, 대규모 모델의 경우 분포가 매우 달라질 수 있습니다([-60, 6] 또는 [6, 60]). 8-bit 양자화는 값이 약 5인 경우 잘 작동하지만, 그 이상에서는 상당한 성능 저하가 발생합니다. 좋은 기본 임계값은 6이지만, 더 불안정한 모델(소형 모델 또는 finetuning)의 경우 더 낮은 임계값이 필요할 수 있습니다.
모델에 가장 적합한 임계값을 찾으려면 BitsAndBytesConfig의 llm_int8_threshold 매개변수를 실험해 보세요. 예를 들어, 임계값을 0.0으로 설정하면 정확도가 일부 저하될 수 있지만 추론 속도가 크게 빨라집니다.
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,
)모듈 변환 건너뛰기
Jukebox와 같은 일부 모델의 경우, 모든 모듈을 8-bit로 양자화하면 오히려 불안정성이 발생할 수 있으므로 양자화를 수행할 필요가 없습니다. Jukebox에서는 BitsAndBytesConfig의 llm_int8_skip_modules 매개변수를 사용하여 건너뛰어야 하는 여러 lm_head 모듈이 있습니다.
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,
)파인튜닝
PEFT 라이브러리는 flan-t5-large와 facebook/opt-6.7b와 같은 대규모 모델의 8-bit 양자화를 통한 fine-tuning을 지원합니다. 모델이 자동으로 GPU에 로드되므로 학습 시 device_map 매개변수를 전달할 필요가 없습니다. 다만, device_map 매개변수를 사용하여 디바이스 맵을 커스터마이즈할 수 있습니다(device_map="auto"는 추론에만 사용해야 합니다).
QLoRA
이 섹션에서는 4-bit 양자화의 특정 기능, 예를 들어 compute data type 변경, Normal Float 4 (NF4) data type, nested quantization 등을 살펴봅니다.
데이터 유형 계산
BitsAndBytesConfig에서 데이터 유형을 float32(기본값)에서 bf16으로 변경하여 계산 속도를 높입니다.
import torch
from transformers import BitsAndBytesConfig
quantization_config = BitsAndBytesConfig(load_in_4bit=True, bnb_4bit_compute_dtype=torch.bfloat16)일반 Float 4 (NF4)
NF4는 QLoRA 논문에서 제안된 4비트 데이터 타입으로, 정규 분포에서 초기화된 가중치에 맞게 조정되었습니다. 4비트 베이스 모델을 학습할 때는 NF4를 사용해야 합니다.
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)추론 시 bnb_4bit_quant_type은 성능에 큰 영향을 주지 않습니다. 그러나 모델 가중치와 일관성을 유지하려면 bnb_4bit_compute_dtype과 dtype 값을 사용해야 합니다.
중첩 양자화
중첩 양자화(Nested quantization)는 추가적인 성능 저하 없이 추가 메모리를 절약할 수 있습니다. 이 기능은 이미 양자화된 가중치에 대해 두 번째 양자화를 수행하여 파라미터당 0.4비트를 추가로 절약합니다. 예를 들어, 중첩 양자화를 사용하면 시퀀스 길이가 1024이고 배치 크기가 1이며 4단계의 그라디언트 축적을 활성화한 상태에서 16GB NVIDIA T4 GPU에서 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("meta-llama/Llama-2-13b-chat-hf", dtype="auto", quantization_config=double_quant_config)bitsandbytes 모델의 역양자화
양자화 후 dequantize()를 통해 모델을 원래 정밀도로 복원할 수 있지만, 이로 인해 일부 품질 저하가 발생할 수 있습니다. 양자화 해제된 모델을 수용할 수 있을 만큼 충분한 GPU 메모리가 있는지 확인하세요.
from transformers import AutoModelForCausalLM, BitsAndBytesConfig, AutoTokenizer
model = AutoModelForCausalLM.from_pretrained("facebook/opt-125m", BitsAndBytesConfig(load_in_4bit=True))
model.dequantize()리소스
8-bit 양자화의 세부 사항은 Hugging Face Transformers, Accelerate, bitsandbytes를 사용한 대규모 transformers를 위한 8-bit 행렬 곱셈에 대한 부드러운 소개에서 자세히 알아보세요.
이 노트북에서 4-bit 양자화를 시도하고, bitsandbytes, 4-bit 양자화 및 QLoRA를 통해 LLM을 더욱 접근 가능하게 만들기에서 세부 사항을 자세히 알아보세요.
Update on GitHub