Files
frankenstallm/source/eval/decision/restart_scenario.md
ModelHub XC d4abdb70fa 初始化项目,由ModelHub XC社区提供模型
Model: pathcosmos/frankenstallm
Source: Original Platform
2026-07-14 04:21:16 +08:00

319 lines
15 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# "처음부터 다시 시작" 시나리오 완전 분석
**작성일**: 2026-02-26
**역할**: "처음부터 제대로 다시" 옹호자
**결론**: ✅ **1B SFT 재학습 강력 권장 (40분), 3B 전환은 병렬 준비**
---
## 1. 현재 접근법의 근본적 한계
### 1.1 발견된 버그/문제가 가중치에 미친 영향
지금까지 발견된 문제들을 정리하면:
| # | 버그/문제 | 가중치 오염 정도 | 제거 가능? |
|---|-----------|-----------------|-----------|
| 1 | 프롬프트 포맷 불일치 (`### 질문:` vs `<\|user\|>`) | ❌ 가중치 무관 (추론 버그) | 추론 코드만 수정 |
| 2 | Dynamic padding 미작동 (4096 고정 패딩) | 🟡 간접 영향 — 학습 효율 저하로 실질 epoch 부족 | 재학습 필요 |
| 3 | 트렁케이션 시 EOS 손실 (0.04%) | 🟢 미미 (61/159K 샘플) | 코드 이미 수정됨 |
| 4 | `</s>` 리터럴 오염 데이터 113건 | 🟡 EOS 경계 혼란 유발 | 데이터 필터 필요 |
| 5 | Output 내 Q/A 마커 ~550건 | 🟡 자체 루프 패턴 학습 | 데이터 필터 필요 |
| 6 | OpenOrca 5배 업샘플링 → 과적합 | 🔴 가중치에 깊이 각인 | 재학습 필요 |
| 7 | Val split 없음 → 과적합 감지 불가 | — | 재학습 시 추가 |
| 8 | ~2 epoch만 학습 (업계 표준 3-5) | 🔴 underfitting | 재학습 필요 |
| 9 | 짧은 output 10.4% (50자 미만) | 🟡 EOS 타이밍 학습 불안정 | 데이터 필터 필요 |
### 1.2 "오염된 학습"의 가중치 잔류 여부
**결론: 부분적으로 남아있고, 완전 제거 불가능.**
SFT는 base model 위에 얇은 layer를 미세조정한 것이 아니라 **전체 가중치를 업데이트**한다. 5000 steps × lr=2e-5로 학습된 gradient update는 모든 layer에 분포되어 있으며:
- OpenOrca 5배 업샘플링으로 인해 해당 소스의 패턴이 **과도하게 각인**
- Q/A 마커 오염 데이터(550건)의 패턴도 가중치에 분산 저장
- `</s>` 리터럴이 포함된 113건이 EOS 토큰 예측 확률 분포를 왜곡
이들은 추가 학습(continual training)으로 "덮어쓸" 수는 있지만, **기존 오염을 정확히 역전시키는 것은 불가능**. 추가 학습은 새로운 gradient로 기존 가중치를 수정하지만, 이미 학습된 잘못된 패턴의 흔적(특히 low-rank subspace에서)은 완전히 사라지지 않는다.
### 1.3 반복 퇴화 17.7%: 파라미터 문제 vs 가중치 문제
수정 후 반복률 변화를 보면:
```
포맷 불일치 상태: 57% → 포맷 수정만으로 → 30.7% → +추론 파라미터 → 17.7%
```
**분석:**
- 57% → 30.7% (포맷 수정): **추론 버그** — 가중치 무관 ✅
- 30.7% → 17.7% (rep_penalty + no_repeat_ngram): **추론 파라미터** — 가중치 무관 ✅
- **잔여 17.7%**: 이것이 **가중치 수준의 문제**
17.7%의 구성:
- 코드 설명 시 알파벳 나열 반복 (샘플 #2: 30.5%)
- 리스트형 답변에서 유사 항목 반복 (샘플 #4: 21.3%, #7: 24.4%, #8: 23.8%)
- 단순 사실 답변은 정상 (샘플 #1: 0.0%, #9: 13.3%)
**결론: 17.7%는 가중치 수준 문제.** 원인:
1. 학습 데이터 자체의 반복 패턴 (57건 직접 반복 + 수백 건 간접)
2. 2 epoch의 underfitting으로 EOS 생성 신뢰도 부족
3. OpenOrca 과잉 대표로 인한 다양성 결핍
---
## 2. 처음부터 다시 한다면: 구체적 개선 사항
### 2.1 SFT 데이터 파이프라인
| 항목 | 현재 | 재시작 시 |
|------|------|----------|
| 포맷 | `<\|user\|>/<\|assistant\|>` ✅ | 동일 유지 |
| EOS 처리 | 트렁케이션 시 손실 가능 | **코드 이미 수정됨** (`response_ids[-1] = eos_token_id`) |
| Dynamic padding | 미작동 (고정 4096) | **코드 이미 수정됨** (가변 길이 반환) |
| 품질 필터 | 기본 (50자, 30% 한글) | **강화**: 80자, 40% 한글, EOS/Q&A 오염 제거, 5-gram 반복 필터 |
| Val split | 없음 | **5% val split** (prepare_sft_data.py에 이미 구현됨) |
| 가중치 샘플링 | OpenOrca 5.0× | **OpenOrca 2.0×** (이미 수정됨) |
| 예상 데이터 | 159K | **~120-130K** (필터링 후) |
**핵심 변경: `prepare_sft_data.py`를 다시 실행하면 된다.** 코드에 이미 enhanced filter와 수정된 가중치가 반영되어 있다.
### 2.2 학습 하이퍼파라미터
| 파라미터 | 현재 | 재시작 시 | 근거 |
|---------|------|----------|------|
| max_steps | 5,000 (~2 epoch) | **7,500-10,000** (3-4 epoch) | 업계 표준 3-5 epoch |
| lr | 2e-5 | **2e-5** 유지 | 업계 표준, loss curve 안정 |
| warmup | 150 (3%) | **225-300** (3%) | steps 증가에 비례 |
| NEFTune alpha | 10.0 | **10.0** 유지 | 159K 데이터에 적합 |
| val_data | 없음 | **val.jsonl** 전달 | 과적합 모니터링 |
| save_interval | 500 | **500** 유지 | best checkpoint 선택 가능 |
### 2.3 추가 고려사항
- **`<|user|>` / `<|assistant|>` 특수 토큰 등록**: 현재 서브워드 분할됨. 단일 토큰으로 등록하면 더 robust하나 base model 재학습 필요 → **SFT에서는 현행 유지, 3B에서 반영**
- **Repetition penalty loss (Unlikelihood Training)**: 중기 옵션. 재시작 1차에는 데이터 품질 개선만으로 충분할 것
---
## 3. 업계 최고 수준 SFT 파이프라인 비교
### 3.1 주요 프레임워크 비교
| 기능 | 현 프로젝트 (수정 후) | LLaMA-Factory | TRL SFTTrainer | Axolotl |
|------|---------------------|---------------|----------------|---------|
| Completion-only loss | ✅ (labels=-1) | ✅ | ✅ (DataCollator) | ✅ |
| Dynamic padding | ✅ (수정됨) | ✅ | ✅ | ✅ |
| Sample packing | ❌ | ✅ | ✅ (`packing=True`) | ✅ |
| EOS 보장 | ✅ (수정됨) | ✅ | ✅ | ✅ |
| Val monitoring | ✅ (구현됨) | ✅ | ✅ | ✅ |
| Flash Attention | ✅ (64-align) | ✅ | ✅ | ✅ |
| NEFTune | ✅ | ✅ | ✅ | ✅ |
### 3.2 `packing=True` + `completion_only_loss` 분석
**Sample Packing**: 여러 짧은 샘플을 하나의 시퀀스에 연결하여 패딩 완전 제거.
```
Before packing (dynamic padding):
[sample1 (200 tok)] [pad pad pad ... (312 pad)] = 512 total
[sample2 (480 tok)] [pad pad pad ... (32 pad)] = 512 total
After packing:
[sample1 (200 tok)][sample2 (480 tok)][pad ... (344)] = 1024 total
→ 2 samples in 1 sequence, less padding waste
```
**현 프로젝트 적용 가능성:**
- 평균 시퀀스 ~500 토큰이므로 packing 효과 **매우 큼** (4096 대비 88% 절약 → packing으로 추가 20-30% 절약)
- 그러나 구현 복잡도 높음: attention mask에 sample boundary 처리 필요
- **권장: 현재 dynamic padding만으로도 충분한 개선. Packing은 3B 또는 TRL 전환 시 도입.**
### 3.3 현 프로젝트에 바로 적용 가능한 것
1.**이미 적용됨**: Dynamic padding, EOS 보장, completion-only loss, NEFTune
2. 🟡 **미적용이나 중요도 낮음**: Sample packing (구현 복잡, 현재 효율 충분)
3. 🟡 **미적용이나 고려 가치**: TRL SFTTrainer 전환 (커스텀 LLM 클래스 호환성 확인 필요)
---
## 4. 3B 모델로의 전환 타이밍
### 4.1 1B 재학습 vs 바로 3B
| 기준 | 1B 재학습 | 바로 3B |
|------|----------|---------|
| 소요 시간 | ~40분 SFT | ~26시간 pretrain + ~2시간 SFT |
| 리스크 | 낮음 (검증된 파이프라인) | 중간 (새 아키텍처 설정 필요) |
| 기대 품질 | 반복률 17.7% → **5-8%** 예상 | 반복률 **2-5%** 예상 |
| ko_ifeval | 20-30% 예상 | 35-45% 예상 |
| 학습 검증 | 즉시 가능 | 26시간 후에야 확인 가능 |
### 4.2 Chinchilla Scaling Law 분석
```
Chinchilla 최적 학습 데이터 = 20 × 파라미터 수
1B 모델: 20 × 1B = 20B tokens (현재 ~8.91B → 부족하지만 SFT에는 충분)
3B 모델: 20 × 3B = 60B tokens (현재 데이터 ~150B → 충분)
70 × 3B = 210B tokens (최적 → 150B로 71% 수준)
```
**현재 150B tokens 데이터는 3B 학습에 충분하다** (Chinchilla 최소 기준의 2.5배).
### 4.3 3B가 반복 퇴화를 구조적으로 덜 겪는가?
**예, 스케일 효과가 있다.** 근거:
1. **Representation capacity**: 3B는 1B 대비 ~2.5배 파라미터 → EOS 예측, 반복 회피 등 복잡한 패턴을 더 정확하게 학습
2. **Attention head 수 증가**: 더 많은 head가 "이전에 말한 것" 추적에 전용 가능
3. **경험적 증거**: Open Ko-LLM 리더보드에서 3B 모델들은 1B 대비 일관되게 반복률 낮음
4. **같은 SFT 데이터라도 3B가 더 잘 일반화**: 더 큰 모델이 same data에서 더 많은 패턴 추출
### 4.4 권장: **1B 재학습 먼저, 3B 병렬 준비**
```
Day 0: 데이터 재준비 (30분) + 1B SFT 재학습 (40분) = 오늘 완료
Day 0: 결과 평가 (30분) → 1B 기준선 확보
Day 1-2: 3B 아키텍처 설정 + pretrain 시작 (26시간)
Day 2-3: 3B SFT (2시간) + 평가
```
**이유:**
- 1B 재학습은 비용이 너무 낮다 (40분). 안 할 이유가 없다.
- 1B 결과로 파이프라인 검증 → 3B에 동일한 (검증된) 파이프라인 적용
- 3B pretrain 동안 1B 모델을 배포/데모에 사용 가능
---
## 5. "다시 시작"의 타임라인
### 5.1 상세 타임라인
| 단계 | 작업 | 소요 시간 | 누적 |
|------|------|----------|------|
| **A. 데이터 재준비** | `prepare_sft_data.py` 재실행 (강화 필터 적용) | **20-30분** | 30분 |
| **B. 1B SFT 재학습** | 7500 steps, 8×B200, dynamic padding 적용 | **30-40분** | 1시간 |
| **C. 1B 평가** | 반복률 + 생성 품질 + (선택) ko_ifeval | **30분-2시간** | 1.5-3시간 |
| **D. 3B pretrain** | 150B tokens, 8×B200 | **~26시간** | 27-29시간 |
| **E. 3B SFT** | 동일 데이터, 10000 steps | **1.5-2시간** | 29-31시간 |
| **F. 3B 평가** | 전체 벤치마크 | **2-4시간** | 31-35시간 |
### 5.2 현재 고쳐서 가는 시간 vs 재시작
| 경로 | 소요 시간 | 예상 최종 품질 |
|------|----------|---------------|
| **경로 A: 현재 모델에서 추가 학습** | 추가 SFT 40분 + 평가 2시간 = ~3시간 | 반복률 12-15%, 잔여 오염 |
| **경로 B: 1B 클린 재학습** | 데이터 30분 + SFT 40분 + 평가 2시간 = **~3시간** | 반복률 **5-8%**, 오염 없음 |
| **경로 C: 3B 처음부터** | 데이터 30분 + pretrain 26시간 + SFT 2시간 + 평가 4시간 = **~33시간** | 반복률 **2-5%**, ko_ifeval 35-45% |
**경로 A와 B의 시간이 거의 같은데, B가 품질이 확실히 높다.** 이것이 재시작을 권장하는 핵심 이유다.
---
## 6. 재시작의 리스크와 예방
### 6.1 "다시 해도 또 새로운 문제가 나올 수 있다"
| 리스크 | 확률 | 예방 방법 |
|--------|------|----------|
| 데이터 파이프라인 새 버그 | 낮음 | 코드 이미 수정/검증됨, 단위 테스트 추가 |
| 과적합 감지 실패 | 낮음 | val split 이번엔 반드시 사용 |
| 새로운 유형의 반복 | 중간 | 다양한 프롬프트로 평가, rep_penalty 보험 |
| 학습 불안정 (loss spike) | 낮음 | 기존 학습에서 안정적이었음, 동일 lr 사용 |
| 데이터 필터 과도 → 데이터 부족 | 낮음 | 120K 여전히 충분 (3-4 epoch에 적합) |
### 6.2 지금까지의 교훈 반영 체크리스트
```
✅ 추론 시 올바른 프롬프트 포맷 (<|user|>/<|assistant|>) 사용
✅ Dynamic padding 실제 작동 확인 (배치별 가변 길이)
✅ 트렁케이션 시 EOS 강제 삽입
✅ EOS 리터럴 / Q&A 마커 오염 데이터 필터링
✅ 가중치 샘플링 정상화 (5.0 → 2.0)
✅ Val split으로 과적합 모니터링
✅ 3-4 epoch 충분히 학습
✅ 평가 시 rep_penalty=1.1 + no_repeat_ngram=3 기본 적용
✅ 다양한 프롬프트 유형으로 종합 평가
```
### 6.3 성공 확률 추정
- **위 체크리스트 100% 반영 시**: 반복률 5-8% 달성 확률 **85-90%**
- **기존 대비 개선**: 반복률 17.7% → 5-8% (55-70% 감소)
- **실패 시나리오**: 반복률이 10-15%에 머무는 경우 → 추가 대응 (ORPO/DPO)
---
## 7. 최종 결론 및 권장
### 7.1 "다시 시작"이 필요한 근본적 이유
**필요하다.** 이유:
1. **비용이 거의 없다** — 1B SFT 재학습은 40분. 기존 모델에서 추가 학습하는 시간과 동일.
2. **오염된 가중치 위에 쌓는 것은 비효율적** — OpenOrca 5배 업샘플링 + Q/A 마커 오염의 흔적이 남아있는 상태에서 추가 학습하면, 새 gradient가 오래된 오염을 완전히 덮지 못함.
3. **모든 수정 사항이 이미 코드에 반영됨** — sft_dataset.py (dynamic padding, EOS 보장), prepare_sft_data.py (강화 필터, 가중치 수정) 모두 수정 완료. 실행만 하면 됨.
4. **깨끗한 기준선이 필요** — 3B로 스케일업하기 전에, 깨끗한 1B 결과가 있어야 파이프라인이 올바른지 검증 가능.
### 7.2 다시 시작 시 예상 최종 품질
| 지표 | 현재 (수정 추론) | 1B 재학습 예상 | 3B 재학습 예상 |
|------|-----------------|---------------|---------------|
| 반복률 (3-gram) | 17.7% | **5-8%** | **2-5%** |
| 반복률 (rep_penalty 없이) | ~30% | **10-15%** | **5-10%** |
| EOS 정상 종료율 | ~60% | **85-90%** | **90-95%** |
| ko_ifeval (추정) | 15-25% | **20-30%** | **35-45%** |
| ko_winogrande (추정) | 50-55% | **53-58%** | **60-68%** |
| 한국어 답변 자연스러움 | 중간 | **중상** | **상** |
### 7.3 타임라인
```
[오늘 — 3시간]
├── 데이터 재준비: prepare_sft_data.py 재실행 (30분)
├── 1B SFT 재학습: 7500 steps (40분)
└── 평가: 반복률 + 생성 품질 (30분-2시간)
[내일-모레 — 30시간]
├── 3B pretrain (26시간, 백그라운드)
├── 3B SFT (2시간)
└── 3B 전체 평가 (2-4시간)
```
### 7.4 최종 권장
| 권장 | 근거 |
|------|------|
| ✅ **1B SFT 즉시 재학습** | 40분 투자, 반복률 17.7% → 5-8% 예상, 리스크 극히 낮음 |
| ✅ **3B pretrain 병렬 시작** | 1B 재학습 결과로 파이프라인 검증 후 동일 파이프라인 적용 |
| ❌ **현재 가중치에서 추가 학습** | 같은 시간으로 더 낮은 품질. 오염 잔류 위험. |
**한 줄 요약: 40분이면 깨끗한 모델을 얻을 수 있는데, 오염된 모델에 40분을 더 쓸 이유가 없다.**
---
## 부록: 재학습 실행 명령어
```bash
# Step 1: 데이터 재준비 (강화 필터 + 수정된 가중치 적용)
cd /PROJECT/0325120031_A/ghong/taketimes/llm-bang
python data/prepare_sft_data.py --output_dir data/sft_v2/ --val_split 0.05
# Step 2: 1B SFT 재학습
torchrun --nproc_per_node=8 train/sft.py \
--base_checkpoint checkpoints/korean_1b_fp8_run1/checkpoint-0034000 \
--sft_data data/sft_v2/train.jsonl \
--val_data data/sft_v2/val.jsonl \
--checkpoint_dir checkpoints/korean_1b_sft_v2 \
--max_steps 7500 \
--batch_size 4 \
--grad_accum 2 \
--lr 2e-5 \
--warmup_steps 225 \
--use_fp8
# Step 3: 평가
python eval/test_generation_params.py \
--checkpoint checkpoints/korean_1b_sft_v2/checkpoint-0007500
```