콘텐츠로 이동

08. 하이퍼파라미터 튜닝 가이드#

📚 학습 목표: 학습 설정을 상황에 맞게 조정하기
⏱️ 읽는 시간: 20분
🎯 원칙: 처음에는 기본값, 결과 보고 조정


왜 하이퍼파라미터가 중요한가#

같은 데이터라도 하이퍼파라미터에 따라: - 학습 시간 2-5배 차이 - 최종 품질 10-30% 차이 - Overfitting 유무 결정

하지만: 처음부터 튜닝하려고 하지 마세요. 기본값이 90% 상황에서 최선.


🎯 우리 프로젝트 기본값 (추천)#

scripts/02b_train_mlx.sh 상단에 정의:

LORA_R=32              # LoRA 용량
LORA_ALPHA=64          # LoRA 스케일링
LEARNING_RATE=2e-4     # 학습률
BATCH_SIZE=2           # 배치 크기
ITERS=600              # 반복 횟수 (데이터량에 따라)
SAVE_EVERY=100         # 체크포인트 주기

이 값들이 왜 기본값인가: 수많은 LoRA 연구에서 한국어 중간 크기 모델(4B)에 적절하다고 검증된 값들.


1. LoRA Rank (r) - 가장 중요한 파라미터#

의미#

LoRA 어댑터의 "용량". 모델이 얼마나 많은 새 지식을 추가로 담을 수 있는지.

값별 특성#

r 값 어댑터 크기 학습 시간 적합한 경우
8 약 50MB 빠름 간단한 태스크, 포맷 학습
16 약 150MB 중간 단일 도메인 특화
32 약 300MB 표준 범용 도메인 모델
64 약 600MB 느림 많은 복잡한 지식
128 약 1.2GB 매우 느림 연구용, 거의 사용 안 함

우리 상황: r=32 이유#

  • 5개 카테고리 균형 학습 → 중간 용량 필요
  • 맥미니 24GB → r=64도 가능하지만 학습 시간 1.5배
  • 300MB 어댑터 → HuggingFace 업로드/관리 편리

조정 시나리오#

r 증가 (32 → 64): - 언제: 카테고리 늘어남, 데이터 5,000건+ - 비용: 학습 시간 +50% - 주의: 데이터 적으면 overfitting 심해짐

r 감소 (32 → 16): - 언제: 빠른 반복 실험, 단일 태스크 - 이득: 학습 시간 -30% - 주의: 복잡한 패턴 학습 약해짐


2. LoRA Alpha (α) - r의 짝꿍#

의미#

LoRA 업데이트의 "강도" 스케일링. actual_update = (α/r) × learned_update

표준 공식#

α = 2 × r (LoRA 논문 권장)

r α α/r
8 16 2.0
16 32 2.0
32 64 2.0
64 128 2.0

조정이 필요한 경우#

99% 상황에서 기본값 사용. 조정하는 케이스:

  • α/r = 1.0: 보수적 학습 (원본 많이 유지)
  • α/r = 2.0: 표준 ⭐
  • α/r = 4.0: 공격적 학습 (원본 많이 변경)

3. Learning Rate (lr) - 민감도 결정#

의미#

한 번에 파라미터를 얼마나 크게 바꿀지.

왜 민감한가#

  • 너무 크면: Loss 폭주 (NaN)
  • 너무 작으면: 학습 거의 안 됨

값별 특성#

lr 특성 적합
1e-3 공격적 짧은 학습 (100 iter 이하)
5e-4 빠름 풍부한 데이터
2e-4 표준 LoRA 일반
1e-4 보수적 안정적 학습
5e-5 매우 보수적 섬세한 튜닝

LR 스케줄 (자동 변경)#

우리 설정은 cosine을 사용:

Iter 0:   lr = 2e-4
Iter 100: lr = 1.95e-4  ← 천천히 감소
Iter 300: lr = 1e-4
Iter 500: lr = 2.5e-5
Iter 600: lr = 0        ← 마지막엔 0 근처

: 초반엔 많이 배우고, 후반엔 미세 조정.

조정 시나리오#

lr 증가 (2e-4 → 5e-4): - Loss가 거의 감소 안 할 때 - 데이터 매우 풍부 (5,000건+)

lr 감소 (2e-4 → 1e-4): - Loss가 폭주하거나 진동할 때 - 섬세한 도메인 (의료 용어 등)


4. Batch Size - 메모리 trade-off#

의미#

한 번의 업데이트에 몇 개 샘플을 같이 볼지.

맥미니 24GB 기준#

