> EulerForge > 튜토리얼 > 6. ORPO 훈련

6. ORPO 훈련

개요

ORPO는 DPO의 대안으로, reference model 없이 preference 학습을 수행합니다. SFT loss와 ORPO loss를 결합하여 단일 forward pass로 chosen/rejected 선호도를 학습합니다.

장점: Reference model forward가 없으므로 DPO보다 메모리 효율적 손실 함수: Loss = SFT_loss + λ * ORPO_loss

중요: SFT Loss는 chosen만 사용

ORPO의 SFT loss는 chosen 응답에 대한 NLL(Negative Log-Likelihood)만 계산합니다. rejected 응답은 SFT 목표에 포함되지 않습니다. 이는 ORPO 원논문의 설계를 따른 것으로, rejected를 SFT로 학습하면 나쁜 응답도 생성하도록 학습되기 때문입니다.

SFT를 먼저 해야 하는 이유

중요: ORPO를 base 모델에 직접 적용하면 벤치 점수가 오히려 하락할 수 있습니다.

ORPO는 SFT와 preference를 동시에 학습하지만, base 모델(pretrain만 된 상태)은 instruction-following 능력이 없습니다. 8~10K 수준의 데이터로 ORPO의 SFT 항만으로는 기초 능력이 충분히 형성되지 않아, 모델이 "어떻게 대답해야 하는지"를 모르는 상태에서 "어떤 대답이 더 나은지"만 학습하게 됩니다.

올바른 순서: SFT (instruction 학습, 5000+ steps) → ORPO (선호 정렬, 2000+ steps) 위험한 순서: Base Model → ORPO (소규모 데이터)

ORPO 단독 적용은 50K+ 고품질 preference 데이터가 있을 때만 고려하세요 (원논문: 60K+). SFT를 먼저 진행하고, 그 체크포인트(final/)를 ORPO의 model_name으로 지정하세요.

```bash

Step 1: SFT 먼저

eulerforge train --preset configs/presets/qwen3.5_0.8b_dense_lora_sft.yml \ --set data.format=raw --set data.task=sft \ --set data.path=data/sft_10k_raw.jsonl

Step 2: ORPO (SFT 완료 모델 기반)

eulerforge train --preset configs/presets/qwen3.5_0.8b_dense_lora_orpo.yml \ --set model_name=outputs/sft_run/final \ --set data.format=raw --set data.task=preference \ --set data.path=data/dpo_10k_raw.jsonl ```

orpo_lambda 선택 가이드

상황 권장 orpo_lambda 이유
SFT 후 ORPO + 소규모 데이터 0.1~0.3 SFT 유지 우선, preference는 보조
SFT 후 ORPO + 중규모 데이터 0.3~0.5 SFT와 선호 균형
ORPO 단독 + 대규모 데이터(50K+) 0.5~1.0 SFT 겸 학습

사전 요구 사항

데이터 포맷

Raw 데이터 (권장)

data/dpo_10k_raw.jsonl은 표준 prompted_preference 형식으로 변환된 데이터입니다:

{"prompt": "질문 내용", "chosen": "선호 응답", "rejected": "비선호 응답"}

data.format=raw를 사용하면 훈련 시 자동 토큰화됩니다.

프리셋

# configs/presets/qwen3.5_0.8b_dense_lora_orpo.yml
training:
  type: orpo
  orpo_lambda: 1.0         # ORPO 항 가중치 (필수, 양수)
  phases:
    - step: 0
      trainable: ["lora", "attn_lora"]

실행

eulerforge train --preset configs/presets/qwen3.5_0.8b_dense_lora_orpo.yml \
    --set data.format=raw \
    --set data.task=prompted_preference \
    --set data.path=data/dpo_10k_raw.jsonl \
    --set data.max_length=256

주요 파라미터

파라미터 설명 기본값
orpo_lambda ORPO 항 가중치 필수 (권장: 1.0)

orpo_lambda가 클수록 선호도 학습이 강해지고, 작을수록 SFT에 가까워집니다.

메트릭

메트릭 설명 정상 범위
train/sft_loss Cross-entropy SFT 손실 1.5~4.0
train/orpo_loss ORPO odds-ratio 손실 0~3.0
train/total_loss sft_loss + λ * orpo_loss 2~7.0

참고: ORPO loss는 토큰당 평균 log-probability를 사용합니다. 시퀀스 합산 log-prob을 사용하면 odds ratio가 수치적으로 폭발할 수 있습니다.

알려진 문제

NaN loss (모든 스텝)

prompted_preference 전처리에서 max_length 절단으로 응답 토큰이 0개인 행이 생성될 수 있습니다. 이 행은 HuggingFace SFT loss가 NaN을 반환하고, NaN 그래디언트가 모델 가중치를 오염시킵니다.

EulerForge는 ProcessedDPODataset 로드 시 자동으로 이런 행을 필터링합니다:

[DPODataset] Filtered N rows with empty labels (response truncated to 0 tokens).

이 경고가 출력되면 정상 동작입니다. 데이터 재생성 없이 훈련이 계속됩니다.

→ 자세한 내용: 2026-03-orpo-nan-loss-empty-labels.md