QLoRA: 16GB GPU에서 7B 모델 미세 조정하기 (5.4GB로 용량이 줄어들었습니다)
요약
QLoRA를 사용하여 7B 모델을 16GB GPU 환경에서 효율적으로 미세 조정하는 방법을 설명합니다. 4비트 양자화(NF4)와 이중 양자화 기술을 통해 모델 메모리 점유율을 15GB에서 5.4GB로 획기적으로 줄이는 과정을 다룹니다.
핵심 포인트
- 4비트 양자화(NF4)를 통해 베이스 모델의 메모리 사용량을 극적으로 절감
- NF4와 이중 양자화(double quantization)를 활용한 정밀도 유지 및 용량 최적화
- 저장은 4비트로 하되 연산은 fp16으로 수행하여 학습 효율성 확보
- 단일 소비자용 GPU에서도 대규모 모델의 미세 조정 가능
시리즈 — 미세 조정 (Fine-Tuning), 가장 작은 모델부터 가장 큰 모델까지:
- Full Fine-Tuning (270M)
- LoRA (1.5B)
- QLoRA (7B) ← 현재 위치
- 작은 모델이 작동했다면, 왜 더 큰 모델로 가야 할까요?
Part 2에서, LoRA를 통해 모델을 동결(freezing)하고 아주 작은 어댑터(adapters)를 학습시킴으로써 1.5B 모델을 미세 조정(fine-tune)할 수 있었습니다. 하지만 동결된 베이스 모델은 여전히 16비트(약 3GB) 상태로 메모리에 남아 있었습니다. 이제 저는 Qwen2.5-7B로 넘어가고 싶었지만, LoRA만으로는 해결할 수 없는 벽에 부딪혔습니다.
문제점
7B 모델은 16비트 정밀도(precision)에서 약 15GB입니다. 무료 티어의 T4 GPU는 16GB를 제공합니다. 이는 모델을 겨우 로드할 수 있는 수준이며, 실제로 학습을 진행할 여유 공간이 전혀 남지 않습니다.
QLoRA의 통찰
QLoRA는 LoRA에서 자연스럽게 이어지는 질문을 던집니다: 베이스 모델은 동결되어 오직 읽기 전용으로만 사용되는데, 왜 굳이 전체 정밀도로 저장해야 하는가?
따라서 여러분은 **동결된 베이스를 4비트로 양자화(quantize)**합니다 (신경망 가중치의 분포에 맞춰 조정된 형식인 NF4 사용). 그리고 그 위에 일반 정밀도로 LoRA 어댑터를 실행합니다. 베이스 모델의 크기는 극적으로 줄어들고, 학습 가능한 부분은 작고 정밀하게 유지됩니다.
from transformers import BitsAndBytesConfig
bnd_config = BitsAndBytesConfig(
...
각 플래그(flag)는 그만한 가치가 있습니다:
load_in_4bit— 동결된 가중치를 16비트 대신 4비트로 저장합니다.nf4— 신경망 가중치의 종 모양 분포(bell-curve distribution)에 맞춘 4비트 유형입니다 (일반적인 int4보다 우수함).double_quant— 양자화 상수(quantization constants)까지 양자화하여 저장 공간을 조금 더 절약합니다.compute_dtype— 실제 행렬 곱셈(matmuls)을 위해 fp16으로 역양자화(dequantize)합니다. 즉, *저장(storage)*은 4비트로 하되, *연산(compute)*은 정밀하게 유지합니다.
깨달음의 순간
출력된 한 줄의 메시지:
loaded in 4-bit. footprint: 5.44 GB
저는 15.2GB의 가중치를 다운로드했지만, 메모리에는 5.44GB로 자리 잡았습니다. 전체 미세 조정(full fine-tuning)을 위해서는 로드조차 할 수 없었던 모델이, 이제는 단일 소비자용 GPU에서 여유 공간을 남겨둔 채 학습되고 있습니다. (다운로드 용량은 여전히 15GB입니다. bitsandbytes가 로드하는 동안 실시간으로 양자화를 수행하기 때문입니다.)
QLoRA 표준 레시피
Part 2의 LoRA 설정에서 두 가지 요소가 더 추가됩니다: 훈련을 위해 양자화된 모델을 준비하는 것과, paged 8-bit optimizer를 사용하여 모든 선형 레이어 (linear layers)를 타겟팅하는 것입니다 (QLoRA 논문에서는 이것이 중요하다고 밝혔습니다).
from peft import prepare_model_for_kbit_training
model = prepare_model_for_kbit_training(model, use_gradient_checkpointing=True)
# ... 모든 선형 레이어에 LoRA를 부착 ...
...
속도는 느리지만, 괜찮습니다
Gradient checkpointing을 사용한 4-bit 가중치 기반의 7B 모델 순전파 (forward pass)는 부하가 큽니다. T4 GPU 기준으로 1 에포크(epoch)당 약 1시간이 소요되며, 초당 약 3개의 예시를 처리합니다. 하지만 QLoRA의 목적은 속도가 아니라, 적합성 (fit)에 있습니다. 모델이 평소라면 담을 수 없는 하드웨어에서도 실행될 수 있게 만드는 것, 그것이 핵심입니다.
⚠️ 하드웨어 참고 사항:
bitsandbytes4-bit는 CUDA 우선입니다. Apple MPS에서는 작동하지 않으며, AMD/ROCm 지원은 존재하지만 아직 성숙도가 낮습니다. 이 작업은 NVIDIA GPU(Kaggle/Colab T4 사용 가능)에서 실행하세요.
결과
[여기에 귀하의 QLoRA 정확도 + macro-F1 입력]. 이는 Part 1과 2에서 다룬 더 작은 모델들과 거의 대등한 수준이었습니다.
그리고 두 작은 모델 모두를 괴롭혔던 card_arrival 대 card_delivery_estimate 혼동 문제는 어떠했을까요? [7B 모델에서 어떤 일이 일어났는지 기술하세요 — 마침내 해결되었나요, 아니면 똑같은 벽에 부딪혔나요?] 어느 쪽이든, 이는 제가 Part 4에서 다룰 질문을 던집니다: 270M 모델이 이미 잘 작동했다면, 왜 이 모든 것을 만들었는가?
📓 Kaggle의 전체 실행 가능한 노트북: https://www.kaggle.com/code/sumannath88/03-qlora-qwen2-5-7b
PyTorch + Transformers + PEFT + bitsandbytes로 제작되었습니다. 질문이나 수정 사항은 댓글로 환영합니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기