17. 스크래치 사전훈련
EulerStack 등 외부 도구가 HuggingFace 형식으로 조립/export한 모델을 raw text 데이터로 스크래치 사전훈련하는 방법을 설명합니다.
1. pretrain vs train
| 항목 | eulerforge train (파인튜닝) |
eulerforge pretrain (스크래치) |
|---|---|---|
| 모델 | 기존 HF 모델 (가중치 있음) | 새로 조립된 모델 (초기화된 가중치) |
| 학습 방식 | LoRA/MoE 인젝션 + 페이즈 스케줄 | 전체 파라미터 causal LM 훈련 |
| 데이터 | instruction/preference JSONL | raw text (packed chunking) |
| 인젝션 | dense_lora, mixture_lora 등 | 없음 (금지) |
| 용도 | 기존 모델 적응 | 모델 아키텍처 검증 + 기초 언어 능력 학습 |
2. 전체 흐름
EulerStack (모델 조립) EulerForge (훈련)
────────────────── ──────────────────
YAML 스펙
↓ compile + export
HF model_dir ──────────────→ eulerforge pretrain
(config.json + ↓
model.safetensors + 사전훈련 완료
modeling_*.py) ↓
final/ (HF save_pretrained)
↓
eulerforge train (LoRA 파인튜닝)
3. 사전 준비
3.1 EulerStack 모델
EulerStack이 HuggingFace 형식으로 export한 모델 디렉토리가 필요합니다.
/path/to/eulerstack/outputs/full_hybrid_moe/
├── config.json # HF config (model_type: eulerstack)
├── configuration_eulerstack.py # 커스텀 config 클래스
├── modeling_eulerstack.py # 커스텀 모델 클래스
├── model.safetensors # 모델 가중치
└── generation_config.json
참고:
model_type: eulerstack인 커스텀 모델이므로trust_remote_code: true가 필요합니다. 어떤 형태의 EulerStack hybrid 모델이든 (pure attention, mamba hybrid, tri-mixer, MoE 등) 모두 지원됩니다.
3.2 데이터
raw text JSONL 파일이 필요합니다. 각 행에 text 키가 있어야 합니다.
{"text": "LABOR'S MARTYRS\n\nHaymarket\n1887\n\nSacco and Vanzetti..."}
{"text": "THROUGH THE WALL\n\nBY CLEVELAND MOFFETT..."}
이 튜토리얼에서는 data/dolma_10k.jsonl (10,000행, Dolma 데이터셋)을 사용합니다.
3.3 토크나이저
모델 디렉토리에 토크나이저 파일이 없으면, 프리셋에서 별도 지정합니다. EulerStack 모델의 config.json에 토크나이저 정보가 명시되어 있습니다.
"tokenizer": {"type": "hf", "pretrained": "gpt2", "add_bos": true, "add_eos": true}
→ 프리셋에서 tokenizer: "gpt2"로 지정합니다.
4. 프리셋 작성
configs/presets/pretrain/eulerstack_hybrid_moe.yml:
# ── 디바이스 ──
device: "cuda:0" # cuda:0, cuda:1, cpu
# ── 모델 ──
model_dir: "outputs/full_hybrid_moe"
trust_remote_code: true
# ── 토크나이저 ──
tokenizer: "gpt2"
# ── 데이터 ──
data:
path: "data/dolma_10k.jsonl"
text_column: "text"
max_length: 1024
packing: true # packed chunking
# ── 훈련 ──
training:
max_steps: 500
batch_size: 2
grad_accum_steps: 4 # 유효 배치 = 2 × 4 = 8
lr: 3.0e-4
weight_decay: 0.1
warmup_steps: 50
max_grad_norm: 1.0
log_steps: 10
save_steps: 250
dtype: "float32" # Hybrid 모델(Hyena/RetNet FFT)은 float32 필수
amp: false # FFT 연산이 bf16 미지원 → AMP 비활성화
seed: 42
프리셋 키 설명
| 키 | 설명 | 필수 |
|---|---|---|
device |
훈련 디바이스 (cuda:0, cuda:1, cpu) |
기본: cuda |
model_dir |
HF 모델 디렉토리 경로 | 필수 |
trust_remote_code |
커스텀 모델 클래스 허용 | EulerStack 모델은 true |
tokenizer |
HF 토크나이저 이름 또는 경로 | model_dir에 없으면 필수 |
data.path |
raw text JSONL 경로 | 필수 |
data.text_column |
JSONL의 텍스트 키 | 필수 (기본: text) |
data.max_length |
시퀀스 최대 길이 | 기본: 2048 |
data.packing |
packed chunking 사용 | 기본: true |
training.max_steps |
최대 훈련 스텝 | 필수 |
training.batch_size |
배치 크기 | 기본: 2 |
training.grad_accum_steps |
gradient accumulation | 기본: 1 |
training.lr |
학습률 | 기본: 3e-4 |
training.dtype |
모델 로드 + 훈련 정밀도 | 기본: bfloat16 |
training.amp |
AMP 활성 여부 | 기본: dtype에 따라 자동 |
dtype과 amp 선택 가이드
| 모델 유형 | dtype |
amp |
이유 |
|---|---|---|---|
| 순수 Attention (simple) | bfloat16 |
true (기본) |
bf16 AMP로 메모리/속도 이점 |
| Hybrid (Mamba/Hyena/RetNet) | float32 |
false |
FFT 연산이 bf16 미지원 |
| MoE + Attention | bfloat16 |
true (기본) |
MoE routing은 bf16 호환 |
| MoE + Hybrid | float32 |
false |
Hyena/RetNet FFT 포함 |
핵심:
torch.fft.rfft는 bfloat16을 지원하지 않습니다. EulerStack의 Hyena, RetNet 블록이 포함된 모델은 반드시dtype: float32+amp: false로 설정하세요.
금지 키
pretrain은 전체 파라미터 훈련이므로, 다음 키가 있으면 검증 에러가 발생합니다:
injection— LoRA/MoE 인젝션은eulerforge train전용moe— MoE 보조 손실 설정은eulerforge train전용backbone— 백본 어댑터는eulerforge train전용
5. 실행
5.1 설정 검증
eulerforge pretrain --preset configs/presets/pretrain/eulerstack_hybrid_moe.yml --validate-only
출력:
[Pretrain] Config validation passed.
[Pretrain] model_dir: /path/to/eulerstack/outputs/full_hybrid_moe
[Pretrain] data.path: data/dolma_10k.jsonl
[Pretrain] training.max_steps: 500
5.2 훈련 실행
eulerforge pretrain --preset configs/presets/pretrain/eulerstack_hybrid_moe.yml
출력 예시:
[Pretrain] Device: cuda
[Pretrain] Loading model from /path/to/eulerstack/outputs/full_hybrid_moe
[Pretrain] Model loaded: 1,932,345,344 params, 1,932,345,344 trainable, dtype=torch.bfloat16
[Pretrain] Tokenizer: gpt2 (vocab=50257)
[Pretrain] Loaded 10000 texts from data/dolma_10k.jsonl
[Pretrain] Packed: 4,521,600 tokens → 2,207 chunks (max_length=2048)
[Pretrain] Starting training: max_steps=500, batch_size=2, grad_accum=4, lr=0.0003, warmup=50
[Pretrain] step=10/500 | loss=10.4523 | lr=6.00e-05 | 0.42 steps/s
[Pretrain] step=20/500 | loss=9.8712 | lr=1.20e-04 | 0.43 steps/s
...
[Pretrain] step=250/500 | loss=6.1234 | lr=2.85e-04 | 0.44 steps/s
[Pretrain] Checkpoint saved: outputs/pretrain_20260327_143000/checkpoint-250
...
[Pretrain] step=500/500 | loss=5.4321 | lr=0.00e+00 | 0.44 steps/s
[Pretrain] Training complete. 500 steps in 1187.3s. Final model saved to outputs/pretrain_20260327_143000/final
5.3 설정 오버라이드
# 학습률 변경
eulerforge pretrain --preset ... --set training.lr=1e-4
# 더 많은 스텝
eulerforge pretrain --preset ... --set training.max_steps=2000
# 출력 디렉토리 지정
eulerforge pretrain --preset ... --output-dir outputs/my_pretrain
# 여러 오버라이드 조합
eulerforge pretrain --preset ... \
--set training.max_steps=1000 \
--set training.lr=1e-4 \
--set data.max_length=1024
6. 출력 구조
outputs/pretrain_20260327_143000/
├── pretrain_config.json # 사용된 설정 스냅샷
├── metrics.jsonl # 스텝별 loss, lr, 경과 시간
├── checkpoint-250/ # 중간 체크포인트
│ ├── config.json
│ ├── model.safetensors
│ ├── tokenizer.json
│ └── tokenizer_config.json
└── final/ # 최종 모델
├── config.json
├── model.safetensors
├── tokenizer.json
└── tokenizer_config.json
metrics.jsonl 형식
{"step": 10, "loss": 10.4523, "lr": 6e-05, "elapsed_sec": 23.8}
{"step": 20, "loss": 9.8712, "lr": 0.00012, "elapsed_sec": 47.1}
7. Packed Chunking
pretrain의 데이터 처리는 파인튜닝과 다릅니다. raw text를 연결하여 고정 길이로 분할합니다.
텍스트 1: "Hello world. This is a test."
텍스트 2: "Another document with more content."
텍스트 3: "Third piece of text..."
↓ 토큰화 + EOS 삽입 + 연결
[tok1, tok2, ..., EOS, tok1, tok2, ..., EOS, tok1, tok2, ..., EOS]
↓ max_length=2048 단위로 분할
청크 1: [tok1, tok2, ..., tok2048] ← labels = input_ids (causal LM)
청크 2: [tok2049, tok2050, ..., tok4096]
청크 3: ...
(나머지 토큰이 max_length 미만이면 버림)
- 패딩 없음: 모든 토큰이 유효한 학습 신호
- EOS 삽입: 문서 경계를 구분
- 나머지 버림: 마지막 불완전 청크는 사용하지 않음
packing: false로 설정하면 개별 텍스트별 토큰화 + 패딩/잘림 방식을 사용합니다.
8. 훈련 후 파인튜닝
pretrain 완료 후 final/ 디렉토리를 eulerforge train의 모델로 사용할 수 있습니다.
# configs/presets/finetune_after_pretrain.yml
device: cuda:0
backbone: qwen3 # 또는 적절한 백본
model_name: "outputs/pretrain_20260327_143000/final"
injection:
strategy: dense_lora
lora_r: 32
lora_alpha: 64
target_keywords: ["gate_proj", "up_proj", "down_proj"]
attn_lora:
enabled: true
keywords: ["q_proj", "v_proj"]
training:
type: sft
phases:
- step: 0
trainable: ["lora", "attn_lora"]
lr: 1.0e-5
max_train_steps: 5000
eulerforge train --preset configs/presets/finetune_after_pretrain.yml \
--set data.path=data/sft_10k_raw.jsonl \
--set data.format=raw \
--set data.task=sft
참고: EulerStack 커스텀 모델(
model_type: eulerstack)은 현재eulerforge train의 BackboneAdapter와 직접 호환되지 않을 수 있습니다. 이 경우 pretrain 완료 모델을 표준 HF 형식으로 변환하거나, 별도 백본 어댑터를 추가해야 합니다.
9. 주의사항
Vocab Size 불일치 (자동 처리)
EulerStack 모델의 vocab_size와 토크나이저의 vocab_size가 다를 수 있습니다. 예를 들어:
- 모델: vocab_size=32000 (EulerStack 스펙에 정의)
- 토크나이저: vocab_size=50257 (GPT-2)
토크나이저 vocab이 모델 vocab보다 크면, 토큰 ID가 embedding 테이블 범위를 초과하여 CUDA index out of bounds 에러가 발생합니다.
pretrain은 이를 자동으로 처리합니다: 토크나이저 vocab > 모델 vocab이면 model.resize_token_embeddings()로 embedding을 확장합니다. 스크래치 훈련이므로 새로 추가된 embedding 행은 랜덤 초기화되어 정상 학습됩니다.
[Pretrain] Tokenizer vocab (50257) > model vocab (32000). Resizing model embeddings to 50257.
Position IDs (자동 처리)
일부 커스텀 모델(EulerStack의 RetNet 등)은 내부에서 position_ids를 .view()로 변환할 때, 텐서가 non-contiguous이면 RuntimeError: view size is not compatible 에러가 발생합니다.
pretrain은 이를 자동으로 처리합니다: 매 forward 호출 시 contiguous한 position_ids를 명시적으로 생성하여 모델에 전달합니다.
GPU 메모리
스크래치 사전훈련은 전체 파라미터를 학습하므로 메모리 사용량이 큽니다. LoRA 파인튜닝보다 훨씬 많은 GPU 메모리가 필요합니다.
| 모델 크기 | 예상 GPU 메모리 (bf16, batch=2, accum=4) |
|---|---|
| ~0.8B | ~8 GB |
| ~2B | ~16 GB |
| ~4B+ | 단일 GPU에서 어려움 — batch_size=1, grad_accum 증가 권장 |
학습률
스크래치 사전훈련은 파인튜닝보다 높은 학습률을 사용합니다.
| 훈련 방식 | 일반적 학습률 범위 |
|---|---|
| LoRA 파인튜닝 | 1e-5 ~ 5e-5 |
| 스크래치 pretrain | 1e-4 ~ 6e-4 |
데이터 양
10k 행은 아키텍처 검증용으로 적합하지만, 실제 사전훈련에는 수십만~수백만 행이 필요합니다.
10. CLI 옵션
| 옵션 | 설명 |
|---|---|
--preset PATH |
pretrain YAML 프리셋 경로 (필수) |
--set KEY=VALUE |
설정 오버라이드 (반복 가능) |
--output-dir DIR |
출력 디렉토리 |
--validate-only |
설정 검증만, 훈련 없음 |
관련 문서
- CLI 레퍼런스 — pretrain 섹션
- EulerStack 문서 — 모델 조립 도구