32장. 파인튜닝 입문 — LoRA / QLoRA
이 장의 목표 “내 데이터로 모델을 학습시킬 수 있나요?” 라는 가장 흔한 질문에 답합니다.
어떻게 / 왜 / 그리고 언제 안 해도 되는지 를 정리합니다.
32.1 먼저 — RAG로 충분한 경우가 많다
대부분의 “모델 학습시키고 싶다” 는 욕구는 사실 RAG (26장) 로 해결됩니다.
| 목적 | 추천 |
|---|---|
| 사내 문서로 답하게 | RAG |
| 회사 용어·약어 이해 | RAG + 시스템 프롬프트 |
| 특정 톤·스타일 답변 | Few-shot 프롬프트 (21장) |
| 분류·태깅 자동화 | Few-shot + Structured Output |
| 모델이 새 작업 자체를 배우게 | 파인튜닝 |
| 새 언어·도메인 전문 능력 | 파인튜닝 |
파인튜닝은 시간·디스크·전기가 듭니다. 정말 필요한지 한 번 더 자문하세요.
32.2 파인튜닝 종류
| 방식 | 특징 | 메모리 |
|---|---|---|
| Full Fine-Tuning | 모든 파라미터 학습 | 매우 큼 (32B → 200GB+) |
| LoRA | 작은 어댑터만 학습 | 보통 |
| QLoRA | 양자화 + LoRA | 작음 (32B → 24GB로도) |
| DPO / ORPO | 선호도 기반 정렬 | LoRA와 비슷 |
로컬 환경(맥 64GB) 에서는 LoRA / QLoRA 가 거의 유일한 현실적 선택.
32.3 LoRA가 뭔가?
원본 모델은 그대로 두고, 작은 보조 행렬을 양 옆에 붙여서 그 작은 부분만 학습하는 방식.
[원본 가중치] (32B) ─ 그대로
↑
[LoRA 어댑터] (수 MB ~ 수백 MB) ← 여기만 학습
장점:
- 학습할 파라미터가 1% 이하
- 메모리·시간 크게 절약
- 같은 베이스에 여러 LoRA를 붙였다 떼었다 가능
- 어댑터 파일이 작음 (배포 쉬움)
품질은 Full Fine-Tuning에 거의 근접.
32.4 QLoRA — LoRA + 양자화
원본 모델을 4bit로 양자화한 상태로 그 위에 LoRA만 학습.
[양자화된 베이스 4bit] (32B → 16GB)
+
[LoRA 어댑터] (수백 MB)
↓
학습 메모리 절약 극대화
이게 맥에서 32B 모델 파인튜닝을 가능하게 합니다.
32.5 데이터 — 가장 중요한 것
파인튜닝 성패의 80%는 데이터 품질.
데이터 형식 (Instruct 학습 예)
{"messages": [
{"role": "user", "content": "회의록을 임원용 5줄 요약으로:\n..."},
{"role": "assistant", "content": "결정사항: ...\n액션: ..."}
]}
JSONL (한 줄 = 한 예시) 형식이 흔함.
양
| 작업 | 권장 샘플 수 |
|---|---|
| 톤·스타일 | 100~500 |
| 새로운 형식 출력 | 500~2,000 |
| 도메인 전문성 | 5,000~50,000 |
| 새 언어 | 100,000+ |
품질
- 중복 제거
- 모범 답안 만 사용
- 어색한 답·실수 포함되면 모델이 그걸 따라함
- 일부러 다양한 표현·길이 섞기
32.6 맥에서 LoRA 학습 — MLX 기반
19장의 mlx-lm 이 LoRA 학습도 지원합니다.
설치:
$ pip install -U mlx-lm
학습:
$ mlx_lm.lora \
--model mlx-community/Qwen3-8B-Instruct-4bit \
--train \
--data ./my_dataset \
--iters 1000 \
--batch-size 4 \
--lora-layers 8 \
--learning-rate 1e-5
| 옵션 | 의미 |
|---|---|
--model | 베이스 모델 |
--data | 폴더 (train.jsonl, valid.jsonl 포함) |
--iters | 학습 반복 횟수 |
--lora-layers | LoRA 적용할 레이어 수 |
--learning-rate | 학습률 |
결과: adapters/ 폴더에 어댑터 파일들.
32.7 학습한 어댑터로 추론
$ mlx_lm.generate \
--model mlx-community/Qwen3-8B-Instruct-4bit \
--adapter-path ./adapters \
--prompt "회의록을 요약해줘: ..."
베이스 + 어댑터를 함께 로드합니다.
32.8 학습한 어댑터를 베이스에 합치기
$ mlx_lm.fuse \
--model mlx-community/Qwen3-8B-Instruct-4bit \
--adapter-path ./adapters \
--save-path ./my-custom-model
이렇게 만들면 어댑터가 베이스에 합쳐져서 일반 모델처럼 배포할 수 있습니다.
32.9 GGUF로 변환
합친 모델을 GGUF로 만들고 싶다면 (Ollama 등 사용):
33장 절차를 따릅니다.
32.10 데이터 준비 자동화
수작업으로 500개 쓰는 건 힘들죠.
LLM 보조
- 합성 데이터(synthetic data): GPT/Claude 같은 큰 모델로 먼저 모범 답안을 만들어 데이터 셋 구축
- 자체 LLM-as-judge: 생성된 데이터의 품질을 다른 LLM이 평가
⚠ 합성 데이터로만 학습하면 원본 모델의 한계를 그대로 답습할 수 있음.
가능하면 실제 사람 작성 데이터 일부 섞으세요.
32.11 자주 만나는 함정
과적합 (Overfitting)
데이터 적은데 너무 오래 학습 → 외워버림.
대처:
- validation set 분리
- 학습률 낮추기
- iters 짧게
- Early stopping
망각 (Catastrophic Forgetting)
새 작업은 잘하는데 기존 능력 잃음.
대처:
- 일반 데이터 일부 섞기
- LoRA를 가볍게 (rank 작게)
- learning rate 낮게
메모리 폭주
batch size 줄이기, 컨텍스트 길이 줄이기, 4bit QLoRA 쓰기.
32.12 평가 — 학습이 잘 됐는지
40장에서 본격 다루지만 미리.
- 테스트 셋 30~50개 분리 (학습에 안 들어간 것)
- 학습 전/후 같은 입력에 답 비교
- LLM-as-judge 또는 사람 평가
- 정량 지표 (정확도·BLEU·ROUGE 등)
32.13 언제 파인튜닝하지 말아야 하나
- 데이터가 100개 이하 → 프롬프트로 시도
- 자주 바뀌는 정보 → RAG
- 회사 정책·정답이 있는 일 → RAG + 시스템 프롬프트
- 한 번만 쓸 일
파인튜닝은 “장기·반복 사용“이 보장될 때 의미 있음.
이 장에서 기억할 한 가지
로컬 파인튜닝 = LoRA / QLoRA + MLX.
데이터 품질이 80%, 알고리즘은 20%.
그리고 시작하기 전에 한 번 더: “이거 RAG로 안 되나?” 자문하세요.
손으로 해볼 것
1. 작은 LoRA 한 번 돌려보기
mlx-examples/lora 디렉토리에 있는
샘플 데이터셋을 그대로 사용해서 한 번 학습해보세요.
$ git clone https://github.com/ml-explore/mlx-examples
$ cd mlx-examples/lora
$ python lora.py --train
학습 그래프와 결과 변화를 관찰.
2. 회의록 요약 톤 LoRA 데이터셋 모으기
본인의 과거 회의록 요약 30개를 질문-답 형태로 정리해보세요.
{"messages": [
{"role":"user", "content":"다음 회의록을 임원용 5줄로:\n..."},
{"role":"assistant", "content":"..."}
]}
이게 다음 파인튜닝 실습의 데이터셋이 됩니다.
다음 장에서는 모델 변환·양자화 를 직접 해봅니다.
LoRA로 학습한 모델을 GGUF로 만들거나, 새로 나온 모델을 직접 양자화하는 절차.