batch_size 메모리 사용 It/sec 품질
1 8GB 1.2 불안정
2 10GB 0.9 표준
4 14GB 0.5 안정적
8 22GB 0.25 빡빡 (OOM 위험)

조정 시나리오#

batch_size 증가 (2 → 4): - 메모리 여유 있을 때 - 더 안정적인 학습 원할 때 - 학습 시간 약 60% 증가

batch_size 감소 (2 → 1): - OOM 에러 날 때 - 더 빠른 실험 원할 때 - Loss 더 진동하지만 더 빠름

Gradient Accumulation (대안)#

메모리는 batch_size=2 유지, 효과는 더 큰 batch처럼:

# MLX에서 (지원 시)
--batch-size 2 --gradient-accumulation-steps 4
# = 실효 batch_size 8

5. Iterations (iters) - 학습 양#

의미#

총 몇 번 반복할지. 1 iter = 1번의 배치 업데이트.

계산법#

1 epoch = 데이터 총량 / batch_size
목표 epoch = 3 (LoRA 일반적)

예시:
- 500건 데이터, batch=2 → 1 epoch = 250 iter
- 3 epochs = 750 iter (⭐ 추천)

- 1,500건 데이터, batch=2 → 1 epoch = 750 iter
- 3 epochs = 2,250 iter

- 5,000건 데이터, batch=2 → 1 epoch = 2,500 iter
- 2 epochs = 5,000 iter (큰 데이터는 2 epoch도 충분)

데이터량별 권장 iter#

데이터량 권장 iter 학습 시간 (M4 24GB)
250건 (더미) 600 1-2시간
500건 750 1.5-2.5시간
1,500건 (MVP) 1,500-2,000 3-5시간
5,000건 3,000-5,000 8-12시간
10,000건 5,000-10,000 15-30시간 (Colab 추천)

과유불급#

너무 적은 iter: - Underfitting (학습 부족) - Loss가 아직 높은데 끝남

너무 많은 iter: - Overfitting (외우기) - Val loss가 다시 올라감

이상적: Val loss가 가장 낮은 지점에서 멈춤 (자동 멈춤 기능 활용)


6. 기타 파라미터들#

lora_layers#

어느 층에 LoRA를 적용할지.

--num-layers 16   # 기본값: 마지막 16개 층
--num-layers 8    # 더 적게 (학습 빠름, 성능 약간 낮음)
--num-layers 32   # 더 많이 (학습 느림, 성능 약간 높음)

우리 추천: 16 (기본값)

save_every#

체크포인트 저장 주기.

SAVE_EVERY=100     # 100 iter마다 저장
  • 너무 자주 (50): 디스크 낭비
  • 너무 드물게 (500): 중단 시 복구 어려움
  • 100: 균형 ⭐

val_batches#

검증 시 몇 개 배치 쓸지.

--val-batches 25   # 기본
  • 적으면: 검증 불안정
  • 많으면: 학습 시간 증가
  • 25: 균형

steps_per_report#

얼마나 자주 로그 출력할지.

--steps-per-report 10   # 10 iter마다 출력

steps_per_eval#

얼마나 자주 검증할지.

--steps-per-eval 50     # 50 iter마다 val loss 계산

🎯 상황별 프리셋 모음#

복사해서 바로 쓸 수 있는 설정들.

프리셋 1: 첫 실험 (더미 데이터) ⭐ 추천 시작점#

LORA_R=32
LORA_ALPHA=64
LEARNING_RATE=2e-4
BATCH_SIZE=2
ITERS=600

용도: 파이프라인 검증, 더미 250건

프리셋 2: MVP (500-1500건 실제 데이터) ⭐ 주력#

LORA_R=32
LORA_ALPHA=64
LEARNING_RATE=2e-4
BATCH_SIZE=2
ITERS=1500

용도: 메디콘솔 v1.0.0 정식 학습

프리셋 3: 빠른 실험 (소규모)#

LORA_R=16
LORA_ALPHA=32
LEARNING_RATE=3e-4
BATCH_SIZE=2
ITERS=500

용도: 하이퍼파라미터 A/B 테스트, 1시간 이내

프리셋 4: 고품질 (풍부한 데이터)#

LORA_R=64
LORA_ALPHA=128
LEARNING_RATE=1e-4
BATCH_SIZE=4
ITERS=3000

용도: 5,000건+ 데이터, 맥미니 24GB 풀가동

프리셋 5: 메모리 절약 (급할 때)#

LORA_R=16
LORA_ALPHA=32
LEARNING_RATE=2e-4
BATCH_SIZE=1
ITERS=1000

