MCMC#
- class MCMC(filter_obj: FilterOD | SolutionOD, verbose: bool = True, *, walkers_per_dimension: int = 4, min_walkers: int = 32, walker_spread: float = 1.0, max_initial_redraws: int = 100, stretch_scale: float = 2.0, de_weights: tuple = (0.7, 0.3), burn_in_factor: float = 2.0, thin_factor: float = 0.5, tau_multiple: float = 50, min_acceptance: float = 0.2)#
Bases:
FilterODMarkov chain Monte Carlo sampling of a converged orbit determination.
A filter (
LSB,SRIFB,LKF,SRIF, …) is first fitted to convergence. Its last pass fixes the reference trajectory, the prefit residuals \(y_k\), the measurement partials \(H_k\) and the STMs \(\Phi(t_k, t_0)\). About that reference the measurements are linear in the deviation \(x\) at the reference epoch,\[y_k = A_k x + \epsilon_k, \qquad A_k = H_k \Phi(t_k, t_0), \qquad \epsilon_k \sim \mathcal{N}(0, R_k),\]and the posterior of \(x\) is sampled with the affine-invariant ensemble sampler of
emcee:\[\log p(x \mid y) = -\frac{1}{2} \sum_k (y_k - A_k x)^T R_k^{-1} (y_k - A_k x) + \log p(x) + \mathrm{const}.\]No trajectory is propagated and no measurement is recomputed while sampling: every step costs two small matrix products. The data enter through the normal matrix and vector
\[D = \sum_k A_k^T R_k^{-1} A_k, \qquad d = \sum_k A_k^T R_k^{-1} y_k.\]Whitening
The walkers move in \(\theta\), with \(x = \hat{x} + L\theta\), where \(\hat{x} = M^{-1} b\) and \(L L^T = M^{-1}\) are the batch least-squares solution and covariance (\(M = \bar{P}_0^{-1} + D\), \(b = \bar{P}_0^{-1} \bar{x}_0 + d\)). With the filter’s Gaussian a-priori the log-posterior is then \(-\tfrac{1}{2}\theta^T\theta\), whatever the conditioning of \(M\). A user prior \(\log p\) replaces the Gaussian a-priori, and the log-posterior becomes
\[-\frac{1}{2} \theta^T L^T D L\, \theta + \theta^T L^T (d - D \hat{x}) + \log p(\hat{x} + L\theta - \bar{x}_0),\]up to a constant. The prior is evaluated on the deviation from the a-priori state, so a Gaussian \(\log p(\delta) = -\tfrac{1}{2}\delta^T \bar{P}_0^{-1}\delta\) reproduces the default.
Sequences
For a
MissionSequenceevery leg is mapped to one global vector \(z\): the first leg’s state at its epoch, followed by each block a later leg adds at its node, with its a-priori sigma. Leg \(j\) is \(x_j = T_j z\), with \(T_j = Q_j \Phi_{j-1}(t_{node}) T_{j-1}\) plus an identity on the blocks the node adds, so a measurement of leg \(j\) has \(A_k = H_k \Phi_j(t_k) T_j\). This is the batch ofLSB, with every leg mapped back through the nodes, as long as no considered state is dropped at a node: a dropped one stays considered in \(z\), whereas the filter folds its spread into the next leg’s a priori and lets that leg’s data reduce it (ConsiderDroppedWarning).Consider parameters
Considered states are not sampled. The walkers sample the estimated states with the considered ones at their reference, and the consider spread is added linearly as in the Schmidt batch: each particle draws \(c \sim \mathcal{N}(0, P_{cc})\) and is shifted by \(S_{xc} c\), with \(S_{xc} = -M_{xx}^{-1} M_{xc}\).
Solution
sample()returns aSolutionODwhose deviation and covariance histories are the chain mean and covariance (plus the consider part) mapped to every epoch with the STMs, and whose filter carriesparticles(the posterior samples mapped the same way), soSolutionOD.uq_metricsis filled. The samples at the reference epoch are also stored assamples, ready forplot_corner().- Parameters:
- filter_objFilterOD or SolutionOD
A filter fitted to convergence with
FilterOD.fit(), or the solution it returned. It is copied, not modified.- verbosebool, optional
Print the initialization banner. Defaults to
True.- walkers_per_dimensionint, optional
Walkers per estimated state when
sample()is not givenn_walkers. The stretch move needs more than twice the dimension; four times keeps the ensemble from collapsing onto a subspace. Defaults to 4.- min_walkersint, optional
Fewest walkers when
sample()is not givenn_walkers. Defaults to 32.- walker_spreadfloat, optional
Spread of the initial walkers, in units of the filter’s 1-sigma. The walkers are drawn from the converged filter’s Gaussian scaled by this factor, so with 1 the chain starts close to stationarity on the linearized problem and the burn-in is short. Defaults to 1.0.
- max_initial_redrawsint, optional
Times an initial walker is redrawn when the log-posterior is not finite at its position (a
log_priorthat rules out part of the Gaussian) beforesample()gives up. Defaults to 100.- stretch_scalefloat, optional
Scale parameter \(a\) of the affine-invariant stretch move of
moves="stretch", the default of Goodman & Weare (2010) and ofemcee. Defaults to 2.0.- de_weightstuple of float, optional
Relative weights of the differential-evolution and snooker moves of
moves="de";emceenormalizes them. Defaults to(0.7, 0.3).- burn_in_factorfloat, optional
Burn-in, in multiples of the largest integrated autocorrelation time of the chain, and at most half the chain. Defaults to 2.0.
- thin_factorfloat, optional
Thinning, in multiples of the smallest integrated autocorrelation time of the chain, and at least one step. Defaults to 0.5.
- tau_multiplefloat, optional
Chain length, in largest integrated autocorrelation times, below which the autocorrelation estimate (and with it burn-in and thinning) is not trusted, and
ShortChainWarningis issued. Thetoldefault ofemcee. Defaults to 50.- min_acceptancefloat, optional
Mean acceptance fraction below which the ensemble mixes poorly and
AcceptanceFractionWarningis issued. There is no upper bound: the stretch move scales its steps with the spread of the ensemble, so a high acceptance does not mean short steps. On the whitened, near-Gaussian posterior of a few states it is about 0.5 or more. Defaults to 0.2.
- Attributes:
labelsName of each entry of the global state
samplesholds.
Methods
fit(*args, **kwargs)Not supported: the source filter is fitted, then
sample()runs.sample([n_steps, n_walkers, moves, ...])Sample the linearized posterior and pack it as a solution.
- Raises:
- FilterTypeError
If
filter_objis not a filter (or the solution of one), or is itself anMCMC.- CovarianceAnalysisError
If the filter ran a covariance analysis: there are no residuals to sample from.
- UnfittedFilterError
If the filter was never fitted.
- FilterNotConvergedError
If the last fit did not converge: the linearization would not be about the solution.
- ProcessNoiseError
If the filter has process noise, which the batch posterior of the reference-epoch state cannot represent.
See also
scarabaeus.LSBThe Gaussian batch solution the chain reproduces.
scarabaeus.MonteCarloSamplesContainer of the reference-epoch samples.
scarabaeus.Plotting.plot_cornerCorner plot of the samples.
Notes
The sampled posterior is the linearized one: the dynamics and measurement models are not re-evaluated, so the chain reproduces the filter’s Gaussian unless a non-Gaussian prior is given. Its value is in the prior and in a sample-based uncertainty description consistent with the particle filters.
The source filter’s smoother, gain and innovation histories describe its own run, not the sampled posterior, and are not carried over.
The sampler settings,
walkers_per_dimensiontomin_acceptance, are kept as attributes of the same name, so they can also be changed between calls tosample().References
[1]Foreman-Mackey, D., Hogg, D. W., Lang, D., & Goodman, J. (2013). emcee: The MCMC Hammer. Publications of the Astronomical Society of the Pacific, 125(925), 306-312.
[2]Goodman, J., & Weare, J. (2010). Ensemble samplers with affine invariance. Communications in Applied Mathematics and Computational Science, 5(1), 65-80.
[3]Tapley, B. D., Schutz, B. E., & Born, G. H. (2004). Statistical Orbit Determination. Elsevier Academic Press.
- fit(*args, **kwargs)#
Not supported: the source filter is fitted, then
sample()runs.- Raises:
- FitNotSupportedError
Always.
- sample(n_steps: int = 5000, n_walkers: int | None = None, moves='stretch', log_prior: Callable[[ndarray], float] | None = None, n_particles: int = 1000, seed: int | None = None, meas_corr: list | None = None, progress: bool = False, verbose: bool = True) SolutionOD#
Sample the linearized posterior and pack it as a solution.
- Parameters:
- n_stepsint, optional
Steps of each walker. Defaults to 5000.
- n_walkersint, optional
Number of walkers, at least twice the number of estimated states. Defaults to
walkers_per_dimensionper estimated state, and at leastmin_walkers.- movesstr or emcee move(s), optional
"stretch"(affine-invariant stretch move, scalestretch_scale),"de"(differential evolution mixed with snooker moves,de_weights), or anymovesargument ofemcee.EnsembleSampler. Defaults to"stretch".- log_priorcallable, optional
Log-density of the prior, called on the deviation of the estimated states from their a-priori value (a 1-D array, in the order of the estimated entries of
labels). It replaces the filter’s Gaussian a-priori; return-np.infoutside the support. Defaults to the Gaussian a-priori.- n_particlesint, optional
Posterior samples kept as particles. Drawn from the burnt-in, thinned chain, with replacement only if it is shorter. Defaults to 1000.
- seedint, optional
Seed of the initial walkers, the sampler, the particle draw and the consider draws. Defaults to
None(not reproducible).- meas_corrlist, optional
Measurement correlation factors, as in
FilterOD.fit(). Defaults toNone.- progressbool, optional
Show the
emceeprogress bar. Defaults toFalse.- verbosebool, optional
Print the chain diagnostics. Defaults to
True.
- Returns:
- SolutionOD
The chain mean and covariance mapped to every epoch, the residuals about the mean, and
SolutionOD.uq_metricsof the particles. It is not saved; callSolutionOD.save().
- Raises:
- SampleSizeError
If
n_stepsorn_particlesis not positive.- NoEstimatedStatesError
If every state is considered.
- WalkerCountError
If
n_walkersis less than twice the number of estimated states.- UnknownMoveError
If
movesis an unknown name.- PosteriorCovarianceError
If the batch covariance is not positive definite.
- InitialWalkersError
If
log_prioris not finite at the redrawn initial walkers.- ConsiderPartitionError
If a state changes between estimated and considered at a node.
- AprioriSigmaSizeError
If a block added at a node has too few a-priori sigmas.
- Warns:
- ShortChainWarning
If the chain is short compared with its autocorrelation time.
- AcceptanceFractionWarning
If the mean acceptance fraction is below
min_acceptance.- ConsiderDroppedWarning
If a considered state is dropped at a sequence node.
Notes
Besides the solution this sets
samples(global state at the reference epoch, as deviations from the converged reference),chain(every step of every walker, estimated states only, shape(n_steps, n_walkers, n_estimated)),log_prob,diagnostics,posterior_meanandposterior_covariance.particleshas shape(n_particles, n, n_epochs), zero-padded on legs with fewer states.
- exception AcceptanceFractionWarning#
Bases:
UserWarningThe mean acceptance fraction is below
min_acceptance: the walkers mix poorly. Silence it withwarnings.filterwarnings("ignore", category=MCMC.AcceptanceFractionWarning).
- exception AprioriSigmaSizeError#
Bases:
ValueErrorA block added at a node has fewer a-priori sigmas than scalars.
- exception ConsiderDroppedWarning#
Bases:
UserWarningA considered state leaves the state vector at a sequence node. The chain keeps it considered over the later legs, whereas the sequential filters fold its spread into the next leg’s a priori, where that leg’s data reduce it, so the sampled posterior is not the filter’s. Keep the considered state in the later legs to match the filter, or silence it with
warnings.filterwarnings("ignore", category=MCMC.ConsiderDroppedWarning).
- exception ConsiderPartitionError#
Bases:
ValueErrorA state is estimated on one leg and considered on the next.
- exception CovarianceAnalysisError#
Bases:
ValueErrorThe filter ran a covariance analysis, so there are no residuals.
- exception FilterNotConvergedError#
Bases:
ValueErrorThe filter’s last fit did not converge.
- exception FilterTypeError#
Bases:
TypeErrorThe object to sample is not a fitted filter or its solution.
- exception FitNotSupportedError#
Bases:
NotImplementedErrorMCMC samples a fitted filter and does not fit itself.
- exception InitialWalkersError#
Bases:
ValueErrorThe log-posterior is not finite at any redrawn initial walker.
- exception NoEstimatedStatesError#
Bases:
ValueErrorEvery state is considered, so there is nothing to sample.
- exception PosteriorCovarianceError#
Bases:
ValueErrorThe batch covariance is not positive definite.
- exception ProcessNoiseError#
Bases:
ValueErrorThe filter has process noise, which the batch posterior cannot hold.
- exception SampleSizeError#
Bases:
ValueErrorThe number of steps or particles is not a positive integer.
- exception ShortChainWarning#
Bases:
UserWarningThe chain is shorter than
tau_multipletimes its largest autocorrelation time, so the burn-in, thinning and effective sample size are rough. Run more steps, or silence it withwarnings.filterwarnings("ignore", category=MCMC.ShortChainWarning).
- exception UnfittedFilterError#
Bases:
ValueErrorThe filter was never fitted.
- exception UnknownMoveError#
Bases:
ValueErrorThe move name is not one of the known ensemble moves.
- exception WalkerCountError#
Bases:
ValueErrorToo few walkers for the ensemble moves.