Skip to content

Application 6: the history backed out with the learning model

Question. In Applications 1-5 the history before the forecast origin is the one the RE model sees: the RE filter and smoother estimate the states and shocks, and the learners learn on those estimates. What history does the learning model itself back out of the data, and which shocks drove inflation in each version?

Three ways to run the history

Scenario history.mode What it does
a6_smooth_re 're_smoother' RE model; states and shocks from the RE smoother. Base of the RE decomposition
a6_smooth_learn 're_smoother' Learning on the RE-filtered history to 2026Q2 (the baseline history, as in Application 1)
a6_inv_learn 'inversion' The learning model backs out the shocks one quarter at a time: observables exogenised, shocks endogenised, beliefs and shares updated on the result
a6_kalman_learn, a6_kalman_re 'kalman' A time-varying Kalman filter of the model in force each quarter, with one-step prediction errors and a log likelihood

All of them move the origin to the last data quarter, 2026Q2, with a 4-quarter horizon:

function cfg = a6_smooth_learn()
cfg = a1_learn();
cfg.id = 'a6_smooth_learn';
cfg.forecast.origin = qq(2026, 2);
cfg.forecast.horizon = 4;
cfg.compare_with = {'a6_smooth_re'};
end

function cfg = a6_inv_learn()
cfg = a6_smooth_learn();
cfg.id = 'a6_inv_learn';
cfg.history.mode = 'inversion';
cfg.history.re_states = 'smoothed';   % required with 'inversion' (it is one-sided already)
cfg.compare_with = {'a6_smooth_learn'};
end

function cfg = a6_kalman_learn()
cfg = a6_smooth_learn();
cfg.id = 'a6_kalman_learn';
cfg.history.mode = 'kalman';
cfg.history.re_states = 'smoothed';   % required with 'kalman'
cfg.compare_with = {'a6_kalman_re'};
end

run_applications('app6') runs a6_smooth_re, a6_smooth_learn and a6_inv_learn, then the shock decompositions of inflation and output growth. The Kalman scenarios are run directly: hetlearn.run(a6_kalman_re()); hetlearn.run(a6_kalman_learn());.

The decompositions

The runner calls hetlearn.decompose for each of the three runs with five shock groups:

groups = struct('demand', {{'eb', 'eg', 'eqs'}}, 'monetary', {{'em'}}, 'supply', {{'ea'}}, ...
    'price_markup', {{'epinf'}}, 'wage_markup', {{'ew'}});
ids = {'a6_smooth_re', 'a6_smooth_learn', 'a6_inv_learn'};
rng = [qq(1966, 1), qq(2026, 2)];
for i = 1:numel(ids)
    D = hetlearn.decompose(ids{i}, {'pinfobs', 'dy'}, rng, struct('groups', groups));
end

Each call writes results/<id>/decomposition.csv. RE runs use IRIS contributions; learning runs use a time-varying decomposition with the model in force each quarter, plus a component beliefs_constants for the moving perceived means. Details: Shock decompositions.

Results

Filtered history (a6_smooth_learn) Inversion (a6_inv_learn)
Learners' share, end of 2022Q2 0.591 0.811
Learners' share, end of 2026Q2 0.632 0.999
Average share 1966Q1-2026Q2 0.523 0.558
  • The inversion reproduces the data: the seven observables to 4e-15 over 1966Q1-2026Q2 (check C9).
  • It needs different shocks. The backed-out price mark-up shocks epinf differ from the RE-smoothed ones by 1.25 standard deviations (RMS) over the whole sample and by 2.58 in 2021-2023; wage mark-up shocks by 0.63 and 1.10.
  • The learners' share is higher in the inverted history, and close to 1 by 2026Q2.

Average contribution to inflation over 2021Q1-2023Q4 (pp, annualised deviation from the steady state; total 1.72 pp in both):

Component RE smoother Learning, inversion
Price mark-up 3.42 6.24
Demand −1.52 −1.08
Monetary 0.95 0.36
Supply (productivity) −0.36 −1.88
Wage mark-up −0.77 −2.23
Intercept channel (perceived means) 0.00 0.30

Under learning, price mark-up shocks explain more of the 2021-2023 inflation, offset by larger negative supply and wage mark-up contributions.

The learners' share and beliefs over the filtered history are drawn in the Application 1 tutorial.

The Kalman history

history.mode = 'kalman' filters the data with the model in force each quarter (the beliefs and shares from the end of the quarter before), so it gives one-step prediction errors and a log likelihood for the learning model. On the 2026-10-20 runs, over 1966Q1-2026Q2:

RE(t-1), a6_kalman_re Learning, a6_kalman_learn
One-step RMSE, inflation (% q/q) 0.371 0.309
Log likelihood −2182.12 −1839.75
res = hetlearn.run(a6_kalman_learn(), 'save', false);
T = hetlearn.engine.kalman_history('rmse', res);    % T.table: RMSE by observable and subsample

A saved Kalman run also writes results/<id>/kalman_errors.csv (date, number of observables, log-likelihood contribution, errors, predictions and variances by observable). More in History modes.