용도: 다른 앱과 병행, 메모리 압박 시


🔬 A/B 테스트 방법#

두 설정 중 어떤 게 나은지 비교하려면:

1. 첫 번째 실험#

# 프리셋 1로 학습
bash scripts/02b_train_mlx.sh

# 결과 보관
mv outputs/mlx_adapter outputs/mlx_adapter_A

2. 두 번째 실험#

# 설정 변경 (예: r=32 → r=16)
# scripts/02b_train_mlx.sh 수정

# 학습
bash scripts/02b_train_mlx.sh

# 결과 보관
mv outputs/mlx_adapter outputs/mlx_adapter_B

3. 평가 비교#

# A 버전
cp outputs/mlx_adapter_A/adapters.safetensors outputs/mlx_adapter/
make fuse-mlx convert deploy evaluate
# 결과 저장: eval_report_A.json

# B 버전
cp outputs/mlx_adapter_B/adapters.safetensors outputs/mlx_adapter/
make fuse-mlx convert deploy evaluate
# 결과 저장: eval_report_B.json

# 비교
diff eval_report_A.json eval_report_B.json

실용 팁#

A/B 테스트는 최소 1주일 일정 확보 후 시작. 성급한 비교는 노이즈에 현혹되기 쉬움.


📊 Loss 값으로 판단하는 법#

학습 완료 후 Train/Val loss를 보고:

좋은 패턴#

Train loss: 0.85
Val loss:   0.92
차이: 0.07

→ 건강함. 그대로 사용.

Overfitting 패턴#

Train loss: 0.20
Val loss:   1.50
차이: 1.30

→ 외우기. iter 줄이거나 데이터 추가.

Underfitting 패턴#

Train loss: 1.80
Val loss:   1.85
둘 다 높음

→ 덜 학습됨. iter 늘리거나 LR 증가.


⚠️ 흔한 실수#

실수 1: "크게 하면 좋을 것"#

# 나쁨
LORA_R=128
ITERS=10000
BATCH_SIZE=8

결과: OOM + 너무 긴 시간 + Overfitting

교훈: 기본값으로 시작, 부족할 때만 증가

실수 2: 한 번에 여러 파라미터 변경#

v1: r=32, lr=2e-4 → 점수 70%
v2: r=64, lr=1e-4, batch=4, iters=3000 → 점수 72%

뭐 때문에 2%p 올랐는지 모름.

교훈: 한 번에 하나만 변경.

실수 3: 평가 없이 계속 튜닝#

"Loss가 더 낮아졌으니 좋아졌겠지" → 실제 답변 품질은 떨어질 수 있음.

교훈: make evaluate실제 품질 확인.

실수 4: 과도한 튜닝#

5% 개선하려고 2주 쓰기 → 데이터 추가 2주가 10% 개선

교훈: 데이터 > 하이퍼파라미터. 막히면 데이터로 돌아가기.


🎓 튜닝 결정 트리#

학습 결과 안 좋음?
├── Loss 감소 없음?
│   └── lr을 높여라 (2e-4 → 5e-4)
├── Loss NaN 폭주?
│   └── lr을 낮춰라 (2e-4 → 5e-5)
├── Overfitting (Train << Val)?
│   ├── iter 줄여라 (2000 → 1000)
│   ├── 데이터 추가
│   └── r 줄여라 (32 → 16)
├── Underfitting (둘 다 높음)?
│   ├── iter 늘려라 (1000 → 2000)
│   ├── r 늘려라 (32 → 64)
│   └── 데이터 품질 확인
├── 특정 카테고리만 약함?
│   └── 해당 카테고리 데이터 추가 (하이퍼파라미터 X)
└── 전체적으로 품질 낮음?
    └── 데이터 품질 검토 (이게 답인 경우 많음)

✅ 자가 체크#

  • 기본값이 왜 그 값인지 감 잡음
  • 각 파라미터가 메모리/속도/품질에 어떻게 영향 주는지 알고 있음
  • 상황별 프리셋 중 하나 선택 가능
  • Loss 패턴 보고 어떤 파라미터 조정할지 판단 가능
  • A/B 테스트 방법 알고 있음

다음 단계#

학습 설정 이해했다면, 결과 평가로 갑니다.

다음 문서: 09_EVALUATION.md - 품질 평가 방법


💡 핵심 요약#

처음: 기본값 (r=32, α=64, lr=2e-4, batch=2, iters=1500)
막히면: 한 번에 하나만 변경
원칙: 데이터 > 하이퍼파라미터
판단: Loss 그래프 + 실제 평가 점수