andrey.varma_lingam#
- andrey.varma_lingam(data, *, order=(1, 1), criterion=None, prune=False, structural_ma=False, max_iter=100)[source]#
Learn a temporal causal structure from one multivariate time series with VARMA-LiNGAM.
VARMA-LiNGAM [1] fits a vector autoregressive moving-average model, then applies LiNGAM to the residuals to fix a causal order over the instantaneous (contemporaneous) effects [2]. Use it when a single multivariate series carries both same-step and lagged causal influence.
- Parameters:
data (
ArrayLike) – A multivariate time series, one row per time step. Coerced tofloat64. A DataFrame’s column names become the structure’slabels.order (
tuple[int,int]) – The(p, q)autoregressive and moving-average lag counts, each at least0and not both0.criterion (
str|None) – Order-selection criterion. When set,(p, q)is chosen by that information criterion over0 <= p <= order[0]and0 <= q <= order[1], excluding(0, 0);Noneusesorderdirectly.prune (
bool) – Re-estimate the weights on the causal order: adaptive Lasso sets small weights to zero and least squares refits the rest. WithFalseevery lagged weight is nonzero, so every lag graph links every pair of variables, self-loops included.structural_ma (
bool) – How the moving-average weights are expressed:Truemaps them onto the independent noise terms,(I - B0) Theta_j (I - B0)^-1[1];Falseuses(I - B0) Theta_j.B0is the lag-0 weight matrix andTheta_jthe fitted moving-average coefficients. Ignored whenprune=True.max_iter (
int) – Most iterations of the likelihood fit, at least1. Withcriterionset, every fit in the grid gets this limit.
- Returns:
Wraps a
temporalTemporalStructure.structure.lag_weights[k][i, j]is the autoregressive weight of edgei -> jat lagk, lag 0 being instantaneous;structure.lag_weights_ma[k]holds the moving-average weights at lagk + 1, in the same orientation. The lag graphs follow the autoregressive weights.orderingis the instantaneous causal order, andmetadata["algorithm"]is"varmalingam".- Return type:
- Raises:
TypeError – If
orderis not a pair of ints, ormax_iteris not an int.ValueError – If
criterionis not one of"aic","bic","hqic", orNone, iforderholds a negative count or is(0, 0), ifmax_iteris below 1, or ifdatahas fewer than 2 columns.
Notes
DirectLiNGAM orders the innovations of the fitted model. Each pairwise regression in its ordering takes the least-squares slope, so every residual it scores is uncorrelated with its regressor in the sample.
With
prune=Trueeach variable is regressed on its causal predecessors at the same step, the lagged values of every variable, and the lagged independent noise terms. Adaptive Lasso selects the regressors, and an ordinary least-squares fit with an intercept on the selected ones gives their weights, so the kept weights are not shrunk toward zero. The noise terms come from a lag-0 matrix refit the same way. The regressions start at time stepmax(p, q): the first steps serve only as lagged values. No lagged value wraps around from the end of the series, so no step is regressed on a later one.Column order. The fit runs on the columns sorted by a rank computed from each column’s own data, as for
hc(), so reordering the columns relabels the result and changes nothing else, unless two columns are identical.Limitations. Measured on simulated linear series with non-Gaussian noise, one autoregressive and one moving-average lag, from 3 to 20 variables with 100 to 1,000 time steps, with
order=(1, 1)andprune=True. Its median errors (missing and extra cross-links) stayed below the empty graph’s from 300 time steps at every size; at 100 time steps they exceeded it from 10 variables on. The fit takes minutes at 20 variables and 1,000 time steps. It assumes linear effects and non-Gaussian noise. The likelihood fit can stop before it converges, and gives no warning; a largermax_iterdoes not prevent this. The result then depends on the versions of the numerical libraries, so the same series can give a different graph in another environment. Withcriterionset, it fits one model for every(p, q)in the grid.References
Examples
>>> import numpy as np >>> from andrey import varma_lingam >>> rng = np.random.default_rng(0) >>> x = rng.uniform(-1, 1, 300) >>> y = np.r_[0.0, 0.8 * x[:-1]] + rng.uniform(-1, 1, 300) >>> out = varma_lingam(np.column_stack([x, y]), order=(1, 1), prune=True) >>> out.structure.lag(1).oriented_edges() [(0, 1, 'directed')]