選好最適化の派生手法
この章では、異なる目的関数、データの仮定、アーキテクチャ上のトレードオフによってDPOを拡張または置き換える手法群を扱います。それぞれが、標準的なオフラインDPOの特定の制限に対応します。分布シフト(Online DPO)、ペアデータの必要性(KTO)、ノイズの多いラベルへの過適合(IPO)、参照モデルのメモリコスト(ORPO)、学習の複雑さ(Best-of-N)です。
Online DPO
動機
標準DPOの主な制限は、選好データが別のモデル(多くの場合は古いチェックポイント、あるいは異なるモデルファミリー)によって生成されていることです。学習が進むと、方策が学習ペアとはまったく異なるテキストを生成するようになり \(\rightarrow\)、損失は関係のない分布上で最適化されます。
Online DPOの解決策 (Guo et al. 2024):各ステップで現在の方策から新しい選好ペアを生成し、報酬モデルで評価してから、DPO損失を適用します。
アルゴリズム
-
プロンプトごとに \(K\) 個の応答を現在の \(\pi_\theta\) から生成します。
-
すべての応答を報酬モデル \(r_\phi\) でスコアリングします。
-
ペアを作成します:最高スコアを選択側、最低スコアを拒否側にします。
-
これらの新鮮なペアにDPO損失を適用します。
-
繰り返します(毎ステップ新たに生成)。
Tip
Online DPO = 両方の長所
DPOから:シンプルな教師あり損失、価値関数不要、GAE不要、安定した最適化
PPOから:オンポリシーデータ、データセットを超えた自己改善、分布シフトなし
GRPOとの主な違い:PPO損失(サンプルごとのアドバンテージ)ではなく、DPO損失(ペアベース)を使います。
トレードオフ :報酬モデルが必要です(DPOには不要)が、価値ヘッドは不要です(PPOには必要)。複雑さの中間に位置します。
TRLでの実装
以下は、HuggingFace TRLを使った最小限の動作例です。
from trl import OnlineDPOConfig, OnlineDPOTrainer
from transformers import AutoModelForCausalLM, AutoModelForSequenceClassification
model = AutoModelForCausalLM.from_pretrained("meta-llama/Llama-3.1-8B-Instruct",
torch_dtype=torch.bfloat16)
reward_model = AutoModelForSequenceClassification.from_pretrained(
"RLHFlow/ArmoRM-Llama3-8B-v0.1", torch_dtype=torch.bfloat16)
online_dpo_config = OnlineDPOConfig(
output_dir="./online_dpo_output",
learning_rate=5e-7,
beta=0.1, # DPO beta (same meaning as standard DPO)
num_generations=4, # K responses per prompt
per_device_train_batch_size=4,
gradient_accumulation_steps=4,
max_new_tokens=512,
temperature=0.7,
bf16=True,
num_train_epochs=1,
logging_steps=10,
)
trainer = OnlineDPOTrainer(
model=model,
reward_model=reward_model,
args=online_dpo_config,
train_dataset=prompt_dataset,
tokenizer=tokenizer,
)
trainer.train()
Online DPOとオフラインDPOとPPOの比較
| データ | モデル | 損失 | 最適な用途 | |
|---|---|---|---|---|
| オフラインDPO | 静的なペア | 2(方策 + 参照) | DPO | 高速なアラインメント、計算量が限られる場合 |
| Online DPO | \(\pi_\theta\) から新規生成 | 3(方策 + 参照 + 報酬モデル) | DPO | DPOが頭打ちになり、探索が必要な場合 |
| PPO | \(\pi_\theta\) から新規生成 | 4(方策 + 参照 + 報酬モデル + 価値ヘッド) | PPOクリップ | 最高品質、複雑な推論 |
KTO — カーネマン・トヴァースキー最適化
動機
DPOにはペアになった選好が必要です。同じプロンプトについて、良い応答と悪い応答の両方が必要になります。しかし実際のフィードバックの大半はペアになっていません。ユーザーは個々の応答に「いいね/よくないね」を付けるだけで、対応するペアはありません。
KTOの洞察 (Ethayarajh et al. 2024):プロスペクト理論(行動経済学)を使います。人間は利益よりも損失を強く感じます。「よくないね」は「いいね」より強い勾配を生むべきです。
損失関数
\[ \boxed{\mathcal{L}_\text{KTO} = \mathbb{E}_{y_w}\left[\lambda_w (1 - v(x, y_w))\right] + \mathbb{E}_{y_l}\left[\lambda_l \cdot v(x, y_l)\right]} \]
ここで \(v(x,y) = \sigma\left(\beta \log\frac{\pi_\theta(y\vert x)}{\pi_\text{ref}(y\vert x)} - z_\text{ref}\right)\)、\(z_\text{ref}\) は期待KLダイバージェンス(移動ベースライン)です。
Tip
プロスペクト理論によるKTOの直感
望ましい応答 (\(y_w\)):確率を高めることで、モデルは「効用」を得ます。ただし限界効用逓減があります。すでにかなり高い確率なら、さらに強く押し上げる必要はありません。
望ましくない応答 (\(y_l\)):損失回避により、悪いテキストを生成することへの罰は、良いテキストへの報酬より強く重み付けされます。デフォルトは \(\lambda_l = 1.0\)、\(\lambda_w = 1.0\) ですが、\(\lambda_l > \lambda_w\) に設定できます。
主な利点 :各学習例は独立しています。対応するペアを探す必要がありません。いいね/よくないねのデータを直接使えます。
Note
KTOのデータ形式
DPOでは次の形式が必要です:
{"prompt": ..., "chosen": ..., "rejected": ...}KTOに必要なのは次の形式だけです:
{"prompt": ..., "completion": ..., "label": true/false}つまり、次のデータを使えます。
本番トラフィックのいいね/よくないね
フォーラムの賛成票/反対票
二値化した人手評価(星4–5 = 良い、星1–2 = 悪い)
応答ごとの品質シグナル
TRLでの実装
以下は、HuggingFace TRLを使った最小限の動作例です。
from trl import KTOConfig, KTOTrainer
# Dataset format: {"prompt": str, "completion": str, "label": bool}
# label=True for desirable, label=False for undesirable
kto_dataset = [
{"prompt": "What's 2+2?", "completion": "The answer is 4.", "label": True},
{"prompt": "What's 2+2?", "completion": "It might be 5.", "label": False},
]
kto_config = KTOConfig(
output_dir="./kto_output",
beta=0.1,
desirable_weight=1.0, # Weight for good examples
undesirable_weight=1.0, # Weight for bad examples (increase for loss aversion)
learning_rate=5e-7,
max_length=2048,
per_device_train_batch_size=4,
gradient_accumulation_steps=4,
num_train_epochs=1,
bf16=True,
)
trainer = KTOTrainer(
model=model,
ref_model=ref_model, # Or None with LoRA
args=kto_config,
train_dataset=kto_dataset,
tokenizer=tokenizer,
)
trainer.train()
KTOを選ぶ場合
-
ペアになったデータはなく、二値フィードバックがある場合
-
大規模な本番環境のいいね/よくないねデータ
-
一方のクラスが支配的な場合(例:良い90%、悪い10%)— KTOは不均衡をより適切に扱います
-
ノイズの多いラベルで素早く反復したい場合(DPOよりノイズに頑健)
IPO — 恒等選好最適化
動機
DPOには退化解があります。選択側と拒否側のマージンを無限に大きくすることで、損失を0にできます。実際には、これはDPOが過適合することを意味します。選択側の確率を1に、拒否側を0に押し上げ、学習データを記憶します。
IPOの修正 (Azar et al. 2024):飽和するlog-sigmoidの代わりに、特定のマージンを目標とする二乗損失を使います。損失は無限大ではなく有限の差で最小になります。
損失関数
\[ \boxed{\mathcal{L}_\text{IPO} = \mathbb{E}\left[\left(\log\frac{\pi_\theta(y_w|x)}{\pi_\text{ref}(y_w|x)} - \log\frac{\pi_\theta(y_l|x)}{\pi_\text{ref}(y_l|x)} - \frac{1}{2\beta}\right)^2\right]} \]
Tip
IPOとDPO:目標マージンによる正則化
DPO:\(\sigma(\text{margin}) \to 1\) が最適です。マージン \(\to \infty\)。自然な停止点がありません。
IPO:マージン \(\to \frac{1}{2\beta}\) が最適です。二乗損失は、マージンが小さすぎる場合と大きすぎる場合の 両方 を罰します。
結果:IPOはノイズの多いラベルに対してより頑健です(誤ラベルのペアの影響が有限に抑えられる)し、記憶しないため汎化も向上します。
TRLでの実装
以下は、HuggingFace TRLを使った最小限の動作例です。
from trl import DPOConfig, DPOTrainer
# IPO is implemented as a DPO loss_type variant in TRL
ipo_config = DPOConfig(
output_dir="./ipo_output",
beta=0.1,
loss_type="ipo", # The key difference!
learning_rate=5e-7,
max_length=2048,
per_device_train_batch_size=4,
gradient_accumulation_steps=8,
bf16=True,
num_train_epochs=1,
)
trainer = DPOTrainer(
model=model, ref_model=None, args=ipo_config,
train_dataset=pref_dataset, tokenizer=tokenizer, peft_config=lora_config,
)
trainer.train()
DPOよりIPOを選ぶ場合
-
ノイズの多い選好データ(クラウドソーシング、誤りを含むAI評価)
-
DPOの過適合が見られる場合(学習損失 \(\to\) 0 だが評価が悪化)
-
より保守的で頑健なアラインメントが必要な場合
-
複数エポックが必要な場合(DPOは1エポック後に悪化するが、IPOはより安定)
ORPO — オッズ比選好最適化
動機
これまでの手法はすべて参照モデルを必要とします。別個のコピー(メモリが倍増)として持つか、LoRAによって暗黙的に持つかのどちらかです。ORPO (J. Hong et al. 2024) は、SFTと選好アラインメントを単一の損失に組み合わせることで、参照モデルを完全に不要にします。
核心となる洞察 :選択側と拒否側を生成するオッズ比を選好シグナルとして使います。SFT成分が自然に崩壊を防ぐため、KL正則化は不要です。
損失関数
\[ \boxed{\mathcal{L}_\text{ORPO} = \underbrace{\mathcal{L}_\text{SFT}(y_w)}_{\text{standard NLL on chosen}} - \lambda \cdot \underbrace{\log\sigma\left(\log\frac{\text{odds}_\theta(y_w|x)}{\text{odds}_\theta(y_l|x)}\right)}_{\text{preference alignment via odds ratio}}} \]
ここで \(\text{odds}_\theta(y\vert x) = \frac{P_\theta(y\vert x)}{1 - P_\theta(y\vert x)}\) です。
Tip
ORPO:SFT + アラインメントを一度に
SFT項 :選択側の応答をうまく生成するようモデルを学習させます(標準的な言語モデリング)。
オッズ比項 :選択側を拒否側より好むよう、モデルをさらに押し進めます。オッズ比は参照モデルを必要としない、自然な対比です。
なぜ参照モデルが不要なのか? :SFT損失がすでにモデルを妥当なテキストに固定します。他の手法における参照モデルへのKLと同じ役割を果たします。1つのモデル、1回のフォワードパス、1つの損失です。メモリを50%削減できます。
TRLでの実装
以下は、HuggingFace TRLを使った最小限の動作例です。
from trl import ORPOConfig, ORPOTrainer
orpo_config = ORPOConfig(
output_dir="./orpo_output",
beta=0.1, # Odds ratio weight (lambda)
learning_rate=5e-7,
max_length=2048,
per_device_train_batch_size=2,
gradient_accumulation_steps=8,
bf16=True,
num_train_epochs=1,
gradient_checkpointing=True,
)
trainer = ORPOTrainer(
model=model, # No ref_model needed!
args=orpo_config,
train_dataset=pref_dataset, # Same format as DPO: prompt/chosen/rejected
tokenizer=tokenizer,
peft_config=lora_config,
)
trainer.train()
ORPOを選ぶ場合
-
メモリに制約がある場合:参照モデルのコピーを保持できない場合(70Bモデルで70–140GBを節約)
-
ベースモデルから始める場合(まだSFT済みではない)— ORPOがSFTを同時に行います
-
可能な限りシンプルなパイプラインが必要な場合:1つのモデル、1つの損失、1回の学習
-
最初から良質な選好データがある場合
Warning
ORPOの制限
DPO/PPOほど研究が進んでいません — 70B以上の規模で実証済みのレシピが少ないです。
SFT成分があるため、単なる相対的な選好ではなく、高品質な選択側応答が必要です。
デバッグが難しくなります:2つの損失成分が衝突する可能性があります。
Important
関連項目:SimPO
SimPO (Meng et al. 2024) は、参照モデルを使わない別の選好手法です。長さ正規化された対数確率を暗黙の報酬として使うことで、参照モデルを完全に排除します。共有する「参照モデルなし」という思想のため、他のDPO拡張とともにセクション3.9.8で扱います。
Best-of-Nサンプリング(棄却サンプリング)
動機
最も単純なアプローチが勝つこともあります。Best-of-N (Nakano et al. 2021) は、RL段階で学習をまったく必要としません。複数の候補を生成し、最良のものを選ぶだけです。
アルゴリズム
-
各プロンプトについて、方策から \(N\) 個の応答(通常は \(N = 4\)–\(64\))を生成します。
-
すべての応答を報酬モデルでスコアリングします。
-
最高スコアの応答を選択します。
-
(任意)次の反復のSFTデータとして選択した応答を使います。
\[ \boxed{\text{Best-of-N response}: \quad y^* = \arg\max_{y_i \sim \pi_\theta(\cdot|x)} r_\phi(x, y_i)} \]
Tip
Best-of-Nが正当な「RL」手法である理由
推論時 :Best-of-Nはモデルの重みを変更せずに出力品質を高めます。\(N=64\) では、貪欲法に対する勝率が10–20%向上し、ときにはPPOに匹敵、あるいはそれを上回ります。
学習手法として (棄却サンプリング・ファインチューニング / RFT):
多数の応答を生成し、最良のものを選択します。
選択した応答に対してSFTを行います。
繰り返します(反復的な改善)。
これは多くの本番モデルが学習される方法です。PPOより単純で、ほぼ同等の効果があり、完全に安定しています。
理論的なつながり (Leo Gao et al. 2023):Best-of-Nは暗黙のKL制約付き方策を実装します:\(\pi_\text{BoN}(y\vert x) \propto \pi_\theta(y\vert x)^{1-1/N} \cdot r(x,y)^{1/N}\)。
TRLでの実装
以下は、HuggingFace TRLを使った最小限の動作例です。
from transformers import pipeline
import numpy as np
# Inference-time Best-of-N (manual implementation)
gen_pipeline = pipeline("text-generation", model=model, tokenizer=tokenizer)
def best_of_n(prompt, n=16, temperature=0.8):
"""Generate N candidates and return the highest-reward one."""
candidates = gen_pipeline(
prompt, num_return_sequences=n,
temperature=temperature, do_sample=True, max_new_tokens=512,
)
scores = [reward_model.score(prompt, c["generated_text"]) for c in candidates]
return candidates[np.argmax(scores)]["generated_text"]
best_response = best_of_n(prompt, n=16)
# Training: Rejection Sampling Fine-Tuning (RFT)
from trl import SFTConfig, SFTTrainer
# Step 1: Generate and filter
all_responses = []
for prompt in prompts:
candidates = [generate(prompt, temp=0.9) for _ in range(16)]
scores = [reward_model.score(prompt, c) for c in candidates]
best_idx = np.argmax(scores)
if scores[best_idx] > threshold: # Quality gate
all_responses.append({"prompt": prompt, "completion": candidates[best_idx]})
# Step 2: SFT on best responses
sft_config = SFTConfig(output_dir="./rft_output", learning_rate=2e-5, num_train_epochs=2, max_seq_length=2048)
trainer = SFTTrainer(model=model, args=sft_config, train_dataset=all_responses, tokenizer=tokenizer)
trainer.train()
# Step 3: Repeat from Step 1 with updated model (iterative RFT)
Best-of-Nのスケーリング則
| \(N\) | 品質向上 | コスト | 注記 |
|---|---|---|---|
| 1 | ベースライン | \(1\times\) | 標準サンプリング |
| 4 | 勝率 +5–8% | \(4\times\) | 実用上の最小値。コストと品質のバランスが良い |
| 16 | 勝率 +10–15% | \(16\times\) | 強力。PPOの品質に匹敵することが多い |
| 64 | 勝率 +15–20% | \(64\times\) | 逓減効果が始まる |
| 256 | 勝率 +18–22% | \(256\times\) | 重要な用途に限る |
Important
Best-of-Nをベースラインにする
RL手法は、同じ計算予算でBest-of-Nと必ず比較してください。PPOが64 GPU時間で、生成に64 GPU時間を使うBest-of-Nを上回れないなら、PPOにバグがあります。
まとめ:アラインメント手法の選択
ここまで、選好最適化とRLベースのアラインメント手法の全体像を調査してきました。この節では、実務者が制約に適したアプローチを選べるよう、主要なトレードオフを1つのリファレンスにまとめます。
| 手法 | モデル | データ | 計算量 | 安定性 | 最適な用途 |
|---|---|---|---|---|---|
| PPO | 4 | オンライン(生成) | 非常に高い | 低い | 最高品質、複雑な推論 |
| GRPO | 2(クリティックなし) | オンライン(生成) | 高い | 中程度 | 数学/コード(検証可能な報酬) |
| DPO | 2 | オフラインのペア | 低い | 高い | 文体/安全性、計算量が限られる場合 |
| Online DPO | 3 | オンライン(生成) | 中程度 | 中〜高 | 分布シフトのないDPO |
| KTO | 2 | ペアなし二値 | 低い | 高い | 本番フィードバック、いいね/よくないね |
| IPO | 2 | オフラインのペア | 低い | 非常に高い | ノイズの多いラベル、過適合防止 |
| ORPO | 1 | オフラインのペア | 非常に低い | 高い | メモリ制約、SFTとアラインメントの統合 |
| Best-of-N | 1+RM | オンライン(生成) | 中程度 | 完全 | 強力なベースライン、データ生成 |
アラインメント手法の横断比較。
Important
意思決定木:どの手法を使うか
検証可能な報酬がありますか? (数学/コード)\(\rightarrow\) GRPO
複雑なタスクで最高品質が必要ですか? \(\rightarrow\) PPO
ペアになった選好がありますか? \(\rightarrow\) DPO (ノイズが多ければIPO)
ペアなしの二値フィードバックだけですか? \(\rightarrow\) KTO
メモリに制約があり、ベースモデルから始めますか? \(\rightarrow\) ORPO
DPOが頭打ちで、オンポリシーを望みますか? \(\rightarrow\) Online DPO
強力なベースラインがすぐ必要ですか? \(\rightarrow\) Best-of-N / RFT