Frontier Questions and Research Roadmaps › Experiment 2: Held-Out Combinations and When Factorization Fails

Michael BrenndoerferAugust 11, 202611 min read
World Models HandbookAll chapters
Part 12 of 12Reliable World Models
Chapter 72Frontier Questions and Research Roadmaps › Experiment 2: Held-Out Combinations and When Factorization Fails
Reading section 6 of 11 · Experiment 2: Held-Out Combinations and When Factorization Fails · 11 minSection 6 of 11 · 11 min

Book contents

Section 6 of 11 · 11 min read

Frontier Questions and Research Roadmaps › Experiment 2: Held-Out Combinations and When Factorization FailsOne section · Sections in this chapter6 / 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

The second experiment asks whether a factorized representation can predict combinations of factors it never saw together. We construct a transition family in which the true interaction between two context factors is multiplicative, so that an additive model is structurally wrong, and then we add a stress condition in which even the multiplicative assumption fails.

The product law supplies a specific interaction that the additive feature family cannot represent exactly across the chosen factor levels. Even when an additive law is correct, its finite-data estimation and held-out predictions can still be tested. Here we use a normalized quadratic damping term, −κv∣v∣-\kappa v|v|, and let the coefficient depend on two context factors; this is a declared toy law, not a universal physical drag model. The capped regime asks a separate question: how does the product-feature model behave when that law changes? A test supporting a model is not thereby rigged, but testing a violated assumption makes the boundary of the result explicit.

The Transition Family

The system is a scalar velocity with quadratic damping:

vt+1=vt+Δt(at−κ(s,p) vt∣vt∣)+ϵtv_{t+1} = v_t + \Delta t \left( a_t - \kappa(s, p) \, v_t |v_t| \right) + \epsilon_t

where:

  • vtv_t: scalar velocity at step tt
  • ata_t: action (normalized acceleration) at step tt
  • Δt=0.2\Delta t = 0.2: integration timestep
  • κ(s,p)\kappa(s, p): damping coefficient determined by the surface factor ss and payload factor pp
  • s∈{1,2,3}s \in \{1, 2, 3\}: surface factor level
  • p∈{1,2,3}p \in \{1, 2, 3\}: payload factor level
  • ϵt\epsilon_t: additive noise at step tt

where ss is a surface factor, pp is a payload factor, and both take levels in {1,2,3}\{1, 2, 3\}. The coefficient κ\kappa is what we will try to learn. In the main regime,

κmain(s,p)=s⋅p\kappa_{\text{main}}(s, p) = s \cdot p

In the stress regime, the damping saturates:

κstress(s,p)=min⁡(s⋅p,κmax⁡),κmax⁡=5\kappa_{\text{stress}}(s, p) = \min(s \cdot p, \kappa_{\max}), \qquad \kappa_{\max} = 5

Here κmax⁡\kappa_{\max} is the saturation ceiling: at high s⋅ps \cdot p the damping stops growing, so the true law is no longer a pure product.

The stress regime specifies a capped coefficient, κ=min⁡(sp,5)\kappa = \min(sp, 5). This is a deliberate alternative law, not a claim that every physical damping coefficient saturates. The held-out products are 3 and 6, so the test includes uncapped and capped combinations. A pure-product feature family is therefore misspecified in this regime. The coefficients and factors here are normalized toy quantities; the experiment does not establish a physical stability margin.

Rather than fit a full transition network, we estimate the single scalar κ\kappa for each context by least squares, then study how meta-models map context to κ\kappa. This controls the feature families and makes the scalar identifiability condition explicit. It does not remove estimation error: the finite noisy identification samples produce uncertain coefficient labels, and that uncertainty propagates into the meta-model errors alongside approximation error. Known ground truth lets us measure those errors, not declare the identification step exact. A real system may also permit scalar fitting, or may require a richer model with additional measurement and model errors.

In[21]:
Code
FACTOR_LEVELS = (1.0, 2.0, 3.0)
SEEN_COMBOS = [(1, 1), (1, 2), (2, 1), (2, 2), (3, 3)]
HELD_OUT_COMBOS = [(1, 3), (2, 3), (3, 1), (3, 2)]
DT_C = 0.2
KAPPA_CAP = 5.0
IDENT_NOISE = 0.4
N_SAMPLES = 60


def kappa_true(s, p, saturated):
    k = float(s) * float(p)
    return min(k, KAPPA_CAP) if saturated else k


def identify_kappa(s, p, saturated, rng, n_samples=N_SAMPLES):
    v = rng.normal(scale=1.2, size=n_samples)
    a = rng.uniform(-1.0, 1.0, size=n_samples)
    k = kappa_true(s, p, saturated)
    v_next = (
        v
        + DT_C * (a - k * v * np.abs(v))
        + IDENT_NOISE * rng.normal(size=n_samples)
    )
    regressor = -DT_C * v * np.abs(v)
    target = v_next - v - DT_C * a
    return float(regressor @ target / (regressor @ regressor))

