cultivars.multivariate.large_dim.graphical#

The graphical VAR: two networks, kept apart because they mean different things.

A large system carries two kinds of dependence and one covariance matrix cannot show both. Dynamic dependence – whose past moves whose present – lives in the coefficient matrices, and its sparsity pattern is a directed Granger network. Contemporaneous dependence – who comoves with whom within the period, given everyone else – lives in the precision of the innovations, and its sparsity pattern is an undirected partial-correlation network. The graphical VAR (Barigozzi and Brownlees, 2019) estimates both, separately and sparsely. The dynamics are a lasso VAR,

\[\hat A = \arg\min_A\ \tfrac{1}{2}\sum_t \bigl\lVert y_t - c - \textstyle\sum_{i=1}^{p} A_i y_{t-i} \bigr\rVert^2 + \lambda \sum_i \lVert A_i \rVert_1,\]

its penalty chosen by rolling-origin one-step forecast error along a geometric path from the zeroing level; the precision is then estimated on the residuals \(\hat u_t\) by Meinshausen-Buhlmann nodewise regressions, each residual on all the others,

\[\hat\gamma_{i\cdot} = \arg\min_\gamma\ \tfrac{1}{2}\sum_t \bigl(\hat u_{it} - \textstyle\sum_{j \ne i} \gamma_j \hat u_{jt}\bigr)^2 + \lambda_i \lVert \gamma \rVert_1, \qquad \hat\Theta_{ij} = -\tfrac{1}{2}\bigl(\hat\theta_{ii}\hat\gamma_{ij} + \hat\theta_{jj}\hat\gamma_{ji}\bigr),\]

with per-node penalties \(\lambda_i\) chosen by plain K-fold cross-validation, which is legitimate in the second stage precisely because residual rows carry no serial ordering worth respecting once the dynamics are removed, and the two one-sided estimates symmetrized by averaging.

Two commitments shape the surface. First, the two networks are read with their own grammars and never merged. A Granger edge is directed and temporal, a statement about the lasso support; a precision edge is undirected and conditional – zero means conditional independence given the other innovations, exactly under Gaussianity and as a partial-correlation zero otherwise. The result reports them through separate methods with separate thresholds, and the summary counts them separately. Second, neither network is a causal graph or a test. Edges are statements about the selected model under the selected penalties; no likelihood, information criteria or standard errors are reported, and the summary says that post-selection inference is an open problem rather than printing a p-value it cannot defend.

Layout. GraphicalVAR validates the specification on _SparseVectorAutoRegressionModel in _internals and shares its first stage with SparseVAR: _fit_sparse builds the geometric path, solves each level with _fista_penalized from _internals._solvers warm-started along the path, and selects by rolling-origin error; _fit_graphical then runs the nodewise regressions on the residuals with the same solver under K-fold selection and packs a _VectorGraphicalFit. GraphicalVARResult extends SparseVARResult, which supplies the closed-system surface, granger_adjacency and the path diagnostics. The forecast-error-variance reading of connectedness is spillover; the shrinkage alternative to sparsity is gibbs.

References

Barigozzi, M., & Brownlees, C. (2019). NETS: Network estimation for time series. Journal of Applied Econometrics, 34(3), 347-364.

Meinshausen, N., & Buhlmann, P. (2006). High-dimensional graphs and variable selection with the lasso. Annals of Statistics, 34(3), 1436-1462.

Basu, S., & Michailidis, G. (2015). Regularized estimation in sparse high-dimensional time series models. Annals of Statistics, 43(4), 1535-1567.

Example

A chain in the dynamics and two pairs in the innovations; the two networks are recovered separately, and neither sees the other’s structure:

>>> import numpy as np
>>> rng = np.random.default_rng(0)
>>> k, n = 5, 400
>>> theta = np.eye(k)
>>> theta[0, 1] = theta[1, 0] = -0.5
>>> theta[2, 3] = theta[3, 2] = 0.5
>>> chol = np.linalg.cholesky(np.linalg.inv(theta))
>>> coef = 0.5 * np.eye(k)
>>> coef[1, 0] = coef[2, 1] = 0.4
>>> y = np.zeros((n, k))
>>> for t in range(1, n):
...     y[t] = coef @ y[t - 1] + chol @ rng.standard_normal(k)
>>> res = GraphicalVAR(y, order=1).fit(seed=0)
>>> contemporaneous = res.contemporaneous_adjacency(threshold=0.3)
>>> [(i, j) for i in range(k) for j in range(i + 1, k) if contemporaneous[i, j]]
[(0, 1), (2, 3)]
>>> granger = res.granger_adjacency(threshold=0.2)
>>> [(i, j) for i in range(k) for j in range(k) if granger[i, j]]
[(1, 0), (2, 1)]
>>> bool(abs(res.coefficients[0][0, 1]) < 0.1), bool(abs(res.partial_correlations[1, 2]) < 0.1)
(True, True)

Classes#

GraphicalVAR

Graphical VAR, Barigozzi-Brownlees: sparse dynamics, sparse precision.

GraphicalVARResult

A fitted graphical VAR: the sparse dynamics plus the precision network.