API reference

andrey.anm#

andrey.anm(data, *, alpha=None)[source]#

Test the direction of a variable pair with the additive noise model (ANM).

ANM [1] fits y = f(x) + e in each direction by Gaussian-process regression. An HSIC test [2] checks whether the residual e is independent of the proposed cause, which holds only in the causal direction. The two p-values determine the edge, and the two test statistics decide a tie.

Parameters:
  • data (ArrayLike) – The two variables, one per column: column 0 is x and column 1 is y. Coerced to float64. A DataFrame’s column names become the structure’s labels.

  • alpha (float | None) – None chooses the direction with the larger p-value, or with the smaller test statistic when the p-values are equal. A significance level such as 0.05 draws an edge only when exactly one p-value exceeds it. See Notes.

Returns:

Contains a two-node GraphStructure of kind dag with the chosen edge, or no edge. metadata["algorithm"] is "ANM"; pval_forward is the independence p-value for x -> y and pval_backward is the p-value for y -> x; stat_forward and stat_backward are the HSIC statistics of the same two tests, each divided by its mean under independence.

Return type:

StructureOutput

Raises:

ValueError – If data does not have 2 columns, or if alpha is not in (0, 1).

Notes

With alpha=None, the edge points in the direction with the larger p-value. On a large sample, or a pair that fits neither direction, both p-values can be zero; equal p-values leave the choice to the HSIC statistics, each divided by its mean under independence, and the edge points in the direction with the smaller one, the weaker dependence between the proposed cause and its residual. Equal statistics give no edge. The rule therefore produces an edge even for unrelated variables, a deterministic pair whose p-values are both near zero, or a pair whose direction cannot be identified. Mooij et al. (2016) [3] compare p-values to avoid choosing a significance level and found the comparison among the best methods in their benchmark.

With a significance level, only the p-values decide; a direction passes when its p-value exceeds alpha:

  • only x -> y passes: the edge x -> y;

  • only y -> x passes: the edge y -> x;

  • both pass: no edge, since neither direction is rejected;

  • neither passes: no edge, since both directions are rejected.

Hoyer et al. (2008) [1] use a level of 0.02. Both p-values and both statistics remain in metadata.

The direction is identifiable when f is nonlinear or the noise is non-Gaussian; a linear pair with Gaussian noise fits an additive noise model in both directions [1].

Each column is standardized to zero mean and unit variance first, so the result does not depend on the units of either variable. The regression is a Gaussian process with a scaled RBF kernel plus a white-noise term, its hyperparameters fitted by maximum marginal likelihood. The HSIC test uses Gaussian kernels and a gamma approximation of its null distribution. The fit is deterministic.

Limitations. Measured on simulated cause-effect pairs with a nonlinear additive-noise mechanism and Gaussian noise, from 200 to 8,000 rows. It named the true direction on three pairs in four at 200 rows and on every pair from 4,000 rows. The median fit took over three minutes at 8,000 rows, on 4 cores. Each regression and HSIC test builds matrices with one row and one column per sample, so memory grows with the square of n_samples and the regression’s time with its cube.

References

Examples

>>> import numpy as np
>>> from andrey import anm
>>> rng = np.random.default_rng(0)
>>> x = rng.uniform(-1, 1, 300)
>>> y = x * x * x + 0.3 * rng.uniform(-1, 1, 300)
>>> out = anm(np.column_stack([x, y]))
>>> out.structure.oriented_edges()
[(0, 1, 'directed')]
>>> out.metadata["pval_forward"] > 0.05 >= out.metadata["pval_backward"]
True