The identification samples (v,a)(v, a) pairs independently rather than rolling the system forward. For this one-parameter least-squares fit, a unique coefficient estimate requires ∑i(Δt vi∣vi∣)2>0\sum_i (\Delta t\,v_i|v_i|)^2>0. More spread can improve information under the stated noise model, but a visual velocity range is not a general persistent-excitation test. Gaussian velocity samples have unbounded support; the code imposes no hard ∣v∣≤3|v|\leq3 limit.

The Split and the Two Meta-Models

Every factor level appears in training. What is held out is specific combinations: (1,3)(1,3), (2,3)(2,3), (3,1)(3,1), and (3,2)(3,2). The training set contains the diagonal (1,1),(2,2),(3,3)(1,1), (2,2), (3,3) and two symmetric off-diagonal cells (1,2)(1,2) and (2,1)(2,1).

The structure of the split is deliberate. Every level of ss and every level of pp appears in training, so the model has seen each factor individually. What it has not seen is the specific way high ss combines with high pp and vice versa. If the factors combine additively, the model can predict the held-out cells by extrapolating each factor's effect. If they combine multiplicatively, the model needs to know the product, and the training cells do not uniquely determine the product unless the model's functional form includes it. This is the sense in which the split tests the inductive bias rather than the data coverage.

Two meta-models map context to the damping coefficient:

  • Factorized (additive) baseline. κ^=b+wss+wpp\hat{\kappa} = b + w_s s + w_p p. No interaction term.
  • Interaction-capable baseline. κ^=b+wss+wpp+wspsp\hat{\kappa} = b + w_s s + w_p p + w_{sp} s p. Characterizes the multiplicative structure.

Both are fit by least squares on the training cells. We check the design matrix rank and condition number so we are not fitting an arbitrary solution.

In[22]:
Code
def fit_additive(pairs):
    X = np.array([[1.0, s, p] for s, p, _ in pairs])
    y = np.array([k for _, _, k in pairs])
    w, *_ = np.linalg.lstsq(X, y, rcond=None)
    return (lambda s, p: w[0] + w[1] * s + w[2] * p), X


def fit_interaction(pairs):
    X = np.array([[1.0, s, p, s * p] for s, p, _ in pairs])
    y = np.array([k for _, _, k in pairs])
    w, *_ = np.linalg.lstsq(X, y, rcond=None)
    return (lambda s, p: w[0] + w[1] * s + w[2] * p + w[3] * s * p), X


_rng_check = np.random.default_rng(3)
_check_seen = [
    (s, p, identify_kappa(s, p, False, _rng_check)) for s, p in SEEN_COMBOS
]
_, X_add = fit_additive(_check_seen)
_, X_int = fit_interaction(_check_seen)
print(
    f"Additive design rank: {np.linalg.matrix_rank(X_add)} of {X_add.shape[1]}"
)
print(
    f"Interaction design rank: {np.linalg.matrix_rank(X_int)} of {X_int.shape[1]}"
)
print(f"Interaction condition number: {np.linalg.cond(X_int):.1f}")
Out[23]:
Console
Additive design rank: 3 of 3
Interaction design rank: 4 of 4
Interaction condition number: 58.4

Both design matrices have full column rank, so least-squares coefficients are uniquely determined within each selected feature family. The reported interaction-design condition number diagnoses sensitivity for that matrix. These checks support the earlier section's model-family-specific identification discussion; they are not prerequisites for every held-out-combination performance test and do not establish identifiability for arbitrary nonlinear models.

Before comparing meta-models, we check the scalar identification procedure against analytic truth on the held-out cells. This diagnostic measures its error in the chosen unsaturated contexts; it does not make finite noisy labels exact. Downstream error still combines identification noise with estimation and functional-form error. Keep that contribution visible rather than attributing every discrepancy to the meta-model's structure.

In[24]:
Code
_rng_verify = np.random.default_rng(77)
verify_rows = []
for combo in HELD_OUT_COMBOS:
    s, p = combo
    est = np.mean([identify_kappa(s, p, False, _rng_verify) for _ in range(20)])
    verify_rows.append((s, p, kappa_true(s, p, False), est))

print(f"{'s':>3}{'p':>3}{'true kappa':>13}{'identified':>13}")
for s, p, truth, est in verify_rows:
    print(f"{s:>3}{p:>3}{truth:>13.3f}{est:>13.3f}")
Out[25]:
Console
  s  p   true kappa   identified
  1  3        3.000        2.984
  2  3        6.000        5.982
  3  1        3.000        3.028
  3  2        6.000        6.009

These diagnostic averages track the analytic coefficients closely in the unsaturated regime. Identification noise still enters every fitted meta-model, so held-out error combines that noise, estimation variance, and functional-form mismatch. The repeated study below measures this combined variability rather than attributing every error exclusively to structure.

Running Both Regimes with Repeats

We repeat the whole procedure eight times with fresh identification noise, so the error bars capture variation from sampling, identification and meta-model fitting under this fixed split. They are standard errors of each model's mean, not standard deviations of individual runs. Assess a model difference against uncertainty in its estimated mean difference; it need not exceed individual-run variability. The models share each repeat's training data, so paired repeat differences would provide a direct uncertainty estimate for their comparison. The separate marginal bars below do not supply that estimate.

