DPO, IPO, and offline preference optimization
Derive DPO's closed-form policy reparameterization that eliminates the reward model; then survey IPO, KTO, and ORPO as robust alternatives.
PPO-RLHF requires a trained reward model and a value model, making the training pipeline complex and memory-intensive. Direct Preference Optimization (DPO, Rafailov et al. 2023) shows that the optimal policy under the RLHF objective can be derived in closed form, and the reward model can be eliminated entirely -- the policy is trained directly on preference pairs with a simple classification-like objective[1].
Deriving DPO
Start from the KL-penalized RLHF objective[2]:
The optimal policy has a closed-form solution (derived by setting the functional derivative to zero):
where is the partition function.
Rearranging: given the optimal policy, we can express the reward in terms of the policy:
Key insight: does not depend on , so it cancels in the Bradley-Terry preference probability:
Replace with the learned policy and maximize likelihood:
This is the DPO objective: binary cross-entropy on preference pairs, using the log-ratio of the policy to the reference model as an implicit reward.
What DPO does intuitively
The quantity measures how much more (or less) likely the policy makes response relative to the SFT baseline.
DPO maximizes :
- It increases the relative probability of preferred responses.
- It decreases the relative probability of dispreferred responses.
- The controls the scale -- large keeps changes close to the reference.
The loss is binary cross-entropy on the margin , where . Watching that margin makes the scale concrete (with the per-pair loss ):
- At initialization, , so both log-ratios are , the margin is , and the loss is nats. Every pair starts at the same value, the entropy of a coin flip.
- A modest correct nudge. Suppose training raises by nats over the reference and lowers by nats. With the implicit rewards are and , a margin of , and the loss drops to . The same probability shifts at would give a margin of and loss : rescales how loudly a fixed change in token probabilities registers.
- Saturation. Once the margin reaches , and the loss is ; pushing further yields almost no gradient. The objective stops driving a pair apart once the preferred response is already clearly ahead, which is what keeps DPO from collapsing the policy onto the chosen samples.
The confusion to name: the implicit reward is not a log-probability of , but times a log-ratio against the frozen reference. A response can have low absolute likelihood and still earn a high implicit reward if the policy raised it far above where the SFT model put it.
Implementation
import torch
import torch.nn.functional as F
def dpo_loss(policy, ref_model, prompts, y_w, y_l, beta=0.1):
"""
policy, ref_model: callable (prompt, response) -> log-probability
prompts, y_w, y_l: batched inputs
"""
def log_prob(model, prompt, response):
# In practice: compute log p(response | prompt) by summing token log-probs
return model.log_probs(prompt, response) # (B,)
log_pi_w = log_prob(policy, prompts, y_w)
log_pi_l = log_prob(policy, prompts, y_l)
log_ref_w = log_prob(ref_model, prompts, y_w)
log_ref_l = log_prob(ref_model, prompts, y_l)
implicit_r_w = beta * (log_pi_w - log_ref_w)
implicit_r_l = beta * (log_pi_l - log_ref_l)
loss = -F.logsigmoid(implicit_r_w - implicit_r_l).mean()
return lossIPO: identity preference optimization
DPO assumes the Bradley-Terry model, which may not hold for all preference datasets. IPO (Azar et al., 2024) derives a variant that is more robust to reward hacking and works without the BT assumption by directly fitting the log-ratio:
This is a regression target: push the difference in log-ratios to , a fixed margin rather than maximizing the BT objective without bound.
KTO: Kahneman-Tversky optimization
KTO (Ethayarajh et al., 2024) does not require preference pairs -- only binary labels (good/bad). This is valuable when pairwise preference collection is expensive.
The objective aligns with human decision-making under prospect theory: losses are felt more acutely than equivalent gains, matching Kahneman-Tversky's reference-point model.
ORPO: odds ratio preference optimization
ORPO (Hong et al., 2024) removes the reference model entirely by combining SFT and preference optimization in a single objective:
where .
ORPO uses the ratio of odds rather than log-ratios to a reference, making it a true single-stage training method with no SFT warm-up required.
Comparison
| Method | Requires RM? | Requires ref model? | Pairs required? |
|---|---|---|---|
| PPO-RLHF | Yes | Yes | Pairs (via RM) |
| DPO | No | Yes | Yes |
| IPO | No | Yes | Yes |
| KTO | No | Yes | No (binary) |
| ORPO | No | No | Yes |
Exercises
Exercise 1. During DPO training with , a chosen response has its policy log-probability raised by nats over the reference and a rejected response lowered by nats. Compute the two implicit rewards, the margin, and the per-pair DPO loss in nats.
Solution
Step 1. The implicit reward is . For the chosen response the log-ratio is , so . For the rejected response the log-ratio is , so .
Step 2. The margin is .
Step 3. The loss is . With and , , so the loss is nats. This matches the lesson's for the same shifts at .
Exercise 2. Derive the gradient of the DPO loss with respect to the margin , and show that it scales with . Use this to explain the saturation noted in the lesson: that a pair with margin gets almost no gradient.
Solution
Step 1. The per-pair loss is . With :
Step 2. The gradient magnitude is , the weight DPO places on a pair. For a still-ambiguous pair near , , a strong push.
Step 3. At , , so . The gradient is roughly weaker than at . Once the preferred response is well ahead, the loss stops driving the pair apart, which keeps DPO from collapsing the policy onto the chosen samples.
Exercise 3 (code). Implement the DPO loss in numpy directly from policy and reference log-probabilities (four scalars per pair). Verify the Exercise 1 numbers, and check that adding the same constant to both chosen log-probs (policy and reference together) leaves the loss unchanged, since only the log-ratio enters.
Solution
import numpy as np
def logsigmoid(z):
# numerically stable log sigmoid
return -np.logaddexp(0.0, -z)
def dpo_loss(logp_w, logref_w, logp_l, logref_l, beta=0.1):
r_w = beta * (logp_w - logref_w) # implicit reward, chosen
r_l = beta * (logp_l - logref_l) # implicit reward, rejected
margin = r_w - r_l
return -logsigmoid(margin), margin
# Exercise 1: chosen log-ratio +3, rejected log-ratio -2, beta = 0.1.
logref_w, logref_l = -1.0, -1.0
logp_w = logref_w + 3.0 # raised by +3 nats
logp_l = logref_l - 2.0 # lowered by 2 nats
loss, margin = dpo_loss(logp_w, logref_w, logp_l, logref_l, beta=0.1)
assert np.isclose(margin, 0.5)
assert np.isclose(loss, -np.log(1 / (1 + np.exp(-0.5))))
# Only the log-ratio matters: shift policy and reference chosen log-probs together.
c = 2.5
loss_shift, _ = dpo_loss(logp_w + c, logref_w + c, logp_l, logref_l, beta=0.1)
assert np.isclose(loss_shift, loss)
print("DPO loss:", round(float(loss), 4), "margin:", round(float(margin), 4))The loss reproduces nats at margin and is invariant to shifting the chosen policy and reference log-probs together, confirming DPO sees only the log-ratio.
DPO and its variants are now the dominant preference optimization methods for open-source LLMs due to their simplicity, stability, and competitive performance with PPO.
References
- [1]Rafailov, R., et al. (2023). "Direct preference optimization (DPO)". NeurIPS. arXiv:2305.18290. The closed-form reparameterization that trains the policy directly on preference pairs.↩
- [2]Ouyang, L., et al. (2022). "Training language models to follow instructions with human feedback (InstructGPT)". NeurIPS. arXiv:2203.02155. The KL-penalized RLHF objective DPO reparameterizes.↩