> EulerForge > 튜토리얼 > 17. 스크래치 사전훈련

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은 전체 파라미터 훈련이므로, 다음 키가 있으면 검증 에러가 발생합니다:


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 미만이면 버림)

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 설정 검증만, 훈련 없음

관련 문서