20. Lab: 수학/코딩 강화 모델
난이도: 중급 | GPU: RTX 3090~5090 | 소요 시간: 2~6시간
목표
Llama-3.2-1B를 수학 문제 풀이에 특화시키는 SFT -> DPO 파이프라인을 실습합니다. 두 가지 주입 방식(dense_lora, moe_expert_lora)으로 각각 SFT+DPO를 수행하여 총 4가지 훈련을 비교합니다.
왜 Llama-3.2-1B인가?
- 1B 파라미터는 수학 추론에 충분하지 않습니다 (표현력 한계)
- 그러나 RTX 3090~5090 단일 GPU에서 10분 내 실험 가능
- SFT로 기초 수학 능력을 주입하고, DPO로 미세 조정하는 파이프라인 패턴을 배우는 것이 핵심
- 실제 프로덕션에서는 3B~8B 모델에 같은 파이프라인을 적용
사전 준비
데이터 다운로드
19_data_collection.md의 섹션 2 (수��� 데이터) 를 실행하여 다음 파일을 준비합니다:
data/math/sft/math_orca_200000.jsonl # SFT 훈련 (200K)
data/math/sft/math_orca_35.jsonl # SFT 벤치 (35 rows)
data/math/dpo/math_step_dpo_10700.jsonl # DPO 훈련 (10.7K)
파이프라인 스크립트
# 스크립트를 프로젝트 루트에 복사 (configs/, data/ 와 같은 위치)
cp examples/run_llama32_pipeline_math.sh ./
chmod +x run_llama32_pipeline_math.sh
아키텍처
SFT (Orca-Math 200K)
┌──────────────┐ ┌─────────────────────┐
│ dense_lora │ │ moe_expert_lora │
│ (plain LoRA) │ │ (FFN->MoE+expert) │
└──────┬───────┘ └─────────┬───────────┘
v v
Bench Bench
│ │
v v
┌──────────────┐ ┌���────────────────────┐
│ dense_lora │ │ moe_expert_lora │
│ DPO │ │ DPO (router frozen) │
└──────┬───────┘ └─────────���───────────┘
v v
Bench Bench
Config 설명
Dense LoRA SFT (configs/presets/math/llama3.2_dense_lora_sft.yml)
injection:
strategy: dense_lora
lora_r: 64 # 큰 r -> 높은 표현력 (1B 모델 보���)
lora_alpha: 64 # alpha/r = 1.0 (표준)
start_layer: 4 # 초기 레이어는 일반 특성이므로 건너뜀
num_layers: 0 # start_layer 이후 전체
training:
lr: 1.5e-4 # SFT에서는 비교적 높은 LR
max_train_steps: 10000
batch_size: 10
MoE Expert LoRA SFT (configs/presets/math/llama3.2_moe_expert_lora_sft.yml)
injection:
strategy: moe_expert_lora
num_experts: 4 # 전문가 4명
top_k: 2 # 각 토큰마다 2명 선택
training:
phases:
- step: 0
trainable: ["lora", "attn_lora", "router"] # LoRA + Router 동시
- step: 5000
trainable: ["lora", "attn_lora", "router", "base_ffn"] # base FFN도 오픈
lr: 1.0e-4
max_train_steps: 30000 # MoE는 더 오래 훈련
참고: 수학 단일 도메인에서 MoE는 다소 과한 구성입니다. 4개 Expert가 모두 수학에 특화되어 다양성이 떨어질 수 있습니다. MoE의 진가는 여러 도메인(수학+금융+CoT+일반)을 동시에 훈련할 때 발휘됩니다 -- 23_lab_full_pipeline_moe.md에서 이를 확인할 수 있습니다.
Dense LoRA DPO (configs/presets/math/llama3.2_dense_lora_dpo.yml)
training:
type: dpo
dpo_beta: 0.05 # 작은 beta -> 정책 이탈 허용 폭 넓음
phases:
- step: 0
trainable: ["lora", "attn_lora"] # base_ffn 닫힘!
lr: 2.0e-6 # SFT 대비 ~75배 낮음!
max_train_steps: 2500 # ~1 epoch
grad_accum_steps: 16 # effective batch 64
max_grad_norm: 0.5 # 그래디언트 클리핑 강화
MoE Expert LoRA DPO (configs/presets/math/llama3.2_moe_expert_lora_dpo.yml)
training:
type: dpo
dpo_beta: 0.20 # MoE는 더 보수적으로 (beta 높음)
phases:
- step: 0
trainable: ["lora", "attn_lora"] # Router FROZEN! (민감)
lr: 1.5e-6
max_train_steps: 1600
max_grad_norm: 0.3 # 더 강한 클리핑
Router Freezing: MoE SFT에서 학습된 라우터는 DPO에서 동결합니다. 라우터가 preference 데이터에 과적합하면 기존 라우팅 체계가 무너져 전체 성능이 저하될 수 있습니다.
DPO 하이퍼파라미터 가이드
DPO는 SFT를 흔들지 않도록 매우 보수적으로 설정하는 것이 기본 기조입니다:
| 파라미터 | SFT 범위 | DPO 권장 범위 | 이유 |
|---|---|---|---|
lr |
1e-4 ~ 1e-3 | 1e-6 ~ 5e-6 | SFT 성과를 보존 |
dpo_beta |
-- | 0.05 ~ 0.3 | 높을수록 기존 정책에 가까이 유지 |
max_grad_norm |
1.0 | 0.3 ~ 0.5 | 급격한 변화 방지 |
base_ffn |
후반 open | 끝까지 닫음 | 변화량 제한 |
max_train_steps |
10K~30K | 1K~3K | 과적합 방지 (~1 epoch) |
DPO 전용 노브:
dpo_beta: 기준 정책에서 얼마나 멀어질지 조절하는 핵심값. 높은 beta는 SFT 정책으로부터의 이탈을 줄입니다. "SFT가 잘 된 상태에서 선호만 살짝 다듬고 싶다"면beta: 0.2~0.3을 먼저 시도하세요.label_smoothing: Noisy preference 데이터에 대한 과적합 완화. Robust DPO에서는 0.0~0.5 사이 값을 사용합니다.- 과적합 징후:
reward_margin이 5 이상으로 폭주,accuracy가 1.0에서 고정, rejected 쪽 길이 이상/다양성 저하
실행
방법 1: 파이프라인 스크립트 (권장)
# dense_lora만 실행 (SFT -> DPO)
RUN_DENSE_LORA=true RUN_MOE_EXPERT_LORA=false \
./run_llama32_pipeline_math.sh
# moe_expert_lora만 실행
RUN_DENSE_LORA=false RUN_MOE_EXPERT_LORA=true \
./run_llama32_pipeline_math.sh
# 둘 다 실행
./run_llama32_pipeline_math.sh
스크립트는 각 단계마다 자동으로 벤치마크를 실행합니다: - SFT 벤치: base model(Llama-3.2-1B) 대비 SFT 모델 비교 - DPO 벤치: base model 대비 DPO 모델 비교
방법 2: 수동 실행
# 1. Dense LoRA SFT
eulerforge train \
--preset configs/presets/math/llama3.2_dense_lora_sft.yml \
--set data.format=raw --set data.task=sft \
--set data.path=data/math/sft/math_orca_200000.jsonl \
--set data.max_length=512 \
--output-dir outputs/math/dense_lora/sft
# 2. Dense LoRA DPO (SFT 체크포인트 기반)
eulerforge train \
--preset configs/presets/math/llama3.2_dense_lora_dpo.yml \
--set model_name=outputs/math/dense_lora/sft/final \
--set data.format=raw --set data.task=prompted_preference \
--set data.path=data/math/dpo/math_step_dpo_10700.jsonl \
--set data.max_length=1024 \
--output-dir outputs/math/dense_lora/dpo
출력 구조
outputs/math_simple/llama3.2_1b/
├── models/
│ ├── dense_lora/
│ │ ├── sft/final/ # SFT 체크포인트
│ │ └���─ dpo/final/ # DPO 체크포인트
│ └── moe_expert_lora/
│ ├── sft/final/
│ └── dpo/final/
���── benchs/
├── dense_lora/
│ ├── sft/ # SFT 벤치 결과
│ └── dpo/ # DPO 벤치 결과
└── moe_expert_lora/
├── sft/
└── dpo/
결과 해석
기대 패턴
- SFT: base 모델(1B pretrain) 대비 수학 점수 상승 (bench avg_score 1~2점 -> 3~5점)
- DPO: SFT 대비 미세 향상 또는 유지. DPO는 "선호 정렬"이므로 극적 향상보다는 답변 품질/형식 개선
- Dense vs MoE: 단일 도메인에서는 큰 차이 없음. MoE의 장점은 멀티도메인 환경에서 드러남
주의사항
- 1B 모델은 수학 추론 능력에 근본적 한계가 있음 -- 점수가 낮더라도 정상
- DPO 초기 loss가 ln(2) = 0.693 근처에서 시작하면 정상 (reference = SFT 모델)
reward_margin이 점진적으로 증가하면 학습이 잘 되고 있는 신호
다음 단계
- MoE가 단일 도메인에서 과한 이유를 체감했다면, 23_lab_full_pipeline_moe.md에서 수학+금융+CoT+일반 SFT를 모두 섞어 MoE의 진짜 효과를 확인하세요
- DPO 하이퍼파라미터 튜닝: 12_grid_search.md로
dpo_beta,lr을 자동 탐색 - 더 큰 모델(3B, 7B)에 같은 파이프라인 적용