Skip to content

Networks: choosing the decision-rule basis

The network is your approximation family for the decision rule π(s) — the role Chebyshev polynomials or splines play in a projection method. Picking one is not a deep-learning decision; it is the same modeling choice you already make when you decide what functions your policy is allowed to be.

The whole decision, in one line

Is your policy a function of today's state (Markov) or of a window of recent history? Markov is almost everything in macro — and the validated default is mlp. Reach for a sequence network only when the policy genuinely depends on the path, not just the point.

flowchart TD
    Q{"Does &pi; depend on the<br/>path, or just today's state?"}
    Q -->|"today's state s = (K, z)<br/>— almost all of macro"| M["Markov basis"]
    Q -->|"a window of recent history<br/>— rare, path-dependent"| H["History-dependent basis"]
    M --> MLP["mlp  (validated default)"]
    M --> LPM["linear_plus_mlp  (validated)<br/>BK linear rule + correction"]
    H --> LSTM["lstm / transformer<br/>(experimental)"]

The Markov choice (start here)

A Markov policy maps today's state to today's controls&pi;(s) → savings, consumption, labor, prices. This is the recursive-equilibrium setup behind almost every DSGE, RBC, and projection-method model you have written.

  • MLP — the validated default


    A flexible global approximator of π(s), bounded to the policy's admissible range. This is the basis the test suite and the gallery exercise. For any Markov policy, start here and don't look further unless something concrete breaks.

    network:
      type: mlp
      hidden_sizes: [128, 128]
      activation: tanh
    
  • LinearPlusMLP — when the basin is wrong


    Policy = Blanchard–Kahn linear rule + a zero-initialized MLP correction. At training step 0 the policy is the BK solution, so descent starts from a correct first-order floor. Reach for it when a bare MLP collapses to a wrong, low-residual fixed point.

    LinearPlusMLP

Both are validated; they share the same Markov interface

mlp and linear_plus_mlp are the two members of the small validated stack. They take the same state vector and return the same policy vector; linear_plus_mlp simply anchors the starting point to your first-order rule. For medium-scale DSGE where random init can land in the wrong attractor, it is the canonical fix — not a different category of object. It changes where descent starts, not which equilibrium gets selected: see the honest limits in the Method Zoo.

The history-dependent choice (rare, experimental)

If — and only if — your policy depends on a window of recent states [H, n_states] rather than the current point, the framework also offers two sequence bases. These are experimental: they work and are wired end-to-end, but they are lightly tested and outside the validated stack. Do not reach for them unless the economics is genuinely path-dependent.

A recurrent sequence policy: it consumes a history window and emits the current controls from the final hidden state.

network:
  type: lstm
  hidden_sizes: [64]
  history_len: 8

Multi-head self-attention over the same history window — useful when the policy benefits from longer context than a recurrence carries cleanly.

network:
  type: transformer
  hidden_sizes: [64]
  history_len: 16
  n_heads: 4

Experimental — not part of the validated stack

The validated recipe is adam + mlp (or linear_plus_mlp) + mse + antithetic Monte-Carlo. lstm and transformer are research instruments for path-dependent policies, not turnkey recommendations. If you reach for one, treat the errREE distribution on the ergodic path as the only verdict that counts — and check it against a Markov baseline first.

When to reach for each

You have… Use Status
A recursive policy in today's state — almost all macro mlp validated
A medium-scale DSGE where a bare MLP lands in the wrong basin linear_plus_mlp validated
A genuinely path-dependent policy (a window of history) lstm / transformer experimental
A CMR-style NK-DSGE with model-specific shape priors disaster_policy_net experimental

The canonical, current list always comes from the code:

uv run deqn-jax list   # registered models, to see which carry history
How Markov vs sequence dispatch works (reference)

There is one policy interface; the framework routes by input rank — an ndim check inside compute_residuals that resolves at trace time, so there is no per-step branching.

  • Markov networks take a state batch [B, D].
  • Sequence networks take a history window [B, H, D].

Episode simulation builds and maintains the window transparently via make_constant_history (seed a window by tiling the current state) and build_history_windows (slice a simulated trajectory into overlapping windows), both in training/history.py. A network advertises its memory through a history_len attribute; get_history_len returns 1 for a Markov net, so the two paths share all downstream loss and expectation code.

The full network cabinet (reference)

The decision-rule basis is one of the four orthogonal choices in the Method Zoo. The complete menu:

Network network.type Status
MLP mlp validated — the default basis
LinearPlusMLP linear_plus_mlp validated — BK floor + correction
LSTM lstm experimental — history window, recurrence
Transformer transformer experimental — history window, attention
DisasterPolicyNet disaster_policy_net experimental — LinearPlusMLP + CMR-specific priors
KfAnchoredMLP kf_anchored_mlp legacy — superseded by disaster_policy_net

The lineage that matters: mlplinear_plus_mlp (add a BK floor) → disaster_policy_net (add model-specific priors). Sequence nets sit on a separate axis — reach for them for path dependence, not for accuracy.


For the residual-ansatz math behind the canonical Markov upgrade, see LinearPlusMLP. For where the basis choice sits among optimizers, expectations, and diagnostics, see the Method Zoo.