NSSDNResult.decompose#
- NSSDNResult.decompose(endog=None, *, exog=None, time=None, scaled=False)[source]#
Every path of the decomposition, for the fitted sample or a new one.
With no arguments this is the fitted sample’s decomposition, the same arrays the result carries as attributes, laid out as one dictionary. With
endogthe trained network is run over a new series under teacher forcing from its learned initial state \(h_0\), which is how the paper draws the full-sample figures: training and holdout concatenated, the network never refitted.- Parameters:
endog (
ArrayLike|None) – A series to run the trained network over under teacher forcing;Nonereturns the fitted sample’s paths. At least two observations.exog (
ArrayLike|None) –(len(endog), p)covariates forendog; required when the fit used covariates and refused otherwise.time (
ArrayLike|None) –(len(endog),)strictly increasing grid forendog; the integers whenNone.scaled (
bool) – Return the paths in training units (the scale the paper’s figures are drawn in, \([-1, 1]\) under min-max scaling) rather than on the original scale.observedis transformed to match.
- Return type:
- Returns:
Arrays keyed
observed, emission, trend, oscillation, amplitude_raw, amplitude, effective_amplitude, frequency, phase, phase_offset, gate, components, state, each with \(r\) rows (the length of the series under the filtered alignment, one fewer under the predicted one) and the column counts of the corresponding attributes.- Raises:
DimensionError – If
endogis not one-dimensional or too short, or ifexogortimeis misaligned with it, or if the covariate width differs from the fit’s.NumericalError – If any input contains non-finite values.
SpecificationError – If
timeis not strictly increasing.
Example
The paper’s trend figure is on the training scale:
>>> import numpy as np >>> y = np.sin(0.2 * np.arange(120.0)) + 5.0 >>> res = NSSDN(y, k=2, state_dim=8, schedule=(Stage(1e-2, 20),), seed=0).fit() >>> paths = res.decompose(scaled=True) >>> bool(paths["trend"].max() <= 1.0 + 1e-6), paths["trend"].shape (True, (120,))
Running over a longer sample does not refit; the first rows reproduce the fitted sample’s paths:
>>> longer = np.concatenate([y, np.sin(0.2 * np.arange(120.0, 150.0)) + 5.0]) >>> out = res.decompose(longer) >>> out["emission"].shape, bool(np.allclose(out["emission"][:120], res.emission)) ((150,), True)