In[26]:
Code
def run_composition_study(saturated, n_repeats=8, seed=0):
    rng = np.random.default_rng(seed)
    add_e = np.zeros((n_repeats, len(HELD_OUT_COMBOS)))
    int_e = np.zeros_like(add_e)
    seen_add_e = np.zeros((n_repeats, len(SEEN_COMBOS)))
    seen_int_e = np.zeros_like(seen_add_e)
    for r in range(n_repeats):
        seen = [
            (s, p, identify_kappa(s, p, saturated, rng)) for s, p in SEEN_COMBOS
        ]
        f_add, _ = fit_additive(seen)
        f_int, _ = fit_interaction(seen)
        for j, (s, p) in enumerate(SEEN_COMBOS):
            truth = kappa_true(s, p, saturated)
            seen_add_e[r, j] = abs(f_add(s, p) - truth)
            seen_int_e[r, j] = abs(f_int(s, p) - truth)
        for j, (s, p) in enumerate(HELD_OUT_COMBOS):
            truth = kappa_true(s, p, saturated)
            add_e[r, j] = abs(f_add(s, p) - truth)
            int_e[r, j] = abs(f_int(s, p) - truth)
    return add_e, int_e, seen_add_e, seen_int_e


add_main, int_main, seen_add_main, seen_int_main = run_composition_study(
    saturated=False, seed=101
)
add_stress, int_stress, seen_add_stress, seen_int_stress = (
    run_composition_study(saturated=True, seed=202)
)


def summarize(e):
    per_repeat = e.mean(axis=1)
    return float(per_repeat.mean()), float(
        per_repeat.std(ddof=1) / np.sqrt(len(per_repeat))
    )


summary = {
    ("Factorized", "Seen, multiplicative"): summarize(seen_add_main),
    ("Interaction", "Seen, multiplicative"): summarize(seen_int_main),
    ("Factorized", "Seen, saturating"): summarize(seen_add_stress),
    ("Interaction", "Seen, saturating"): summarize(seen_int_stress),
    ("Factorized", "Held-out, multiplicative"): summarize(add_main),
    ("Interaction", "Held-out, multiplicative"): summarize(int_main),
    ("Factorized", "Held-out, saturating"): summarize(add_stress),
    ("Interaction", "Held-out, saturating"): summarize(int_stress),
}
Out[27]:
Console
model         regime                      mean |err|      SEM
Factorized    Seen, multiplicative             0.450    0.005
Interaction   Seen, multiplicative             0.072    0.005
Factorized    Seen, saturating                 0.321    0.012
Interaction   Seen, saturating                 0.312    0.011
Factorized    Held-out, multiplicative         0.978    0.022
Interaction   Held-out, multiplicative         0.131    0.016
Factorized    Held-out, saturating             0.492    0.023
Interaction   Held-out, saturating             0.629    0.016
Out[28]:
Visualization
Grouped bar chart with standard error bars comparing held-out combination error for factorized and interaction meta-models under multiplicative and saturating regimes.
Absolute error in the predicted damping coefficient on held-out combinations of surface and payload for two meta-models under two regimes. Under the multiplicative law, the interaction model generalizes and the factorized model does not, whereas under saturation the advantage collapses because the interaction model's assumption is also violated.

Interpreting the Two Regimes

In the multiplicative regime the interaction model has much lower held-out coefficient error than the additive model. The table also reports error against analytic truth on seen combinations: training-side approximation error is part of this comparison, not something to assume away. The product feature represents the specified law, while the additive family cannot represent it over the full grid. Under the capped law that advantage does not persist. These results concern two chosen feature families and splits, not every factorized representation or a universal compositionality advantage.

Under saturation, the interaction model's held-out error increases, while the additive model's error decreases relative to its own multiplicative-regime result. The mean ranking reverses in this seeded study. Both remain misspecified: neither functional form represents the capped product exactly. This is not evidence that saturation always favors an additive model. The product feature has lower error under the product law here, and that advantage does not survive this cap. Misspecification alone does not establish operational unreliability: deciding whether either error is acceptable requires a task-specific tolerance. Test the target regime and report the measured errors against that requirement.

The practical implications are direct:

  • Test compositional claims with held-out combinations and report seen and unseen separately.
  • When interpreting recovered factor effects, establish identifiability under the chosen feature family and report its design rank. Keep this identification claim separate from measured held-out performance.
  • Include a violation condition so that the reader knows what happens when the assumed structure breaks.
  • Prefer a model whose inductive bias matches the regime you will deploy in. Justify that regime from known structure or an appropriately powered target-system study; a small trial need not detect rare or later changes.

A predeclared held-out comparison can be a valid test even when it supports the proposed method. Adding a violation condition asks a separate question: how does performance change when the assumed law no longer holds? The capped regime supplies that boundary check here; it does not make all positive-only studies invalid. For deployment, test the target regime and ask whether the measured errors meet its requirements rather than seeking an unconditional model ranking.

An illustrative controlled example with a known ground-truth transition family, not a benchmark result.