QLoRA
QLoRA는 4비트 NF4로 저장된 동결 기본 모델에 LoRA 어댑터를 학습시켜 LLM을 미세 조정하므로, 단일 48 GB GPU에서 65B 매개변수 모델을 학습할 수 있습니다.
QLoRA(양자화 저랭크 적응)는 사전 학습된 대형 언어 모델(LLM)을 4비트 정밀도로 동결하고 그 위에 소규모 LoRA 어댑터를 학습하는 파인튜닝 방법입니다. 양자화된 가중치를 통해 역전파를 수행해 어댑터를 학습합니다. Dettmers 등이 2023년 QLoRA 논문에서 소개한 이 방법은 650억 파라미터 모델 파인튜닝에 필요한 GPU 메모리를 780GB 이상에서 48GB 미만으로 줄여 단일 워크스테이션 GPU에서 실행할 수 있게 했으며, 16비트 파인튜닝과 동등한 작업 성능을 유지했습니다. 이 방법으로 파인튜닝한 논문의 Guanaco 모델은 단일 GPU에서 24시간 학습한 뒤 Vicuna 벤치마크에서 ChatGPT 점수의 99.3%를 달성했습니다.
QLoRA 작동 방식#
QLoRA는 동결된 압축 기반 모델에 세 가지 메모리 절약 기법을 결합합니다.
- 4비트 NormalFloat(NF4): 각 가중치는 정규 분포 분위수에 배치된 16개 수준 중 하나를 가리키는 4비트 코드로 저장되며, 가중치 64개 블록마다 절대 최댓값 스케일 하나가 사용됩니다. 사전 학습된 모델 가중치는 대체로 정규 분포를 따르므로 분위수 수준은 대부분의 가중치가 위치하는 0 부근에서 더 높은 해상도를 제공합니다.
- 이중 양자화: 블록별 스케일 자체를 256개 단위의 블록에서 8비트로 양자화해 파라미터당 오버헤드를 0.5비트에서 약 0.127비트로 줄입니다. 65B 모델에서 약 3GB를 절약합니다.
- 페이징 옵티마이저: 옵티마이저 상태는 NVIDIA 통합 메모리에 저장되며, 그래디언트 체크포인팅 중 긴 시퀀스를 처리하는 경우처럼 메모리가 급증하면 CPU RAM으로 이동합니다. 따라서 메모리 부족 오류로 학습이 중단되지 않습니다.
순전파 중에는 각 동결 계층의 NF4 가중치가 행렬 곱셈 직전에 bfloat16으로 역양자화되고, LoRA 경로의 출력이 더해집니다. 역전파는 역양자화된 가중치를 통해 기울기를 계산하지만, 업데이트 대상은 저랭크 LoRA 행렬 두 개뿐입니다. 논문에서는 전체 파인튜닝과 동등한 성능을 내려면 Transformer 블록의 모든 선형 계층에 어댑터를 적용해야 한다고 밝혔습니다.
아래 코드는 bitsandbytes 라이브러리의 방식대로 NF4 수준을 생성하고, 정규 분포 가중치 블록에서 16개의 균일 간격 수준과 비교합니다.
import torch
torch.manual_seed(0)
normal = torch.distributions.Normal(0.0, 1.0)
# NF4: 16 levels at quantiles of a normal distribution, with an exact zero (as built in bitsandbytes)
positive = normal.icdf(torch.linspace(0.9677083, 0.5, 9)[:-1])
negative = -normal.icdf(torch.linspace(0.9677083, 0.5, 8)[:-1])
nf4 = torch.cat([negative, torch.zeros(1), positive]).sort().values
nf4 = nf4 / nf4.max()
int4 = torch.linspace(-1, 1, 16) # evenly spaced 4-bit levels for comparison
weights = torch.randn(4096, 64) * 0.02 # pretrained weights are roughly normal, in blocks of 64
absmax = weights.abs().amax(dim=1, keepdim=True) # one scale per block
for name, levels in (("NF4", nf4), ("INT4", int4)):
codes = ((weights / absmax)[..., None] - levels).abs().argmin(dim=-1) # 4-bit index per weight
restored = levels[codes] * absmax
print(f"{name} mean squared error: {(restored - weights).pow(2).mean():.3e}")출력 결과는 NF4의 평균 제곱 오차가 3.395e-06이고 균일 간격 수준의 평균 제곱 오차는 4.053e-06임을 보여 줍니다. 동일한 16개 수준과 동일한 블록 스케일을 사용할 때 NF4의 분위수 간격은 정규 분포 가중치의 재구성 오류를 약 16% 줄입니다. 실제로 Hugging Face Transformers는 BitsAndBytesConfig를 사용해 bitsandbytes로 NF4 모델을 불러오며, 이 설정은 load_in_4bit=True, bnb_4bit_quant_type="nf4", bnb_4bit_use_double_quant=True, bnb_4bit_compute_dtype=torch.bfloat16을 지정합니다. PEFT 라이브러리는 LoRA 어댑터를 연결합니다.
QLoRA와 관련 방법 비교#
- LoRA: 16비트 정밀도로 유지되는 기반 모델에서 같은 종류의 어댑터를 학습합니다. 65B 모델의 16비트 가중치만으로 약 130GB가 필요하지만, NF4로 저장하면 대략 4분의 1로 줄어듭니다.
- 파라미터 효율적 파인튜닝(PEFT): LoRA, QLoRA, 어댑터, 프롬프트 튜닝 등 소수의 파라미터를 학습하는 방법을 포괄하는 계열입니다.
- 학습 후 모델 양자화: 완성된 모델을 추론용으로 압축합니다. QLoRA로 튜닝한 모델은 흔히 16비트 가중치로 병합한 다음 서비스용으로 다시 양자화합니다.
- 양자화 인식 학습(QAT): 순전파 중 저정밀도 반올림을 시뮬레이션하면서 모든 가중치를 학습해 배포된 모델이 저정밀도에서도 정확도를 유지하도록 합니다. Ultralytics YOLO26은
quantize=8로 학습할 때 INT8 QAT를 실행하고, NVIDIA ModelOpt를 통해 합성 양자화를 합성곱 및 선형 계층에 삽입해 학습된 가중치가 INT8 내보내기 후에도 유지되도록 합니다.
절충점#
QLoRA는 메모리를 절약하는 대신 속도를 희생합니다. 매 순전파 및 역전파마다 동결된 모든 가중치를 역양자화하므로 학습 단계가 16비트 LoRA보다 느립니다. 어댑터는 작아 작업별로 저장하고 교체하기 쉽지만, 기반 모델에 병합하려면 먼저 16비트로 역양자화해야 합니다. 65B 모델의 경우 4비트 가중치와 이중 양자화된 스케일에 약 34GB가 필요하므로, 48GB GPU에서 나머지 공간을 어댑터, 활성화 값, 페이징 옵티마이저 상태에 사용할 수 있습니다.










