API reference

andrey.core.ci_gpdc.GPDC#

class andrey.core.ci_gpdc.GPDC(data, *, n_null=1000, seed=None)[source]#

Gaussian-process regression, then a distance-correlation test of the residuals (GPDC).

Each query regresses x and y on the conditioning set with a Gaussian process, ranks the two residuals, and tests their distance correlation, which is zero only when they are independent. The null distribution of the ranked statistic depends only on the number of rows, so it is drawn once and reused by every query.

Parameters:
  • data (ndarray) – Observed data, one row per sample. Each column is standardized to unit variance.

  • n_null (int) – Draws of the null distribution of the distance correlation.

  • seed (int | None) – Seed for the null draws and the tie-breaking. None uses ANDREY_SEED, or 0 when it is unset.

Raises:

ValueError – If data is not 2-D, has fewer than 2 rows, contains NaN or infinity, or has values too large or too small to standardize, or n_null is below 1.

Notes

How it works. For a conditioning set z, x and y are each fitted by a Gaussian-process regression on z with a radial-basis-function kernel plus white noise, whose length scale and noise level maximize the marginal likelihood [2]; the residuals are the observations minus the fitted means. An empty conditioning set uses x and y themselves. A fit depends only on the variable and the conditioning set, so its residuals are kept on the test object and reused by every later query on the same pair of them. The residuals are replaced by their ranks, which gives them uniform marginals; tied values are ordered by a random key per row and variable, drawn once from seed, so that every ranking stays equally likely under the null. Each variable takes its keys, and its place among the regressors of a conditioning set, by its tie_ranks() rank, a rank computed from each column’s own data, so a p-value does not depend on the column order. The statistic is their squared distance correlation, from the doubly centered matrices of their pairwise distances [3]. After ranking, the null is the same statistic between the ranks and a random permutation of them, drawn n_null times [1]. With b of the n_null draws at least as large as the statistic, the p-value is (b + 1) / (n_null + 1): the observed statistic counts as one more draw, so the p-value is never zero [4].

Limitations. Measured in PC on simulated data from sparse random graphs (mean degree 2), each variable a weighted sum of z + sin(z), or of cos(z), over its parents plus Gaussian noise, with 20 datasets per size on 4 cores. At 5 variables with 500 to 2,000 rows, and 10 and 20 with 500 and 1,000, its median errors (SHD) stayed below the empty graph’s at every size. The median fit took 12 seconds to 2 minutes at 500 rows, and 15 minutes at 20 variables with 1,000 rows. The test assumes x and y depend on the conditioning set additively, a function of it plus noise; a dependence through the noise’s scale, such as x = z e, stays in the residuals and reads as conditional dependence. The null ignores the degrees of freedom the regressions use, as [1] does. Each regression costs the cube of the number of rows per optimizer step, so thousands of rows take seconds per query. The p-value is a multiple of 1 / (n_null + 1), and is at least that.

References