PerturbationDSGE.sample#
- PerturbationDSGE.sample(theta0, *, n_particles=500, n_draws=2000, n_burn=500, thin=1, proposal_scale=None, seed=None)[source]#
Particle marginal Metropolis-Hastings under the specification’s prior.
Each iteration proposes in the unconstrained space, estimates the likelihood with a fresh particle filter, and accepts by the pseudo-marginal ratio, which targets the exact posterior whatever the particle count; the count only governs mixing.
- Parameters:
theta0 (
ArrayLike) – Starting structural parameters; a point estimate fromfit()is the natural choice.n_particles (
int) – Particles per likelihood estimate. Pitt et al. (2012) suggest sizing it so the log-likelihood estimate’s standard deviation at the mode is near one.n_draws (
int) – Total iterations.n_burn (
int) – Burn-in, during which the proposal adapts.thin (
int) – Keep everythin-th post-burn draw.proposal_scale (
ArrayLike|None) – Initial proposal standard deviations in the unconstrained space,(d,), or a covariance(d, d);Nonefor0.1per coordinate.
- Return type:
_PerturbationDSGEPosterior- Returns:
The
_PerturbationDSGEPosteriorwith the kept draws, their log-likelihood and log-posterior values, the acceptance rate and convergence diagnostics.
Example
A short chain, far too short for inference, shows the shape of the surface:
>>> import numpy as np >>> class Latent: ... parameter_names, bounds = ("rho", "sigma"), ((0.0, 0.99), (0.01, 1.0)) ... n_states, n_controls = 1, 1 ... def equations(self, th, y_next, y, x_next, x): ... return np.array([y[0] - x[0], x_next[0] - th[0] * x[0]]) ... def steady_state(self, th): ... return np.zeros(1), np.zeros(1) ... def shock_loading(self, th): ... return np.array([[th[1]]]) ... def observation(self, th): ... return np.array([[0.0, 1.0]]), np.zeros(1), np.array([[1e-4]]) ... def log_prior(self, th): ... return 0.0 >>> rng = np.random.default_rng(0) >>> x = np.zeros(120) >>> for t in range(1, 120): ... x[t] = 0.8 * x[t - 1] + 0.5 * rng.standard_normal() >>> model = PerturbationDSGE(Latent(), x, order=2) >>> res = model.fit([0.5, 0.3]) >>> post = model.sample(res.theta, n_particles=100, n_draws=40, n_burn=10, seed=0) >>> post.n_kept, post.n_particles, bool(0.0 <= post.acceptance_rate <= 1.0) (30, 100, True)