Model-Based Reinforcement Learning › Sample Efficiency, Model Bias, and Model Exploitation
World Models HandbookAll chapters Model-Based Reinforcement Learning › Sample Efficiency, Model Bias, and Model ExploitationOne section · Sections in this chapter4 / 11 ↓
Reading tools Definitions & inline links
Choose your expertise level to adjust how many terms are explained. Beginners see more tooltips, experts see fewer to maintain reading flow. Hover over underlined terms for instant definitions.
Article links
Make inline references clickable
This section covers the central tradeoff of the chapter. Models buy sample efficiency, and they charge for it in bias. The two subsections that follow give each side its due, first the mechanisms by which models reduce the demand for real data, then the quantitative ways in which model error enters and accumulates. By the end, you should be able to identify the controlling tradeoffs and design evaluations that reveal whether a model-based system helps on a particular problem.
Why Models Improve Sample Efficiency
It is worth being precise about where the efficiency comes from, because "the model lets you imagine" is only part of the story. There are at least four distinct sources, and they interact:
- Compression. A suitable parametric model can share structure across states rather than learn each tabular state-action pair independently. This statistical advantage depends on whether the hypothesis class captures structure that actually transfers.
- Re-use and re-weighting. Both model-free replay and model-based training can revisit real transitions many times. A model adds structured branching: it can propose continuations and reweight where computation is spent.
- Off-policy imagination. A generalized model can evaluate actions absent from a particular trajectory, but reliable counterfactual prediction still requires action coverage or defensible structural assumptions. State coverage alone is not enough.
- Auxiliary predictive signal. Predicting observations or dynamics provides dense self-supervised targets even when reward is sparse. A learned reward model does not by itself densify sparse reward labels; that requires shaping, auxiliary objectives, or other added structure.
These potential benefits do not require long-horizon rollouts. A system may use a model only for short branching, auxiliary prediction, or one-step backups.
Compounding Rollout Error
Suppose the true and learned transition maps start from the same state, so , and are evaluated under the same actions. Assume the learned map has uniform one-step error at most on the relevant region and the true transition map is -Lipschitz in state. If is the state error after modeled transitions, then
An error injected transitions before the end is multiplied by at most . The regimes differ: the bound stays finite as grows when , grows linearly when , and grows exponentially only when .
The bound is easiest to internalize as a curve. Fix a one-step error of , a deliberately small value that would look excellent on any one-step benchmark, and plot the worst-case rollout error against horizon for a few values of the Lipschitz constant :
import numpy as np
EPSILON = 0.01
HORIZONS = np.arange(1, 51)
LIPSCHITZ_VALUES = [0.8, 1.0, 1.2]
def rollout_error_bound(L, horizons, epsilon=EPSILON):
if np.isclose(L, 1.0):
return epsilon * horizons
return epsilon * (L**horizons - 1.0) / (L - 1.0)
bound_curves = {L: rollout_error_bound(L, HORIZONS) for L in LIPSCHITZ_VALUES}
The plot does not say that every rollout diverges. It isolates how transition sensitivity and repeated one-step error interact under explicit assumptions. Short rollouts, replanning, and value bootstrapping reduce exposure to the expansive regime.
Discounting supplies a separate amplification factor. If is a uniform one-step Bellman-operator error, the induced fixed-policy value error is bounded on the order of . That statement does not follow from an unspecified transition prediction error. Simulation lemmas based on reward error and transition-kernel error usually contain a reward term proportional to and a transition term proportional to , with constants determined by reward bounds, the norm convention, and policy selection.
The amplification factor is worth seeing as a curve rather than a formula, because its growth is not gentle:
import numpy as np
GAMMA_GRID = np.linspace(0.50, 0.999, 300)
amplification = 1.0 / (1.0 - GAMMA_GRID)
gamma_marks = np.array([0.9, 0.99, 0.999])
mark_amplification = 1.0 / (1.0 - gamma_marks)
The markers make the arithmetic concrete: moving from to multiplies a fixed Bellman error by ten, so a fixed value-error budget permits ten times less one-step backup error. Moving to tightens the budget by another factor of ten.
Let's make compounding concrete with a small experiment. We take a damped pendulum, fit two models to a few thousand random-policy transitions, a linear model that is structurally misspecified for the nonlinear dynamics and a more flexible small neural network, and compare their one-step error against their open-loop rollout error. The experiment measures the resulting errors directly; it does not separately identify approximation bias, estimation error, and recursive feedback.
import numpy as np
from sklearn.linear_model import LinearRegression
from sklearn.neural_network import MLPRegressor
rng = np.random.default_rng(0)
DT = 0.1
def pendulum_next(s, a):
"""Deterministic damped pendulum: state is (angle, angular velocity)."""
theta, omega = s[0], s[1]
return np.array(
[
theta + DT * omega,
omega + DT * (-np.sin(theta) - 0.1 * omega + a),
]
)
rng = np.random.default_rng(0)
def collect_transitions(n_traj, horizon):
S, A, S2 = [], [], []
for _ in range(n_traj):
s = np.array([rng.uniform(-np.pi, np.pi), rng.uniform(-2.0, 2.0)])
for _ in range(horizon):
a = rng.uniform(-2.0, 2.0)
S.append(s)
A.append(a)
S2.append(pendulum_next(s, a))
s = S2[-1]
return np.array(S), np.array(A), np.array(S2)
S, A, S2 = collect_transitions(100, 20) # 2000 random-policy transitions
X = np.hstack([S, A[:, None]])
lin = LinearRegression().fit(X, S2)
mlp = MLPRegressor(
hidden_layer_sizes=(64, 64), max_iter=5000, random_state=0
).fit(X, S2)The raw linear model cannot represent the term exactly. The neural network is more flexible, but capacity alone does not guarantee lower held-out error. We therefore evaluate both models on exactly the same held-out initial states and action sequences.
eval_rng = np.random.default_rng(2026)
def predict_linear(s, a):
return lin.predict(np.append(s, a)[None, :])[0]
def predict_mlp(s, a):
return mlp.predict(np.append(s, a)[None, :])[0]
N_TEST_TRAJ, TEST_HORIZON = 50, 30
test_initial_states = np.column_stack(
[
eval_rng.uniform(-np.pi, np.pi, size=N_TEST_TRAJ),
eval_rng.uniform(-2.0, 2.0, size=N_TEST_TRAJ),
]
)
test_actions = eval_rng.uniform(-2.0, 2.0, size=(N_TEST_TRAJ, TEST_HORIZON))
def evaluate_model(predict):
n_traj, horizon = test_actions.shape
onestep_err = np.zeros(horizon)
rollout_err = np.zeros(horizon)
for initial_state, actions in zip(test_initial_states, test_actions):
s_true = initial_state.copy()
s_model = s_true.copy()
for t in range(horizon):
a = actions[t]
s_true_next = pendulum_next(s_true, a)
onestep_err[t] += np.mean((s_true_next - predict(s_true, a)) ** 2)
rollout_err[t] += np.mean((s_true_next - predict(s_model, a)) ** 2)
s_true, s_model = s_true_next, predict(s_model, a)
return onestep_err / n_traj, rollout_err / n_traj
err_lin_onestep, err_lin_rollout = evaluate_model(predict_linear)
err_mlp_onestep, err_mlp_rollout = evaluate_model(predict_mlp)
horizons = np.arange(1, TEST_HORIZON + 1)Both models see the same held-out trajectories. One-step error always starts from the true state; rollout error feeds each model's prediction back as its next input.
Linear model one-step MSE (steps 1-5): [0.0014 0.0013 0.0013 0.0012 0.0011] MLP model one-step MSE (steps 1-5): [0.0015 0.0014 0.0011 0.0013 0.0016] Linear model rollout MSE at step 30: 1.234 MLP model rollout MSE at step 30: 1.016


