35

QLoRA: 16GB GPU로 7B 모델을 학습하는 마법

파인튜닝 개요 & LoRA/QLoRA

학습 목표

QLoRA의 3가지 핵심 기술을 이해한다 (NF4, 이중 양자화, 페이지드 옵티마이저) 양자화가 메모리를 줄이는 원리를 파악한다 QLoRA vs LoRA 메모리 비교를 할 수 있다

QLoRA: Quantized LoRA

김대리의 질문

"LoRA가 학습 파라미터를 줄인다는 건 알겠는데, 기본 모델 자체가 28GB면 GPU에 안 올라가잖아요?"

박선배의 답

"그래서 QLoRA가 나온 거야. 기본 모델을 4비트로 압축해서 올리는 거지. 28GB -> 4GB로 줄어들어. 그 위에 LoRA를 얹는 거고."

메모리 비교

Llama-2-7B 기준:

방법              | 모델    | 학습    | 옵티마이저 | 총 VRAM
------------------+--------+---------+-----------+--------
Full FT (FP32)    | 28 GB  | 28 GB   | 56 GB     | 112 GB
Full FT (FP16)    | 14 GB  | 14 GB   | 28 GB     | 56 GB
LoRA (FP16)       | 14 GB  | 0.1 GB  | 0.2 GB    | ~16 GB
QLoRA (NF4)       | 4 GB   | 0.1 GB  | 0.2 GB    | ~6 GB  <-- !!!

QLoRA는 RTX 4060 (8GB)으로도 가능!

QLoRA의 3가지 핵심 기술

1. NF4 (4-bit NormalFloat)

일반 4-bit 양자화:
  - 균등 간격으로 16개 값 배정
  - 문제: 가중치 분포는 정규분포인데, 균등하게 나누면 손실 큼

NF4:
  - 정규분포에 최적화된 16개 값 배정
  - 분포의 중심(0 근처)에 더 많은 값 할당
  - 결과: 일반 4-bit 대비 정보 손실 50% 감소!

NF4 양자화 레벨 (예시):
  [-1.0, -0.69, -0.52, -0.39, -0.28, -0.18, -0.09, 0.0,
    0.08,  0.17,  0.27,  0.38,  0.51,  0.68,  0.99, 1.0]

2. 이중 양자화 (Double Quantization)

일반 양자화:
  가중치 블록 (64개) -> 양자화 -> 양자화 상수 (FP32, 4바이트)
  메모리: 가중치 + 양자화 상수
  양자화 상수 오버헤드: 0.5 bit/param

이중 양자화:
  양자화 상수도 양자화!
  FP32 양자화 상수 -> 8-bit 양자화
  오버헤드: 0.127 bit/param (74% 감소!)

7B 모델 기준 절약: ~400MB

3. 페이지드 옵티마이저 (Paged Optimizers)

문제:
  - GPU 메모리가 부족하면 OOM 에러로 학습 중단
  - 특히 긴 시퀀스 처리 시 메모리 스파이크 발생

해결:
  - NVIDIA Unified Memory 활용
  - 메모리 부족 시 GPU -> CPU로 자동 스왑
  - 여유가 생기면 CPU -> GPU로 자동 복구

비유: "가상 메모리"와 같은 원리
  - 실제 RAM이 부족하면 디스크를 임시로 사용하는 것처럼
  - GPU VRAM이 부족하면 CPU RAM을 임시로 사용

코드로 보는 QLoRA 설정

from transformers import BitsAndBytesConfig
import torch

# QLoRA 양자화 설정
bnb_config = BitsAndBytesConfig(
    load_in_4bit=True,              # 4비트 양자화 활성화
    bnb_4bit_quant_type="nf4",      # NF4 양자화 (핵심 1)
    bnb_4bit_use_double_quant=True, # 이중 양자화 (핵심 2)
    bnb_4bit_compute_dtype=torch.bfloat16,  # 연산은 BF16으로
)

# 모델 로드 (4비트로 압축되어 올라감)
from transformers import AutoModelForCausalLM

model = AutoModelForCausalLM.from_pretrained(
    "meta-llama/Llama-3.3-70B-Instruct",
    quantization_config=bnb_config,
    device_map="auto",  # GPU 자동 배치
)

# LoRA 설정
from peft import LoraConfig, get_peft_model

lora_config = LoraConfig(
    r=16,
    lora_alpha=32,
    target_modules=["q_proj", "k_proj", "v_proj", "o_proj"],
    lora_dropout=0.05,
    bias="none",
    task_type="CAUSAL_LM",
)

# QLoRA 모델 생성
model = get_peft_model(model, lora_config)
model.print_trainable_parameters()
# 출력: trainable params: 16,777,216 || all params: 6,738,415,616 || trainable%: 0.249

QLoRA가 성능을 유지하는 이유

Q: 4비트로 압축하면 성능이 떨어지지 않나?

A: 핵심 포인트!
   - 4비트로 압축되는 건 "기본 모델 가중치" (W)
   - 학습되는 건 "LoRA 어댑터" (BA) -> 이건 FP16/BF16
   - 역전파 시 BF16으로 계산 -> 정밀도 유지

   즉, "읽기"는 4비트, "쓰기(학습)"는 16비트!

   논문 결과:
   - QLoRA vs Full FT 성능 차이 < 1%
   - 메모리는 95% 절약
   - 놀라운 효율!
AI로 학습하기 — 꿀팁
QLoRA 3대 기술 개념 오류 점검AI 학습 팁

NF4 양자화, 이중 양자화, 페이지드 옵티마이저 각각의 메모리 절감 기여분이 과장되거나 혼동되지 않았는지 검증해 보세요.

QLoRA의 세 가지 핵심 기술에 대해 내가 정리한 내용이 정확한지 검증해줘. (1) NF4 양자화: '4비트로 가중치를 저장해 메모리를 16비트 대비 4분의 1로 줄인다.' (2) 이중 양자화: '양자화 상수까지 한 번 더 양자화해서 파라미터당 약 0.5비트를 추가로 절약한다.' (3) 페이지드 옵티마이저: 'GPU 메모리가 부족할 때 옵티마이저 상태를 CPU RAM으로 페이징한다.' 각 항목의 오류나 빠진 뉘앙스를 제조 sLLM 학습 16GB GPU 맥락으로 교정해줘.
이 팁이 도움이 됐나요?
실습 — 직접 해보기
🧪QLoRA 파인튜닝 랩
4/8/16-bit 양자화를 토글하며 베이스 모델 VRAM이 어떻게 줄어드는지 체험해보세요
핵심 포인트
  • QLoRA = NF4 양자화 + 이중 양자화 + 페이지드 옵티마이저
  • 7B 모델: 112GB -> 6GB (95% 메모리 절약)
  • 기본 모델은 4비트로 압축, LoRA 어댑터는 16비트로 학습
  • 성능 저하 < 1%, 메모리 절약 95%