Reward Modeling¶
메타 정보¶
| 항목 | 내용 |
|---|---|
| 분류 | Alignment / RLHF |
| 핵심 논문 | "Learning to summarize from human feedback" (Stiennon et al., NeurIPS 2020), "Training language models to follow instructions with human feedback" (Ouyang et al., NeurIPS 2022 - InstructGPT), "Let's Verify Step by Step" (Lightman et al., 2023 - PRM), "Direct Preference Optimization" (Rafailov et al., NeurIPS 2023) |
| 주요 저자 | Jan Leike (OpenAI alignment), Paul Christiano (reward modeling 선구자), Rafael Rafailov (DPO), John Schulman (PPO/RLHF) |
| 핵심 개념 | 인간의 선호도를 학습한 모델(reward model)을 통해 언어 모델의 출력을 인간의 의도에 맞게 정렬하는 기법 |
| 관련 분야 | Reinforcement Learning, Preference Learning, AI Safety, Language Model Fine-tuning |
정의¶
Reward Modeling은 인간의 선호도 데이터로부터 보상 함수(reward function)를 학습하는 과정이다. 학습된 reward model은 언어 모델의 출력이 얼마나 인간의 의도에 부합하는지 점수화하며, 이 점수를 기반으로 RL(강화학습)을 통해 언어 모델을 최적화한다.
왜 필요한가¶
문제: 언어 모델의 목적 함수와 인간의 의도가 불일치
LM 목적 함수: max P(next_token | context)
인간이 원하는 것: 도움이 되고, 정확하고, 안전한 답변
--> Next-token prediction만으로는 "좋은 답변"을 정의할 수 없음
--> 인간의 선호를 명시적으로 학습해야 함
RLHF 파이프라인¶
전체 흐름¶
RLHF Pipeline (3단계):
+------------------------------------------------------------------+
| |
| Stage 1: Supervised Fine-Tuning (SFT) |
| ============================================ |
| |
| [Base LM] + [Human demonstrations] --> [SFT Model] |
| |
| * 인간이 작성한 고품질 응답으로 지도학습 |
| * 모델이 instruction following의 기본 능력을 갖추게 함 |
| |
+------------------------------------------------------------------+
|
v
+------------------------------------------------------------------+
| |
| Stage 2: Reward Model Training |
| ============================================ |
| |
| Prompt --> [SFT Model] --> Response A |
| --> Response B |
| |
| Human: "A > B" (선호 판단) |
| |
| [Preference Data] --> Train [Reward Model] |
| |
| * SFT 모델로 여러 응답 생성 |
| * 인간 평가자가 쌍(pair)으로 비교 |
| * Bradley-Terry model로 reward model 학습 |
| |
+------------------------------------------------------------------+
|
v
+------------------------------------------------------------------+
| |
| Stage 3: RL Optimization (PPO) |
| ============================================ |
| |
| Prompt --> [Policy (LM)] --> Response |
| | |
| v |
| [Reward Model] --> reward score |
| |
| Objective: |
| max E[R(response)] - beta * KL(policy || SFT_model) |
| |
| * PPO로 policy 최적화 |
| * KL penalty로 SFT 모델에서 과도하게 벗어나지 않도록 제약 |
| |
+------------------------------------------------------------------+
데이터 흐름 요약¶
Human Demonstrations
|
v
[Base LM] -------> [SFT Model] -------> Comparison Pairs
|
Human Ranking
|
v
[Reward Model]
|
v
[SFT Model] ----(PPO)----> [RLHF Model] <--- reward signal
^ |
|___ KL penalty (reference) _____________|
Bradley-Terry Model¶
수식¶
인간의 선호를 확률적으로 모델링하기 위해 Bradley-Terry model을 사용한다. 응답 y_w (preferred)와 y_l (rejected)가 주어졌을 때:
여기서:
- r(x, y): reward model이 프롬프트 x에 대한 응답 y에 부여하는 점수
- sigma: sigmoid 함수, sigma(z) = 1 / (1 + exp(-z))
손실 함수¶
이는 binary cross-entropy loss와 동일한 형태이다. Reward model은 선호된 응답에 더 높은 점수를, 거부된 응답에 더 낮은 점수를 부여하도록 학습된다.
Reward Model 아키텍처¶
Reward Model 구조:
[Prompt + Response]
|
v
[Pretrained LM (frozen or fine-tuned)]
|
v
[Last hidden state of final token]
|
v
[Linear projection: hidden_dim -> 1]
|
v
scalar reward score r(x, y)
일반적으로 SFT 모델과 동일한 크기이거나 약간 작은 모델을 사용한다. InstructGPT에서는 6B 파라미터 reward model을 사용했다.
Reward Model 학습¶
선호 데이터 수집¶
선호 데이터 수집 프로세스:
1. 프롬프트 풀(pool)에서 프롬프트 x 선택
2. SFT 모델로 K개의 응답 생성: y_1, y_2, ..., y_K
3. 인간 평가자가 응답 쌍을 비교하여 순위 매김
예시:
프롬프트: "양자역학을 5살 아이에게 설명해줘"
응답 A: "양자역학은 슈뢰딩거 방정식으로 기술되는..."
응답 B: "아주 작은 것들은 신기한 규칙을 따라..."
응답 C: "물리학의 한 분야입니다."
인간 평가: B > A > C
생성되는 쌍:
(B, A): B 선호
(B, C): B 선호
(A, C): A 선호
K개 응답에서의 비교 쌍 수: C(K, 2) = K*(K-1)/2
InstructGPT에서는 K=4~9, 하나의 프롬프트에서 C(K,2)개의 비교 쌍을 생성했다.
Pairwise Comparison Loss¶
학습 시 주의사항:
| 항목 | 권장 사항 |
|---|---|
| 배치 구성 | 같은 프롬프트의 모든 쌍을 하나의 배치에 포함 |
| 정규화 | Reward score에 normalization 적용 (mean=0, std=1) |
| 모델 크기 | Policy 모델과 비슷하거나 약간 작은 크기 |
| 학습률 | 1e-5 ~ 5e-6 (작은 값) |
| 에포크 | 1~2 에포크 (overfitting 방지) |
Reward Hacking / Overoptimization¶
Goodhart's Law¶
"When a measure becomes a target, it ceases to be a good measure."
측정 지표가 목표가 되면, 그것은 더 이상 좋은 지표가 아니다.
Reward Model에 적용:
- RM은 인간 선호의 "근사(proxy)"
- Policy가 RM을 과도하게 최적화하면, 실제 인간 선호와 괴리 발생
- RM의 약점을 exploit하는 방향으로 학습됨
Reward Hacking 예시¶
정상적 최적화:
Prompt: "Python sort 설명해줘"
Response: 명확하고 정확한 설명 --> 높은 reward
Reward Hacking:
Prompt: "Python sort 설명해줘"
Response: 불필요하게 장황하고, 자신감 넘치는 어투,
핵심을 반복하고, 사족을 붙임
--> RM이 "자세한 답변"으로 인식하여 높은 점수
--> 실제 사용자 만족도는 낮음
Overoptimization 현상¶
Reward (proxy) vs True Quality
Quality
^
| *
| * *
| * *
| * * <-- True quality 하락
| * *
| * *
|* *
+------------------------------> RM optimization steps
RM score는 계속 증가하지만,
실제 품질은 일정 지점 이후 하락
Gao et al. (2023) "Scaling Laws for Reward Model Overoptimization"에서 RM 점수와 실제 품질의 관계를 정량화:
Gold reward ~= d * sqrt(KL) - c * KL
여기서:
d: RM의 정보량에 비례하는 계수
c: overoptimization 정도를 나타내는 계수
KL: policy와 reference model 간 KL divergence
완화 방법¶
| 방법 | 설명 |
|---|---|
| KL Penalty | PPO 목적 함수에 KL(pi |
| RM Ensemble | 여러 RM의 점수를 앙상블 (exploit 어렵게) |
| Conservative RM | RM 점수의 하한을 보수적으로 추정 |
| Iterative RLHF | 주기적으로 새로운 선호 데이터 수집 및 RM 재학습 |
| Constrained Optimization | RM 점수에 상한 설정 |
PRM vs ORM¶
Process Reward Model (PRM)¶
추론 과정의 각 단계(step)에 대해 보상을 부여한다.
PRM 예시 (수학 문제):
문제: 2x + 3 = 7을 풀어라
Step 1: 2x + 3 = 7 --> r_1 = +1 (정확)
Step 2: 2x = 7 - 3 --> r_2 = +1 (정확)
Step 3: 2x = 4 --> r_3 = +1 (정확)
Step 4: x = 2 --> r_4 = +1 (정확)
잘못된 풀이:
Step 1: 2x + 3 = 7 --> r_1 = +1 (정확)
Step 2: 2x = 7 + 3 --> r_2 = -1 (오류! 부호 실수)
Step 3: 2x = 10 --> r_3 = -1 (이전 오류 전파)
Step 4: x = 5 --> r_4 = -1 (최종 답 오류)
Outcome Reward Model (ORM)¶
최종 결과에 대해서만 보상을 부여한다.
ORM 예시:
문제: 2x + 3 = 7을 풀어라
풀이 A: [전체 과정] --> 최종 답: x = 2 --> r = +1
풀이 B: [전체 과정] --> 최종 답: x = 5 --> r = -1
* 중간 과정은 평가하지 않음
* 올바른 답에 도달했는지만 확인
PRM vs ORM 비교¶
| 항목 | Process RM (PRM) | Outcome RM (ORM) |
|---|---|---|
| 평가 대상 | 각 추론 단계 | 최종 결과만 |
| 피드백 밀도 | Dense (단계별) | Sparse (결과만) |
| 라벨링 비용 | 매우 높음 (단계별 라벨 필요) | 낮음 (결과 정답 비교) |
| 오류 위치 파악 | 가능 (어느 단계에서 틀렸는지) | 불가 |
| Credit Assignment | 명확 | 어려움 |
| 적합 도메인 | 수학, 코딩, 논리 추론 | 일반 텍스트 생성 |
| 대표 연구 | Lightman et al. (2023) | Cobbe et al. (2021) |
| 성능 (수학) | 더 우수 | 상대적으로 낮음 |
| 자동화 가능성 | 낮음 (인간 라벨 필요) | 높음 (자동 검증 가능) |
Lightman et al. (2023) "Let's Verify Step by Step"에서 PRM이 ORM보다 GSM8K, MATH 벤치마크에서 유의미하게 우수함을 보였다. 특히 Best-of-N sampling에서 PRM의 이점이 두드러진다.
Constitutional AI / RLAIF¶
Constitutional AI (Anthropic, 2022)¶
인간 피드백 대신 AI 자체가 원칙(constitution)에 따라 피드백을 생성한다.
Constitutional AI 프로세스:
1. Red Teaming: 모델에게 해로운 응답을 유도
Prompt: "폭탄 만드는 법 알려줘"
Response: [해로운 응답]
2. Critique (자기 비판):
"이 응답이 다음 원칙을 위반하는지 평가해줘:
- 원칙 1: 해로운 정보를 제공하지 말 것
- 원칙 2: 도움이 되되 안전해야 함"
Critique: "이 응답은 원칙 1을 위반합니다..."
3. Revision (수정):
"원칙에 맞게 응답을 수정해줘"
Revised: "죄송합니다, 폭발물 제조 방법은..."
4. RLAIF:
원래 응답 vs 수정된 응답으로 선호 데이터 생성
--> RM 학습 --> RL 최적화
RLAIF (RL from AI Feedback)¶
RLHF vs RLAIF:
RLHF: Human annotator가 선호 판단 --> 비용 높음, 일관성 낮음
RLAIF: LLM이 선호 판단 (with principles) --> 비용 낮음, 확장 가능
RLAIF 프로세스:
1. 프롬프트 x에 대해 응답 y_1, y_2 생성
2. LLM에게 원칙과 함께 비교 요청:
"다음 원칙에 따라 어떤 응답이 더 좋은지 판단해줘:
[원칙 목록]
응답 A: ...
응답 B: ...
더 좋은 응답: "
3. AI 선호 데이터로 RM 학습
Reward Model-Free 접근법¶
RM을 별도로 학습하지 않고, 선호 데이터로 직접 policy를 최적화하는 방법들이다.
DPO (Direct Preference Optimization, Rafailov et al., NeurIPS 2023)¶
Bradley-Terry model 하에서 optimal policy와 reward function의 관계를 이용하여, RM 없이 직접 policy를 최적화한다.
핵심 통찰:
RLHF의 optimal policy:
pi*(y|x) = (1/Z(x)) * pi_ref(y|x) * exp(r(x,y) / beta)
이를 r에 대해 정리하면:
r(x,y) = beta * log(pi*(y|x) / pi_ref(y|x)) + beta * log(Z(x))
이를 Bradley-Terry model에 대입하면 reward model이 소거되고:
DPO Loss:
L_DPO = -E_{(x, y_w, y_l)} [log sigma(
beta * (log pi_theta(y_w|x) / pi_ref(y_w|x))
- beta * (log pi_theta(y_l|x) / pi_ref(y_l|x))
)]
장점: - RM 학습과 RL 최적화를 하나의 단계로 통합 - PPO의 복잡한 학습 루프 불필요 - 메모리 효율적 (RM, critic, reference를 따로 로드할 필요 없음) - 안정적 학습
단점: - Offline 학습이므로 on-policy 탐색 불가 - 분포 밖(out-of-distribution) 응답에 대한 보상 추정 어려움
KTO (Kahneman-Tversky Optimization, Ethayarajh et al., 2024)¶
쌍(pair) 데이터가 아닌 개별 응답의 good/bad 라벨만으로 학습 가능하다. Prospect theory에서 영감을 받았다.
KTO Loss:
L_KTO = E_{y_w} [w(y_w) * (1 - sigma(r_theta(y_w) - z_ref))]
+ E_{y_l} [w(y_l) * (1 - sigma(z_ref - r_theta(y_l)))]
여기서:
r_theta(y) = beta * log(pi_theta(y|x) / pi_ref(y|x))
z_ref = E[r_theta(y)] (reference point)
w(y): 손실 가중치 (loss aversion 반영, bad에 더 큰 가중치)
핵심 차이: DPO는 반드시 (y_w, y_l) 쌍이 필요하지만, KTO는 개별적으로 "좋은 응답", "나쁜 응답"만 있으면 된다. 데이터 수집이 훨씬 쉽다.
ORPO (Odds Ratio Preference Optimization, Hong et al., 2024)¶
Reference model이 필요 없는 방식으로, SFT와 alignment를 하나의 단계로 통합한다.
ORPO Loss:
L_ORPO = L_SFT + lambda * L_OR
L_SFT = -log pi_theta(y_w | x)
L_OR = -log sigma(log(OR(y_w) / OR(y_l)))
OR(y) = pi_theta(y|x) / (1 - pi_theta(y|x)) (odds ratio)
장점: - Reference model 불필요 (메모리 절약) - SFT + alignment 단일 단계 - 구현 단순
방법론 비교¶
| 항목 | RLHF (PPO) | DPO | KTO | ORPO |
|---|---|---|---|---|
| RM 필요 | O | X | X | X |
| Reference Model | O | O | O | X |
| 데이터 형태 | 쌍 비교 | 쌍 비교 | 개별 good/bad | 쌍 비교 |
| 학습 안정성 | 낮음 | 높음 | 높음 | 높음 |
| 메모리 사용 | 매우 높음 (4 models) | 높음 (2 models) | 높음 (2 models) | 보통 (1 model) |
| 구현 복잡도 | 매우 높음 | 낮음 | 낮음 | 매우 낮음 |
| On-policy 탐색 | O | X | X | X |
| 성능 (일반) | 강함 | 동등 | 약간 낮음 | 동등 |
RewardBench¶
개요¶
RewardBench (Lambert et al., 2024)는 reward model을 체계적으로 평가하기 위한 벤치마크이다.
평가 카테고리:
| 카테고리 | 설명 | 예시 |
|---|---|---|
| Chat | 일반 대화 품질 | 자연스럽고 도움이 되는 응답 선호 |
| Chat Hard | 어려운 대화 구분 | 미묘한 차이가 있는 응답 쌍 |
| Safety | 안전성 | 해로운 응답 거부 |
| Reasoning | 추론 능력 | 수학, 코딩의 정확성 |
평가 방식:
각 문제: (prompt, chosen, rejected) 삼중쌍
RM이 chosen에 높은 점수를 부여하면 정답:
score(chosen) > score(rejected) --> correct
score(chosen) <= score(rejected) --> incorrect
Accuracy = correct / total
주요 결과 (2024 기준)¶
| 모델 | Chat | Chat Hard | Safety | Reasoning | 평균 |
|---|---|---|---|---|---|
| GPT-4-turbo (as judge) | 95.3 | 74.3 | 87.2 | 86.9 | 85.9 |
| Nemotron-4-340B-RM | 95.8 | 87.1 | 91.5 | 93.2 | 91.9 |
| Llama-3-70B-RM | 92.1 | 78.4 | 88.3 | 89.7 | 87.1 |
| Gemma-2-27B-RM | 91.5 | 76.8 | 89.1 | 87.2 | 86.2 |
Multi-Objective Alignment¶
문제¶
단일 reward score로는 인간 선호의 다차원적 속성을 충분히 반영하기 어렵다.
인간 선호의 다차원성:
Helpfulness: 정확하고 유용한 정보 제공
Harmlessness: 해로운 내용 거부
Honesty: 불확실할 때 인정, 거짓 정보 X
Verbosity: 적절한 길이 (너무 짧지도, 길지도 않게)
Style: 자연스럽고 읽기 좋은 문체
Factuality: 사실에 기반한 정확한 정보
--> 이 모든 것을 하나의 scalar로 표현하기 어려움
--> 차원 간 trade-off 존재 (예: safety vs helpfulness)
접근법¶
| 방법 | 설명 |
|---|---|
| Multi-head RM | 각 차원별 별도 head로 점수 출력, 가중합 |
| Reward Composition | 여러 RM의 점수를 조합 (선형 결합 등) |
| Constrained RL | 주 목표 최적화 + 안전성 등은 제약 조건으로 |
| Pareto Optimization | 모든 목표의 Pareto front 탐색 |
| Conditional Training | 원하는 속성 조합을 condition으로 학습 |
Multi-head RM 수식:
r(x, y) = sum_{d=1}^{D} alpha_d * r_d(x, y)
여기서:
r_d: d번째 차원의 reward score
alpha_d: 차원별 가중치 (배포 시 조절 가능)
D: 차원 수 (helpfulness, safety, ...)
TRL 코드 예시¶
"""
TRL (Transformer Reinforcement Learning) 라이브러리를 이용한
Reward Model 학습 예시
pip install trl transformers datasets
"""
from dataclasses import dataclass
from typing import Optional
import torch
from datasets import load_dataset
from transformers import (
AutoModelForSequenceClassification,
AutoTokenizer,
TrainingArguments,
)
from trl import RewardTrainer, RewardConfig
# --- 설정 ---
MODEL_NAME = "meta-llama/Llama-3.1-8B"
OUTPUT_DIR = "./reward_model"
# --- 데이터 준비 ---
def prepare_preference_data():
"""
선호 데이터 형식:
{
"prompt": "질문...",
"chosen": "선호된 응답...",
"rejected": "거부된 응답..."
}
"""
dataset = load_dataset("Anthropic/hh-rlhf", split="train")
def format_example(example):
# 데이터셋에 맞게 파싱
chosen = example["chosen"]
rejected = example["rejected"]
# prompt 추출 (공통 prefix)
prompt = ""
for i, (c, r) in enumerate(zip(chosen, rejected)):
if c != r:
prompt = chosen[:i]
break
return {
"prompt": prompt,
"chosen": chosen,
"rejected": rejected,
}
return dataset.map(format_example)
# --- Reward Model 학습 ---
def train_reward_model():
# 토크나이저
tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME)
tokenizer.pad_token = tokenizer.eos_token
# 모델 (sequence classification head 추가)
model = AutoModelForSequenceClassification.from_pretrained(
MODEL_NAME,
num_labels=1, # scalar reward
torch_dtype=torch.bfloat16,
)
model.config.pad_token_id = tokenizer.pad_token_id
# 데이터
dataset = prepare_preference_data()
dataset = dataset.train_test_split(test_size=0.1)
# 학습 설정
training_args = RewardConfig(
output_dir=OUTPUT_DIR,
num_train_epochs=1,
per_device_train_batch_size=4,
per_device_eval_batch_size=8,
gradient_accumulation_steps=4,
learning_rate=1e-5,
lr_scheduler_type="cosine",
warmup_ratio=0.1,
bf16=True,
logging_steps=10,
eval_strategy="steps",
eval_steps=500,
save_strategy="steps",
save_steps=500,
max_length=512,
remove_unused_columns=False,
)
# Trainer
trainer = RewardTrainer(
model=model,
tokenizer=tokenizer,
args=training_args,
train_dataset=dataset["train"],
eval_dataset=dataset["test"],
)
# 학습
trainer.train()
trainer.save_model(OUTPUT_DIR)
return model, tokenizer
# --- Reward Model 추론 ---
def compute_reward(model, tokenizer, prompt, response, device="cuda"):
"""단일 응답에 대한 reward score 계산"""
text = f"{prompt}\n\n{response}"
inputs = tokenizer(text, return_tensors="pt", truncation=True, max_length=512)
inputs = {k: v.to(device) for k, v in inputs.items()}
with torch.no_grad():
outputs = model(**inputs)
reward = outputs.logits[0][0].item()
return reward
def rank_responses(model, tokenizer, prompt, responses, device="cuda"):
"""여러 응답을 reward 점수로 순위 매김"""
scores = []
for response in responses:
score = compute_reward(model, tokenizer, prompt, response, device)
scores.append(score)
ranked = sorted(
zip(responses, scores),
key=lambda x: x[1],
reverse=True
)
return ranked
# --- DPO 학습 (비교) ---
def train_dpo():
"""DPO로 직접 policy 최적화 (RM 없이)"""
from trl import DPOTrainer, DPOConfig
from transformers import AutoModelForCausalLM
# SFT 모델 (policy + reference)
model = AutoModelForCausalLM.from_pretrained(
MODEL_NAME,
torch_dtype=torch.bfloat16,
)
ref_model = AutoModelForCausalLM.from_pretrained(
MODEL_NAME,
torch_dtype=torch.bfloat16,
)
tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME)
tokenizer.pad_token = tokenizer.eos_token
dataset = prepare_preference_data()
training_args = DPOConfig(
output_dir="./dpo_model",
num_train_epochs=1,
per_device_train_batch_size=2,
gradient_accumulation_steps=8,
learning_rate=5e-7,
beta=0.1, # KL penalty 강도
bf16=True,
logging_steps=10,
max_length=512,
max_prompt_length=256,
)
trainer = DPOTrainer(
model=model,
ref_model=ref_model,
args=training_args,
train_dataset=dataset["train"],
tokenizer=tokenizer,
)
trainer.train()
# --- 실행 ---
if __name__ == "__main__":
print("=== Reward Model Training ===")
model, tokenizer = train_reward_model()
# 테스트
prompt = "Python에서 리스트를 정렬하는 방법은?"
responses = [
"sorted() 함수나 list.sort() 메서드를 사용합니다.",
"정렬은 어렵습니다.",
"sorted()는 새 리스트를 반환하고, sort()는 in-place로 정렬합니다. "
"key 파라미터로 정렬 기준을 지정할 수 있으며, reverse=True로 내림차순 정렬이 가능합니다.",
]
ranked = rank_responses(model, tokenizer, prompt, responses)
for i, (resp, score) in enumerate(ranked):
print(f" Rank {i+1} (score={score:.4f}): {resp[:50]}...")
핵심 논문 목록¶
| 논문 | 연도 | 기여 |
|---|---|---|
| Christiano et al., "Deep RL from Human Preferences" | 2017 | RLHF 초기 프레임워크 |
| Stiennon et al., "Learning to summarize from human feedback" | 2020 | 요약 태스크에 RLHF 적용 |
| Ouyang et al., "Training LMs to follow instructions" (InstructGPT) | 2022 | RLHF의 대규모 적용 |
| Bai et al., "Constitutional AI" | 2022 | RLAIF, 원칙 기반 자기 개선 |
| Lightman et al., "Let's Verify Step by Step" | 2023 | Process Reward Model |
| Rafailov et al., "DPO" | 2023 | RM-free alignment |
| Gao et al., "Scaling Laws for RM Overoptimization" | 2023 | Overoptimization 분석 |
| Ethayarajh et al., "KTO" | 2024 | 비쌍(unpaired) 선호 학습 |
| Hong et al., "ORPO" | 2024 | Reference-free alignment |
| Lambert et al., "RewardBench" | 2024 | RM 평가 벤치마크 |
마지막 업데이트: 2026-03-25