API reference

andrey.ica_lingam#

andrey.ica_lingam(data, *, random_state=None, max_iter=1000)[source]#

Learn a fully oriented DAG with ICA-LiNGAM (linear, non-Gaussian noise).

ICA-LiNGAM uses FastICA to estimate an unmixing matrix, which separates mixed signals. It reorders this matrix into a causal order [1]. It estimates edge weights by regressing each variable on those before it, using adaptive Lasso. Like DirectLiNGAM, it returns one weighted DAG (directed acyclic graph) with a total ordering, rather than an equivalence class. FastICA starts from a random point, so the order can change with random_state.

Parameters:
  • data (ArrayLike) – Observed data, one row per sample. Coerced to float64. A DataFrame’s column names become the structure’s labels.

  • random_state (int | None) – Seed for FastICA’s starting point, from 0 to 2**32 - 1. None uses the ANDREY_SEED environment variable, or 0 when it is unset.

  • max_iter (int) – Maximum FastICA iterations; at least 1.

Returns:

Wraps a dag GraphStructure; metadata["algorithm"] is "ICALiNGAM". ordering is the causal order as a tuple of column indices, causes first. weighted_adjacency[i, j] is the coefficient of edge i -> j, estimated by adaptive Lasso; the DAG has an edge exactly where the coefficient is nonzero.

Return type:

StructureOutput

Raises:
  • RuntimeError – If no causal order can be read from the FastICA result.

  • TypeError – If max_iter is not an int.

  • ValueError – If max_iter is less than 1, if random_state is outside 0 to 2**32 - 1, or if data has fewer than n_variables + 1 rows, the fewest with which the pruning step can estimate the edge weights.

Warns:

sklearn.exceptions.ConvergenceWarning – When FastICA does not converge within max_iter iterations.

See also

andrey.direct_lingam

The same model with a deterministic order search; it recovered most edges on the published benchmarks.

Notes

When to use it. ICA-LiNGAM assumes linear effects, independent non-Gaussian noise, and no unmeasured common causes, like direct_lingam(). On the published benchmark data, it scored worse than the empty graph at the benchmarks’ sample size, while DirectLiNGAM recovered most edges. Prefer direct_lingam() unless ICA is needed.

Choosing random_state and max_iter. Different values of random_state can give different orders; compare a few when the result matters. If FastICA reaches max_iter before converging, scikit-learn issues a ConvergenceWarning; then raise max_iter.

Column order and machines. When several variables can come next in the causal order, the one whose column ranks first by its own values goes first. FastICA itself can reach another solution under a new column order or on another machine when it converges slowly, at few rows per variable; the column-order guide gives the measured limit.

Limitations. Measured on simulated data from scale-free graphs with linear effects and uniform noise, from 20 to 100 variables with ten rows per variable: its median errors (SHD) passed the empty graph’s at every size, 27 against 19 at 20 variables and 181 against 99 at 100. The median fit took 0.44 s at 20 variables and 15.8 s at 100, on 16 cores. On Sachs’s protein-signaling data (853 rows, 11 variables), its errors were below the empty graph’s (14 against 17).

References

Examples

>>> import numpy as np
>>> from andrey import ica_lingam
>>> rng = np.random.default_rng(0)
>>> x = rng.uniform(-1, 1, 500)
>>> y = 0.8 * x + rng.uniform(-1, 1, 500)
>>> out = ica_lingam(np.column_stack([x, y]), random_state=0)
>>> out.structure.kind
'dag'