- Introduction: Why DPO
- 1. The Structure and Limits of RLHF
- 2. The Mathematics of DPO
- 3. RLHF vs DPO: Comparing the Training Pipelines
- 4. A DPO Implementation in PyTorch
- 5. DPO Variants Compared: IPO, KTO, ORPO
- 6. Experimental Results and Benchmarks
- 7. Cautions When Applying DPO in Practice
- 8. The Limits of DPO and Where Research Is Heading
- 9. Conclusion
- References
Introduction: Why DPO
When ChatGPT changed the world in 2023, alignment — matching an LLM to human intent — rose to the top of the agenda. The RLHF (Reinforcement Learning from Human Feedback) pipeline that OpenAI established with InstructGPT is powerful, but it has to go through 2 complicated stages: training a separate reward model, and then PPO reinforcement learning. Along the way you have to hold 4 models in GPU memory at once, tune a great many hyperparameters, and live with unstable training.
Direct Preference Optimization (DPO), presented by Rafailov et al. at NeurIPS 2023, offered a mathematically elegant answer to that problem. The core insight is simple. The reward-optimization problem in RLHF has a closed-form solution, and with it you can optimize a policy directly from preference data without a reward model. Exactly as the paper's title puts it: "Your Language Model is Secretly a Reward Model."
This article follows the mathematical derivation in the DPO paper from beginning to end, and covers the structural differences from RLHF, a PyTorch implementation, a comparison of the variants (IPO, KTO, ORPO), an analysis of the experimental results, and the cautions that matter when you apply it in practice.
1. The Structure and Limits of RLHF
1.1 The 3-Stage RLHF Pipeline
RLHF consists of the following three stages.
Stage 1 - SFT (Supervised Fine-Tuning): fine-tune the base model on high-quality instruction-response pairs to give it basic instruction-following ability.
Stage 2 - Reward Model training: for the same prompt , collect two responses (chosen) and (rejected), and train a reward function based on the Bradley-Terry model.
Stage 3 - PPO optimization: maximize the score from the trained reward model while constraining the KL divergence from the reference policy .
1.2 The Practical Limits of RLHF
| Limitation | Description |
|---|---|
| Memory cost | Policy, Reference, Reward and Value — 4 models must be loaded at once |
| Training instability | Many sensitive hyperparameters: PPO clipping ratio, KL coefficient, GAE lambda |
| Reward hacking | Risk of learning a policy that exploits weaknesses in the reward model to inflate the score |
| Poor reproducibility | Results vary widely with the random seed even under identical settings |
| High implementation difficulty | PPO advantage estimation, value-function training and the rest make it complex to implement |
For a 70B model, the RLHF pipeline needs at least 8 A100 80GB GPUs. Limits like these are the backdrop against which RL-free alignment methods such as DPO appeared.
2. The Mathematics of DPO
2.1 Starting Point: the Closed-Form Solution of the RLHF Objective
The derivation of DPO begins with an analytic solution of the RLHF objective. Rewriting the KL-constrained reward-maximization problem of RLHF gives the following.
The optimal policy for this problem can be obtained analytically.
Here is the normalizing constant (the partition function).
2.2 Reward Reparameterization
Take the logarithm of both sides of the optimal-policy equation above and rearrange for , and you get the following.
This is the core insight of DPO. The reward function can be expressed as the log ratio of the optimal policy to the reference policy. In other words, without explicitly training a reward model, the policy itself implicitly contains the reward function.
2.3 The Bradley-Terry Model and the Derivation of the DPO Loss
The Bradley-Terry model, which models human preference, is as follows.
Here is the sigmoid function. Now substitute the reparameterized reward function into the Bradley-Terry model.
Remarkably, the terms cancel. That cancellation is the mathematical heart of what makes DPO possible. With the intractable partition function gone, the preference probability is expressed purely in terms of policy ratios.
Train this with maximum likelihood estimation (MLE) and the final DPO loss function falls out.
2.4 An Intuitive Reading of the DPO Loss
Analyzing the gradient of the DPO loss function gives the following.
Here is the implicit reward.
This gradient performs two roles at once.
- It raises the probability of the chosen response and lowers the probability of the rejected one (the term inside the square brackets)
- It assigns a small weight to pairs the model already separates correctly and a large weight to pairs it separates wrongly (the sigmoid term)
That dynamic weighting is the key device that prevents the model degeneration which arises from naive probability-ratio optimization.
3. RLHF vs DPO: Comparing the Training Pipelines
3.1 Pipeline Structure Compared
| Item | RLHF (PPO) | DPO |
|---|---|---|
| Training stages | SFT → RM training → PPO optimization (3 stages) | SFT → DPO optimization (2 stages) |
| Number of models needed | 4 (Policy, Reference, Reward, Value) | 2 (Policy, Reference) |
| Reward model | Must be trained explicitly | Implicit in the policy |
| Optimization method | Reinforcement learning (PPO) | Classification loss (similar to Binary Cross-Entropy) |
| Training stability | Unstable (sensitive to PPO hyperparameters) | Stable (a training loop much like SFT) |
| Main hyperparameters | lr, clip ratio, KL coeff, GAE lambda, epochs | lr, beta |
| Online generation | Required (the model generates responses during training) | Not required (offline data only) |
| GPU requirement, 70B model | A100 80GB x 8+ | A100 80GB x 4 |
| Implementation complexity | High | Low (roughly SFT code with small edits) |
3.2 The Two Training Loops Side by Side
The training loop of the RLHF pipeline (conceptual pseudocode):
# RLHF (PPO) training loop pseudocode
import torch
# 4 models must be loaded at the same time
policy_model = load_model("sft_checkpoint")
reference_model = load_model("sft_checkpoint") # frozen
reward_model = load_model("reward_model_checkpoint")
value_model = load_model("value_head_checkpoint")
for batch in dataloader:
prompts = batch["prompt"]
# 1. Generate responses with the policy model (online generation required)
responses = policy_model.generate(prompts)
# 2. Score them with the reward model
rewards = reward_model(prompts, responses)
# 3. Estimate the advantage with the value function (GAE)
values = value_model(prompts, responses)
advantages = compute_gae(rewards, values, gamma=0.99, lam=0.95)
# 4. Optimize the PPO clipped objective
ratio = policy_model.log_prob(responses) - reference_model.log_prob(responses)
clipped_ratio = torch.clamp(ratio, 1 - clip_eps, 1 + clip_eps)
policy_loss = -torch.min(ratio * advantages, clipped_ratio * advantages).mean()
# 5. Add the KL penalty
kl_penalty = beta * kl_divergence(policy_model, reference_model, responses)
total_loss = policy_loss + kl_penalty
total_loss.backward()
optimizer.step()
The DPO training loop (conceptual pseudocode):
# DPO training loop pseudocode
import torch
import torch.nn.functional as F
# Only 2 models are needed
policy_model = load_model("sft_checkpoint")
reference_model = load_model("sft_checkpoint") # frozen
for batch in dataloader:
# Train directly from offline data (no online generation needed)
prompts = batch["prompt"]
chosen = batch["chosen"]
rejected = batch["rejected"]
# 1. Compute the log probability under each model
pi_chosen = policy_model.log_prob(chosen, prompts)
pi_rejected = policy_model.log_prob(rejected, prompts)
ref_chosen = reference_model.log_prob(chosen, prompts)
ref_rejected = reference_model.log_prob(rejected, prompts)
# 2. The DPO loss (just 3 lines!)
log_ratio_chosen = pi_chosen - ref_chosen
log_ratio_rejected = pi_rejected - ref_rejected
loss = -F.logsigmoid(beta * (log_ratio_chosen - log_ratio_rejected)).mean()
loss.backward()
optimizer.step()
The difference is plain. RLHF needs 4 models and a complicated advantage estimation, whereas DPO reaches the same goal with 2 models and 3 lines of loss computation.
4. A DPO Implementation in PyTorch
4.1 Implementing the DPO Loss Directly
Implementing the DPO loss yourself in PyTorch makes its inner workings clear.
import torch
import torch.nn.functional as F
from torch import nn
def dpo_loss(
policy_chosen_logps: torch.Tensor,
policy_rejected_logps: torch.Tensor,
reference_chosen_logps: torch.Tensor,
reference_rejected_logps: torch.Tensor,
beta: float = 0.1,
label_smoothing: float = 0.0,
) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor]:
"""
An implementation of the DPO loss function.
Args:
policy_chosen_logps: log probability of the chosen response under the policy model
policy_rejected_logps: log probability of the rejected response under the policy model
reference_chosen_logps: log probability of the chosen response under the reference model
reference_rejected_logps: log probability of the rejected response under the reference model
beta: strength of the KL constraint (temperature)
label_smoothing: label smoothing coefficient (0 gives standard DPO)
Returns:
loss: the DPO loss value
chosen_rewards: implicit reward of the chosen response
rejected_rewards: implicit reward of the rejected response
"""
# Implicit reward: r(x,y) = beta * log(pi/pi_ref)
chosen_rewards = beta * (policy_chosen_logps - reference_chosen_logps)
rejected_rewards = beta * (policy_rejected_logps - reference_rejected_logps)
# Reward margin
reward_margin = chosen_rewards - rejected_rewards
# Apply label smoothing (optional)
if label_smoothing > 0:
loss = (
-F.logsigmoid(reward_margin) * (1 - label_smoothing)
- F.logsigmoid(-reward_margin) * label_smoothing
)
else:
loss = -F.logsigmoid(reward_margin)
return loss.mean(), chosen_rewards.mean(), rejected_rewards.mean()
# Usage example
batch_size = 4
seq_len = 128
# Mock log probability values
policy_chosen_logps = torch.randn(batch_size) * 0.1 - 2.0
policy_rejected_logps = torch.randn(batch_size) * 0.1 - 2.5
reference_chosen_logps = torch.randn(batch_size) * 0.1 - 2.0
reference_rejected_logps = torch.randn(batch_size) * 0.1 - 2.5
loss, chosen_r, rejected_r = dpo_loss(
policy_chosen_logps,
policy_rejected_logps,
reference_chosen_logps,
reference_rejected_logps,
beta=0.1,
)
print(f"DPO Loss: {loss.item():.4f}")
print(f"Chosen Reward: {chosen_r.item():.4f}")
print(f"Rejected Reward: {rejected_r.item():.4f}")
4.2 A Log-Probability Utility
The most important piece of computation in DPO is getting the log probability of a sequence exactly right.
import torch
import torch.nn.functional as F
def compute_log_probs(
logits: torch.Tensor,
labels: torch.Tensor,
attention_mask: torch.Tensor,
) -> torch.Tensor:
"""
Compute per-token log probabilities and sum them per sequence.
Args:
logits: model output logits (batch_size, seq_len, vocab_size)
labels: ground-truth token IDs (batch_size, seq_len)
attention_mask: attention mask (batch_size, seq_len)
Returns:
per-sequence log probability (batch_size,)
"""
# Shift the logits forward by 1 token (next token prediction)
shift_logits = logits[:, :-1, :]
shift_labels = labels[:, 1:]
shift_mask = attention_mask[:, 1:]
# Per-token log probability
log_probs = F.log_softmax(shift_logits, dim=-1)
per_token_logps = torch.gather(
log_probs, dim=2, index=shift_labels.unsqueeze(2)
).squeeze(2)
# Treat masked tokens as 0 and sum over the sequence
per_token_logps = per_token_logps * shift_mask
return per_token_logps.sum(dim=-1)
4.3 Real-World DPO Training with Hugging Face TRL
In practice, using the DPOTrainer from the TRL library is the recommended route.
from datasets import load_dataset
from transformers import AutoModelForCausalLM, AutoTokenizer
from trl import DPOConfig, DPOTrainer
from peft import LoraConfig
# 1. Load the model and tokenizer
model_name = "Qwen/Qwen2.5-7B-Instruct"
model = AutoModelForCausalLM.from_pretrained(
model_name,
torch_dtype="bfloat16",
attn_implementation="flash_attention_2",
)
tokenizer = AutoTokenizer.from_pretrained(model_name)
if tokenizer.pad_token is None:
tokenizer.pad_token = tokenizer.eos_token
# 2. LoRA configuration (saves memory)
peft_config = LoraConfig(
r=16,
lora_alpha=32,
lora_dropout=0.05,
target_modules=["q_proj", "k_proj", "v_proj", "o_proj"],
task_type="CAUSAL_LM",
)
# 3. Load the preference data (prompt, chosen, rejected structure)
dataset = load_dataset("trl-lib/ultrafeedback_binarized", split="train")
# 4. DPO training configuration
training_args = DPOConfig(
output_dir="./dpo-qwen2.5-7b",
per_device_train_batch_size=2,
gradient_accumulation_steps=8,
learning_rate=5e-6, # 10~100x lower than for SFT
beta=0.1, # strength of the KL constraint
max_length=1024,
max_prompt_length=512,
num_train_epochs=1,
bf16=True,
logging_steps=10,
save_strategy="steps",
save_steps=500,
warmup_ratio=0.1,
gradient_checkpointing=True,
remove_unused_columns=False,
)
# 5. Create the DPO Trainer and train
trainer = DPOTrainer(
model=model,
args=training_args,
train_dataset=dataset,
processing_class=tokenizer,
peft_config=peft_config,
)
trainer.train()
trainer.save_model("./dpo-qwen2.5-7b-final")
Environment setup before training starts:
# Install the required packages
pip install trl>=0.12.0 transformers>=4.46.0 peft>=0.13.0 \
datasets accelerate bitsandbytes flash-attn
# Run multi-GPU training (DeepSpeed ZeRO-3)
accelerate launch --config_file deepspeed_zero3.yaml \
--num_processes 4 \
train_dpo.py
# Monitor training
tensorboard --logdir ./dpo-qwen2.5-7b/runs
5. DPO Variants Compared: IPO, KTO, ORPO
Since DPO succeeded, a range of variants has been proposed. Each one either addresses a specific limitation of DPO or answers a different data requirement.
5.1 IPO (Identity Preference Optimization)
Paper: A General Theoretical Paradigm to Understand Learning from Human Preferences (Azar et al., 2024, AISTATS)
IPO questions the Bradley-Terry model that DPO assumes at its core. The Bradley-Terry model converts pairwise preferences into a pointwise reward, and that conversion loses information and raises the risk of overfitting. IPO solves this by using a squared loss.
In DPO, optimization can run in the direction of pushing the probability of the chosen response up without limit; IPO is constrained to converge on the target margin .
5.2 KTO (Kahneman-Tversky Optimization)
Paper: KTO: Model Alignment as Prospect Theoretic Optimization (Ethayarajh & Jurafsky, 2024, ICML)
The biggest innovation in KTO is that alignment becomes possible with binary signals alone, without pairwise data. Building on Kahneman and Tversky's Prospect Theory, it writes into the objective the loss-aversion phenomenon whereby humans react more strongly to losses than to gains.
Here is the loss-aversion coefficient, which comes from the experimental results of prospect theory.
5.3 ORPO (Odds-Ratio Preference Optimization)
Paper: ORPO: Monolithic Preference Optimization without Reference Model (Hong et al., 2024)
ORPO merges SFT and preference optimization into a single objective and removes the reference model entirely.
The odds-ratio preference loss optimizes the odds ratio of the chosen and rejected responses directly, achieving alignment in a single training run with no separate SFT stage and no reference model.
5.4 Overall Comparison Table
| Item | DPO | IPO | KTO | ORPO |
|---|---|---|---|---|
| Theoretical basis | Bradley-Terry model | General preference framework | Prospect Theory | Odds-Ratio |
| Data format | Pairwise (chosen/rejected) | Pairwise (chosen/rejected) | Binary (good/bad) | Pairwise (chosen/rejected) |
| Reference model | Required | Required | Required | Not required |
| SFT stage | Separate stage needed | Separate stage needed | Separate stage needed | Merged in (not needed) |
| Robustness to overfitting | Moderate | High (bounded) | High | Moderate |
| Key hyperparameters | beta (0.1~0.5) | beta (0.01~0.1) | beta, lambda | lambda |
| Memory efficiency | Moderate (2 models) | Moderate (2 models) | Moderate (2 models) | High (1 model) |
| Training stability | High | Very high | High | High |
| Implementation complexity | Low | Low | Medium | Low |
| NeurIPS/ICML | NeurIPS 2023 | AISTATS 2024 | ICML 2024 | ICLR 2024 reject |
6. Experimental Results and Benchmarks
6.1 The Main Experimental Results in the DPO Paper
The DPO paper ran experiments on three tasks.
Controlled Sentiment Generation: in an experiment aligning GPT-2 to generate positive reviews on the IMDb dataset, DPO reached a higher reward than PPO-based RLHF while keeping KL divergence lower. That shows DPO manages the trade-off between reward and diversity more efficiently.
TL;DR Summarization: training GPT-J 6B on the Reddit TL;DR summarization task, DPO reached a GPT-4-judged win rate of about 61% at temperature 0.0, exceeding PPO's 57%. DPO was also far more robust than PPO with respect to sampling temperature.
Single-Turn Dialogue: training Pythia 2.8B on the Anthropic HH dataset, DPO showed response quality equal to or better than PPO.
6.2 The Distribution Shift Experiment
One important DPO experiment evaluated a model trained on Reddit TL;DR against the CNN/DailyMail news dataset. The DPO policy held meaningfully higher performance than the PPO policy even under distribution shift. This suggests the alignment DPO learns is not confined to one domain but generalizes.
6.3 Benchmark Summary
| Task | Evaluation method | DPO win rate | PPO win rate | Best-of-N |
|---|---|---|---|---|
| TL;DR summarization | GPT-4 judge | ~61% | ~57% | ~63% |
| Anthropic HH dialogue | GPT-4 judge | Equal | Baseline | Equal |
| Sentiment control | Reward score | Better | Baseline | - |
| Distribution shift (CNN/DM) | GPT-4 judge | Better | Baseline | - |
That said, a 2024 study (Xu et al., "Is DPO Superior to PPO for LLM Alignment?") showed that a properly tuned PPO can exceed DPO, suggesting the potential of RLHF has not been entirely superseded by DPO. PPO's advantage was observed in particular on complex reasoning tasks such as code generation.
7. Cautions When Applying DPO in Practice
7.1 Dataset Construction Strategy
DPO's performance depends heavily on the quality of the preference-pair data. The things to watch in practice are as follows.
Data quality beats data volume: a small amount of high-quality data is better than a large amount of low-quality data. Data with low inter-annotator agreement gets in the way of training.
Using synthetic data: generating preference pairs with GPT-4 or Claude is widely used. The UltraFeedback dataset is a representative example.
# An example pipeline for generating synthetic preference data
from openai import OpenAI
client = OpenAI()
def generate_preference_pair(prompt: str, model_response_a: str, model_response_b: str) -> dict:
"""Use GPT-4 to make the preference judgement"""
judge_prompt = f"""Compare the two responses below and judge which one is more helpful,
more accurate, and safer.
Prompt: {prompt}
Response A: {model_response_a}
Response B: {model_response_b}
Output only the label of the better response (A or B):"""
result = client.chat.completions.create(
model="gpt-4",
messages=[{"role": "user", "content": judge_prompt}],
max_tokens=1,
)
choice = result.choices[0].message.content.strip()
if choice == "A":
return {"prompt": prompt, "chosen": model_response_a, "rejected": model_response_b}
else:
return {"prompt": prompt, "chosen": model_response_b, "rejected": model_response_a}
The quality gap between chosen and rejected: if the quality gap between the two responses is too large the training signal is weak, and if it is too small the data gets noisy. A middling gap is ideal.
7.2 A Hyperparameter Tuning Guide
| Hyperparameter | Recommended range | Description |
|---|---|---|
| beta | 0.1 ~ 0.5 | Strength of the KL constraint. Higher is more conservative. 0.1 is the usual starting point |
| learning_rate | 1e-7 ~ 5e-6 | Set 10~100x lower than for SFT |
| epochs | 1 ~ 3 | 1 epoch is recommended to avoid overfitting |
| batch_size (effective) | 32 ~ 128 | Including gradient accumulation |
| max_length | 1024 ~ 2048 | Adjust to the task |
| warmup_ratio | 0.05 ~ 0.15 | Stabilizes early training |
| label_smoothing | 0.0 ~ 0.1 | Prevents overfitting. Proposed in cDPO |
Beta tuning strategy: if beta is too high (0.5+) the policy stays too close to the reference model and the alignment effect is negligible. If it is too low (0.01) the policy becomes unstable and overfits to the chosen responses. Monitor the implicit-reward gap between chosen and rejected during training and pick a beta at which the reward margin grows neither too large nor too small.
Key metrics to monitor during training:
# The key metrics to monitor during DPO training
def log_dpo_metrics(chosen_rewards, rejected_rewards, loss):
"""A function that logs the key metrics during training"""
reward_margin = (chosen_rewards - rejected_rewards).mean()
accuracy = (chosen_rewards > rejected_rewards).float().mean()
metrics = {
"dpo/loss": loss.item(),
"dpo/reward_margin": reward_margin.item(),
"dpo/accuracy": accuracy.item(),
"dpo/chosen_reward_mean": chosen_rewards.mean().item(),
"dpo/rejected_reward_mean": rejected_rewards.mean().item(),
}
# A reward_margin that keeps rising is a sign of overfitting
# If accuracy reaches 1.0, consider stopping training
return metrics
7.3 Common Failure Patterns and Fixes
| Failure pattern | Symptom | Fix |
|---|---|---|
| Overfitting | accuracy 1.0, reward margin explodes | Reduce the epoch count, apply label smoothing |
| Rambling responses | Response length shoots up | Check the quality of the SFT stage, add a length penalty |
| Failure to converge | Oscillating loss, accuracy stuck at 0.5 | Check data quality, lower the learning rate |
| Reward hacking | Only the benchmark rises while real quality falls | Introduce varied evaluation criteria, secure data diversity |
| Drift from the reference model | Probability falls for both chosen and rejected | Check the quality of the SFT model, adjust beta |
8. The Limits of DPO and Where Research Is Heading
8.1 Known Limitations
Distribution shift: because DPO trains on offline data, the policy drifts further from the reference model as training goes on, and the gap widens between the distribution of the training data and the distribution the model actually generates. This is DPO's most fundamental limitation, and attempts to solve it with variants such as online DPO and iterative DPO are under way.
The generalization limit of the implicit reward model: according to research from Apple Research, DPO's implicit reward performs similarly to an RLHF reward model on in-distribution data, but in out-of-distribution settings its accuracy drops by up to 7%. That an explicit reward model holds greater generalization ability is a structural weakness of DPO.
Likelihood displacement: during DPO training, the probability of responses that are neither chosen nor rejected has been reported to increase unintentionally. This arises from the limits of model capacity interacting with a large number of training samples.
The fragility of the Bradley-Terry assumption: the assumption that human preference is always transitive and expressible as a pointwise reward may differ from reality. IPO pointed the problem out but did not reach a fundamental solution.
8.2 Where Research Is Heading
Online/Iterative DPO: a method that continuously refreshes the preference data using the model's own generations during training. It addresses the distribution-shift problem of offline DPO while keeping a pipeline simpler than RLHF.
Hybrid approaches: research combining the simplicity of DPO with the online exploration ability of PPO is active. A 2-stage approach — DPO for initial alignment, then fine-tuning with RLHF — has proved effective in several studies.
Alignment on verifiable rewards: on tasks whose results can be verified automatically, such as mathematics and coding, GRPO and verifier-driven RL are more effective than DPO. The success of DeepSeek-R1 shows the promise of this direction.
Multi-objective alignment: DPO variants that optimize several objectives at once — safety, helpfulness, honesty — rather than a single preference axis, are under study.
9. Conclusion
DPO is the paper that changed the paradigm of LLM alignment. It simplified RLHF's complicated 3-stage pipeline with mathematical elegance, replacing reward-model training and PPO optimization with a single classification loss. The key is cancelling the partition function through a reparameterization of the reward function, and that cancellation cuts implementation complexity and compute cost sharply.
DPO does not, however, replace RLHF outright. Structural limits remain — the distribution-shift problem, the generalization limit of the implicit reward, the fragility of the Bradley-Terry assumption — and results have been reported in which a properly tuned PPO exceeds DPO on particular tasks. In practice you have to weigh the character of the task, data availability and compute resources together, then pick the best strategy among DPO, KTO, ORPO, or a hybrid approach.
References
- Direct Preference Optimization: Your Language Model is Secretly a Reward Model (Rafailov et al., NeurIPS 2023)
- A General Theoretical Paradigm to Understand Learning from Human Preferences - IPO (Azar et al., AISTATS 2024)
- KTO: Model Alignment as Prospect Theoretic Optimization (Ethayarajh & Jurafsky, ICML 2024)
- Is DPO Superior to PPO for LLM Alignment? A Comprehensive Study (Xu et al., 2024)
- Hugging Face TRL - DPO Trainer official documentation
- DPO Reference Implementation (Eric Mitchell, GitHub)
- On the Limited Generalization Capability of the Implicit Reward Model Induced by DPO (Apple ML Research)
- How to Align Open LLMs in 2025 with DPO & Synthetic Data (Philipp Schmid)
- Towards Analyzing and Understanding the Limitations of DPO: A Theoretical Perspective (2024)
- A Comprehensive Survey of Direct Preference Optimization (2024)