The panels support a narrower and more useful conclusion. On these paired trajectories, the two models have one-step errors of the same order, with no consistent winner over the first five steps. By step 30 the neural model has the lower rollout error. One-step ranking therefore does not determine long-horizon ranking, and recursive use must be evaluated directly. A trained policy would induce another test distribution, so these random-action results should not be generalized beyond the displayed experiment.
Model Exploitation and Distribution Shift
Compounding error degrades rollouts passively. A nastier failure mode is active: the decision machinery seeks out the model's errors.
Model exploitation occurs when optimization favors trajectories that look good under the learned model because of model error, for example an overestimated reward or implausibly convenient dynamics. Greater search pressure can increase this failure, but optimizer choice alone does not determine it.
The interaction is between optimization and distribution shift. A planner may steer toward unfamiliar states or actions where the model is unreliable; those regions need not be the true high-reward regions. If optimistic errors dominate there, additional planning can worsen real performance even while imagined return improves.
One common defense is model uncertainty. Bootstrap ensembles often provide a useful proxy for epistemic uncertainty. Disagreement can expose sensitivity to finite data, but it can miss shared model-class bias and is not automatically calibrated.
To see both the value and the limitation, fit quadratic models to bootstrap resamples of noisy sine data. The members share the same misspecified feature class, so their spread measures resampling sensitivity within that class, not total predictive uncertainty.
import numpy as np
from sklearn.linear_model import LinearRegression
rng = np.random.default_rng(7)
N_ENSEMBLE = 20
def make_features(x):
return np.column_stack([np.ones_like(x), x, x**2])
x_train = rng.uniform(-1.0, 1.0, size=60)
y_train = np.sin(2.0 * np.pi * x_train) + rng.normal(0.0, 0.1, size=60)
F_train = make_features(x_train)
x_eval = np.linspace(-1.6, 1.6, 200)
F_eval = make_features(x_eval)
ensemble_preds = np.zeros((N_ENSEMBLE, len(x_eval)))
for m in range(N_ENSEMBLE):
idx = rng.integers(0, len(x_train), size=len(x_train))
coef, *_ = np.linalg.lstsq(F_train[idx], y_train[idx], rcond=None)
ensemble_preds[m] = F_eval @ coef
pred_mean = ensemble_preds.mean(axis=0)
pred_std = ensemble_preds.std(axis=0)
true_curve = np.sin(2.0 * np.pi * x_eval)
covered = (x_eval >= -1.0) & (x_eval <= 1.0)
The widening band outside is a useful warning about extrapolation. The dashed truth also exposes the limitation: a thin band is not a certificate of correctness when all members share a misspecified quadratic class. An uncertainty penalty or rollout truncation can still be useful, but it should be calibrated and checked against control-relevant held-out data.
PETS averages over ensemble rollouts in its planner; many other methods add an uncertainty penalty directly to the objective. Other common defenses include:
- Short rollouts and branching. Generate imagined data only a few steps from real states, then bootstrap with the value function. This bounds compounding by construction: every imagined trajectory starts from ground truth and stays short. This is MBPO's core insight and, as we saw, it is also implicit in MPC's re-planning.
- Pessimism. One common implementation subtracts an uncertainty estimate from imagined reward so that unfamiliar, possibly-wrong regions look bad rather than promising. Other implementations use lower-confidence values, robust transition sets, constraints, or worst-case objectives. These constructions connect to the same pessimism principle used in offline RL.
- Model trust diagnostics. Before letting the agent act on a model, test it the way the qualification test from Part I: The World-Model Idea suggested: not only on held-out data, but on the distribution the policy will induce, and at the rollout lengths the decision machinery will use. A model validated only on its training distribution has not been validated at all, as far as the decision machinery is concerned.
Planner error and model error are distinct. A precise optimizer can expose optimistic model errors, while an approximate optimizer can simply be suboptimal. Robust objectives, constraints, uncertainty penalties, and real-environment validation are more principled controls than assuming that fewer optimizer iterations always make an uncertain model safer.