Source code for causalexplain.estimators.lingam.utils
"""
Python implementation of the LiNGAM algorithms.
The LiNGAM Project: https://sites.google.com/site/sshimizu06/lingam
"""
import numpy as np
from sklearn.linear_model import LassoLarsIC, LinearRegression
[docs]
def find_all_paths(dag, from_index, to_index, min_causal_effect=0.0):
"""Find all paths from point to point in DAG.
Parameters
----------
dag : array-like, shape (n_features, n_features)
The adjacency matrix to fine all paths, where n_features is the number of features.
from_index : int
Index of the variable at the start of the path.
to_index : int
Index of the variable at the end of the path.
min_causal_effect : float, optional (default=0.0)
Threshold for detecting causal direction.
Causal directions with absolute values of causal effects less than ``min_causal_effect`` are excluded.
Returns
-------
paths : array-like, shape (n_paths)
List of found path, where n_paths is the number of paths.
effects : array-like, shape (n_paths)
List of causal effect, where n_paths is the number of paths.
"""
# Extract all edges
edges = np.array(np.where(np.abs(np.nan_to_num(dag)) > min_causal_effect)).T
# Aggregate edges by start point
to_indices = []
for i in range(dag.shape[0]):
adj_list = edges[edges[:, 1] == i][:, 0].tolist()
if len(adj_list) != 0:
to_indices.append(adj_list)
else:
to_indices.append([])
# DFS
paths = []
stack = [from_index]
stack_to_indice = [to_indices[from_index]]
while stack:
if len(stack) > dag.shape[0]:
raise ValueError(
"Unable to find the path because a cyclic graph has been specified."
)
cur_index = stack[-1]
to_indice = stack_to_indice[-1]
if cur_index == to_index:
paths.append(stack.copy())
stack.pop()
stack_to_indice.pop()
else:
if len(to_indice) > 0:
next_index = to_indice.pop(0)
stack.append(next_index)
stack_to_indice.append(to_indices[next_index].copy())
else:
stack.pop()
stack_to_indice.pop()
# Calculate the causal effect for each path
effects = []
for p in paths:
coefs = [dag[p[i + 1], p[i]] for i in range(len(p) - 1)]
effects.append(np.cumprod(coefs)[-1])
return paths, effects
[docs]
def predict_adaptive_lasso(X, predictors, target, gamma=1.0):
"""Predict with Adaptive Lasso.
Parameters
----------
X : array-like, shape (n_samples, n_features)
Training data, where n_samples is the number of samples
and n_features is the number of features.
predictors : array-like, shape (n_predictors)
Indices of predictor variable.
target : int
Index of target variable.
Returns
-------
coef : array-like, shape (n_features)
Coefficients of predictor variable.
"""
lr = LinearRegression()
lr.fit(X[:, predictors], X[:, target])
weight = np.power(np.abs(lr.coef_), gamma)
reg = LassoLarsIC(criterion="bic")
reg.fit(X[:, predictors] * weight, X[:, target])
return reg.coef_ * weight