12 KiB
FRANKENSTALLM 3B — SFT 완료, 종합 평가, 코드 개선 및 ORPO 준비 보고서
작성일: 2026-03-06 Phase: Phase 2 (SFT) 완료 → Phase 3 (ORPO) 준비 완료 이 보고서의 범위: SFT v1 완료, 6차원 평가, SFT v2 설계, 코드 개선, ORPO 준비
1. SFT v1 학습 완료
1.1 최종 결과
| 항목 | 값 |
|---|---|
| 최종 Step | 25,500 / 33,000 (77.3%) |
| 종료 사유 | Early stopping (patience 5 exhausted) |
| Best val_loss | 1.8851 (step 23,000) |
| 최종 train_loss | ~1.80 |
| 학습 시작 | 2026-03-05 22:15 |
| 학습 종료 | 2026-03-06 13:56 |
| 총 학습 시간 | ~15시간 41분 |
| VRAM | 24.2 GB / 183 GB (13.2%) — 전 구간 일정 |
| 사고 | 0건 |
1.2 Val Loss 전체 추이
Step 500: 2.0732
Step 1,000: 2.0035 (-0.070)
Step 2,000: 1.9558 (-0.048)
Step 3,000: 1.9329 (-0.023)
Step 5,000: 1.9107 (-0.022)
Step 10,000: 1.8917 (-0.019)
Step 15,000: 1.8864 (-0.005)
Step 20,000: 1.8853 (-0.001)
Step 23,000: 1.8851 ← BEST
Step 23,500~25,500: 1.8851 (변동 없음, patience 1~5/5)
Step 25,500: Early Stop
수렴 분석: step 15K 이후 val_loss 변동 < 0.001. Cosine decay LR이 step 23K에서 2.18e-06까지 감소하여 실질적 학습 종료. Early stopping이 정확히 작동.
1.3 학습 설정 (v1)
| 항목 | 값 | 근거 |
|---|---|---|
| LR | 1e-5 | Pretrain LR(1.5e-4)의 1/15 — forgetting 방지 |
| Effective batch | 64 (2 × 8GPU × 4 accum) | |
| NEFTune alpha | 5.0 | 임베딩 노이즈로 생성 다양성 향상 |
| Warmup | 500 steps | |
| Weight decay | 0.01 | |
| Max steps | 33,000 | ~3.3 epochs |
2. SFT 종합 평가 결과 (6차원)
평가 일시: 2026-03-06 16:27, SFT 체크포인트: checkpoint-best (step 23000), 소요 49분 27초
2.1 차원별 판정
| # | 평가 차원 | 결과 | 핵심 수치 |
|---|---|---|---|
| 1 | Perplexity (지식 보존) | PASS | 최대 forgetting 0.9% (임계값 15%) |
| 2 | 생성 품질 (반복률/EOS) | FAIL | Greedy 반복률 72.97% (목표 <5%) |
| 3 | 한국어 벤치마크 | FAIL | KoBEST 평균 43.26% (목표 >55%) |
| 4 | 영어 벤치마크 (유지) | PASS | 모든 태스크 하한 초과 |
| 5 | Calibration | PASS | Top-1 68.59% (목표 >=65%) |
| 6 | SFT Chat 능력 | PASS | EOS 종료율 60% (Base 0% → 60%) |
종합: 4/6 차원 통과
2.2 Base vs SFT 핵심 비교
| 지표 | Base | SFT | 변화 | 판정 |
|---|---|---|---|---|
| Val PPL (통합) | 5.2263 | 5.2529 | +0.5% | PASS |
| Greedy 3-gram 반복률 | 60.99% | 72.97% | +12pp | FAIL (악화) |
| EOS 종료율 | 0% | 60% | +60pp | 개선 (목표 미달) |
| KoBEST 평균 | 43.69% | 43.26% | -0.4pp | FAIL |
| MMLU-KO | 22.75% | 26.00% | +3.2pp | 부분 개선 |
2.3 Perplexity 상세 (19개 데이터셋)
| 데이터셋 | Base PPL | SFT PPL | Forgetting % |
|---|---|---|---|
| 3b | 5.2263 | 5.2529 | +0.5% |
| cc100_ko | 21.7820 | 21.8072 | +0.1% |
| hplt_ko | 2.4028 | 2.4121 | +0.4% |
| korean_c4 | 5.7173 | 5.7617 | +0.8% |
| korean_namuwiki | 25.8814 | 26.1185 | +0.9% |
평균 Forgetting: +0.4% — 19개 전체 PASS. 지식 보존 우수.
2.4 생성 샘플
Greedy (반복 문제):
- "대한민국의 수도는" → "서울특별시입니다. 대한민국의 수도는 서울이며..." (EOS=True, rep=0%)
- "인공지능이란" → 동일 문장 5회 반복 (EOS=True, rep=82.5%)
- "한국의 전통 음식 중에서" → 김치 설명 5회 반복 (EOS=False, rep=83.6%)
Sampled (t=0.7, rep_penalty=1.2) → 반복률 0%:
- 파라미터 검색에서 rep_penalty 1.1~1.3 적용 시 반복률 0% 달성 확인
- ORPO가 이 행동을 내재화할 수 있다는 근거
2.5 한국어 벤치마크 (0-shot)
| 태스크 | Base | SFT | 변화 |
|---|---|---|---|
| kobest_boolq | 50.28% | 50.14% | -0.1pp |
| kobest_copa | 49.30% | 48.60% | -0.7pp |
| kobest_hellaswag | 21.60% | 19.80% | -1.8pp |
| kobest_sentineg | 48.61% | 49.12% | +0.5pp |
| kobest_wic | 48.65% | 48.65% | +0.0pp |
| 평균 | 43.69% | 43.26% | -0.4pp |
| haerae | 19.71% | 19.89% | +0.2pp |
| MMLU-KO | 22.75% | 26.00% | +3.2pp |
KoBEST는 거의 변동 없음 (SFT가 0-shot 분류 능력을 크게 바꾸지 않음). MMLU-KO의 +3.2pp 개선은 instruction-following이 다소 반영된 결과.
3. SFT v1의 한계와 v2 설계
3.1 v1 한계 분석
SFT v1은 지식 보존(forgetting 0.9%)에서 우수했으나, 핵심 목표인 반복률 해소에 실패했다.
| 문제 | 원인 분석 |
|---|---|
| Greedy 반복률 72.97% (base 60.99%보다 악화) | LR 1e-5가 너무 보수적 → SFT 데이터의 패턴을 충분히 학습하지 못함 |
| KoBEST 변동 없음 | 동일 원인: 낮은 LR로 instruction-following이 약하게 학습됨 |
| Val_loss 1.8851 plateau | Cosine decay가 step 20K에서 사실상 0 → 추가 학습 여지 소진 |
3.2 SFT v2 설계 (configs/korean_3b_sft_v2.yaml)
v1 실패를 바탕으로 SFT v2를 설계하고 설정 및 코드를 준비했다.
| 항목 | SFT v1 | SFT v2 | 변경 근거 |
|---|---|---|---|
| LR | 1e-5 | 5e-5 | 5배 상향, 3B SFT 표준 범위 (Llama-3 SFT 참고) |
| Effective batch | 64 | 256 | 4배 확대 (bs=4, accum=8) |
| Warmup | 500 | 2,000 | 높은 LR 안정화 |
| Max steps | 33,000 | 15,000 | 높은 LR+큰 배치 → 빠른 수렴 |
| Weight decay | 0.01 | 0.05 | forgetting 억제 강화 |
| Data mixing | 없음 | SFT 70% + Pretrain 30% | catastrophic forgetting 방지 |
3.3 ORPO 경로 선택 이유
SFT v2를 실행하기 전에, 먼저 ORPO로 반복 문제를 해결하는 것이 더 효율적이라고 판단:
- SFT v1의 지식 보존이 우수 (forgetting 0.9%) → base가 건강함
- 반복 문제는 선호도 정렬의 영역 — 반복을 "나쁜 응답"으로 학습시키는 것이 더 직접적
- 파라미터 검색에서 rep_penalty로 0% 달성 → 모델이 반복하지 않는 능력 자체는 있음
- SFT v2 후에도 ORPO가 필요할 가능성 높음 → 단계 절약
4. 이번 세션의 코드 변경 사항
4.1 train/sft.py — MixingDataLoader + DDP 최적화 (+238줄)
MixingDataLoader 클래스: SFT 데이터와 Pretrain 데이터를 확률적으로 인터리빙하는 DataLoader 래퍼.
pretrain_ratio=0.3이면 30% 배치가 pretrain에서, 70%가 SFT에서 옴- 양쪽 DataLoader 무한 사이클 (epoch 단위 자동 재시작)
- 빈 DataLoader 방어 (RuntimeError with 상세 메시지)
DDP Rank 0 전용 토크나이징:
- 이전: 8개 rank가 각각 독립 토크나이징 → 8배 중복 작업 + 8배 메모리
- 개선: Rank 0만 64-worker 병렬 토크나이즈 + 디스크 캐시 → DDP barrier → 나머지 rank는 캐시 로드
- 효과: 메모리 8배 절감, 재실행 시 ~2분으로 단축 (21GB
.sft_cache.pt)
새 CLI 인자: --pretrain_data, --pretrain_mix_ratio, --max_grad_norm
4.2 train/trainer.py — Early Stopping DDP 수정 (+17줄)
문제: 기존 코드에서 rank 0만 early stopping을 판단하고 return → 나머지 rank는 무한 대기 (DDP hang)
해결: torch.distributed.broadcast로 early stopping 결정을 전 rank에 동기화.
stop_tensor = torch.tensor([1 if should_stop else 0], device=self.device)
torch.distributed.broadcast(stop_tensor, src=0)
추가 변경: patience 5 → 10 (v2에서 warmup 후 충분한 학습 보장)
4.3 train/orpo.py — YAML 설정 지원 + 3B 기본값 (+30줄)
- YAML config 파일 로드 기능 추가 (
--config인자) - 3B 최적화 기본값: batch=2, accum=8, max_length=2048, max_prompt_length=1024
- output_dir 기본값:
checkpoints/korean_3b_orpo
4.4 eval/report_generator.py — SFT 비교 보고서 생성기 (+831줄)
Base vs SFT 비교 보고서를 자동 생성하는 대규모 확장:
- Base 모델 참조값 내장 (PPL 19개, 벤치마크 전체)
- Forgetting 계산 (PPL 변화율)
- 생성 품질 비교 (반복률, EOS, chat template)
- 벤치마크 비교 (한국어 7개 + 영어 6개, 0-shot + 5-shot)
- Calibration 비교
- ORPO 진행 판정 자동 로직
- Repetition 파라미터 검색 결과 통합
4.5 eval/tasks/generation_task.py — Chat Template + 다양성 메트릭 (+75줄)
- 환경변수 기반 체크포인트 경로 (
EVAL_CHECKPOINT,EVAL_TOKENIZER) - Chat template 지원 (
USE_CHAT_TEMPLATE=1→<|user|>...<|assistant|>포맷) compute_diversity_metrics(): Distinct-n, Type-Token Ratio 추가
4.6 eval/tasks/{calibration,ppl,token_nll}_task.py — 로깅 개선 (+35줄)
logging모듈 도입 (기존print→ 구조화된 로깅)
4.7 eval/sft_eval_pipeline.py — 새 파일 (SFT 6차원 평가 파이프라인)
8-GPU 병렬 SFT 평가를 위한 통합 파이프라인:
- Phase 1: PPL (19개 데이터셋, GPU 0-4 분배)
- Phase 2: 생성 품질 + 파라미터 검색 (GPU 6-7)
- Phase 3: 벤치마크 (KoBEST, HAE-RAE, MMLU-KO, MMLU-EN, 영어 5대)
- Phase 4: 자동 보고서 생성 + ORPO 판정
4.8 설정 파일
| 파일 | 설명 |
|---|---|
configs/korean_3b_sft_v2.yaml |
SFT v2 설정 (lr=5e-5, data mixing 70/30, 15K steps) |
configs/korean_3b_orpo.yaml |
ORPO 설정 (lr=5e-6, beta=0.1, 795K pairs) |
scripts/launch_3b_sft_v2.sh |
SFT v2 런처 (NCCL 최적화, pre-flight checks) |
scripts/launch_3b_orpo.sh |
ORPO 런처 업데이트 |
5. Phase 게이트 판정 및 다음 단계
5.1 결정: Phase 3 ORPO 진행
| 근거 | 상세 |
|---|---|
| 지식 보존 양호 | forgetting 0.9% — base 지식 파괴 없음 |
| 반복 미해결 | greedy 72.97% — 선호도 정렬이 직접적 해결 경로 |
| 파라미터 검색 희망적 | rep_penalty 1.2 적용 시 0% → ORPO가 내재화 가능 |
| 데이터 준비 완료 | 795,468 preference pairs (7.9GB) |
| 코드/설정 완비 | train/orpo.py, configs/korean_3b_orpo.yaml |
5.2 ORPO 실행 계획
1. HF 변환: checkpoint-best → safetensors
2. ORPO 학습: scripts/launch_3b_orpo.sh
3. 평가: eval/sft_eval_pipeline.py
4. 판정: 반복률 < 5% → GGUF + Ollama 배포
5.3 SFT v2 백업 경로
ORPO가 충분하지 않을 경우:
SFT v2 (lr=5e-5, data mixing) → ORPO → 재평가
6. 전체 프로젝트 타임라인
Feb 25 125M FP8 검증, 인프라 세팅
Feb 25-26 1B Pretrain (34K steps, loss 1.904)
Feb 26 1B SFT v1 실패 (label off-by-one → loss=0)
Feb 27 5-에이전트 루트 코즈 분석 (5가지 버그 발견)
Feb 27 1B SFT v2 성공 (val_loss 2.206, 반복률 18%)
Feb 27 저스티스리그 토론 → 3B 전환 결정
Feb 27 640GB+ 데이터 조립
Mar 02 Phase 0 완료 (GQA FA, VRAM -20%, SIGHUP 3중 방어)
Mar 02 Phase 1 시작 (3B Pretrain)
Mar 05 Phase 1 완료 (57K steps, loss 1.466, 63시간)
Mar 05 SFT 데이터 준비 (24소스 → 2.44M samples, 5단계 필터)
Mar 05 Phase 2 시작 (3B SFT v1)
Mar 06 Phase 2 완료 (25.5K steps, val_loss 1.8851, early stopping)
Mar 06 SFT 6차원 평가 (4/6 PASS, 반복률 FAIL)
Mar 06 코드 개선 (MixingDataLoader, DDP early stop fix, eval pipeline)
Mar 06 SFT v2 설계 + ORPO 설정 준비
Mar 06 → ORPO 진행 결정
7. 수정 파일 요약
| 파일 | 변경 | 줄 수 |
|---|---|---|
train/sft.py |
MixingDataLoader, DDP 토크나이징, CLI 인자 | +238 |
eval/report_generator.py |
SFT 비교 보고서 생성기 | +831 |
eval/tasks/generation_task.py |
Chat template, 다양성 메트릭 | +75 |
eval/tasks/calibration_task.py |
로깅 개선 | +13 |
eval/tasks/ppl_task.py |
로깅 개선 | +11 |
eval/tasks/token_nll_task.py |
로깅 개선 | +11 |
train/orpo.py |
YAML config, 3B 기본값 | +30 |
train/trainer.py |
DDP early stop broadcast, patience 10 | +17 |
scripts/launch_3b_orpo.sh |
3B ORPO 런처 업데이트 | +10 |
신규: eval/sft_eval_pipeline.py |
SFT 6차원 평가 파이프라인 | 신규 |
신규: configs/korean_3b_sft_v2.yaml |
SFT v2 설정 | 신규 |
신규: configs/korean_3b_orpo.yaml |
ORPO 설정 | 신규 |
신규: scripts/launch_3b_sft_v2.sh |
SFT v2 런처 | 신규 |
총 변경: +1,312줄 / -132줄
이 보고서는 SFT v1 완료(early stopping at step 25,500), 6차원 종합 평가, SFT v2 설계, 코드 개선, ORPO 준비를 포괄합니다.
상세 평가: reports/2026-03-06_3B_SFT_EVALUATION_REPORT.md
상세 평가 계획: reports/2026-03-06_3B_SFT_EVAL_PLAN.md