特征相关性#
在特征归因的背景下,我们解决以下问题
特征对我的目标有多相关?
有多种方法可以解决这个问题。在此背景下,我们利用 Shapley 值概念以及经过特殊调整的集合函数,这些函数可以根据具体问题进行更改。在最常见的设置中,这类似于 SHAP 软件包。但是,我们提供了一种简单灵活的方法来修改集合函数,从而定制解释。
我们采用因果框架来处理这个问题,其中噪声(即未解释的部分)也作为模型的一个输入特征包含在内。换句话说,我们可以检查因果机制,它包括节点的父节点和噪声作为输入。
请参阅以下论文,以进一步了解如何将 Shapley 值解释为给定模型的因果解释
Dominik Janzing, Lenon Minorics, Patrick Blöbaum. 可解释人工智能中的特征相关性量化:一个因果问题 International Conference on Artificial Intelligence and Statistics, 2907-2916, 2021.
如何使用#
尽管也存在非因果用例,并且我们的工具也可用于这些用例,但我们首先来看一个使用节点因果机制的示例。像往常一样,我们首先生成一些示例数据
>>> import numpy as np, pandas as pd, networkx as nx
>>> from dowhy import gcm
>>> X = np.random.normal(loc=0, scale=1, size=1000)
>>> Z = np.random.normal(loc=0, scale=1, size=1000)
>>> Y = X + 3 * Z + np.random.normal(loc=0, scale=1, size=1000)
>>> data = pd.DataFrame(data=dict(X=X, Y=Y, Z=Z))
现在,有不同的选项来分析这一点。我们首先将其建模为因果模型
>>> causal_model = gcm.InvertibleStructuralCausalModel(nx.DiGraph([('X', 'Y'), ('Z', 'Y')])) # X -> Y <- Z
>>> gcm.auto.assign_causal_mechanisms(causal_model, data)
>>> gcm.fit(causal_model, data)
现在,我们可以评估父节点的全局相关性(总体/分布级别)
>>> parent_relevance, noise_relevance = gcm.parent_relevance(causal_model, target_node="Y")
>>> parent_relevance, noise_relevance
{('X', 'Y'): 1.1211907746332785, ('Z', 'Y'): 8.92516062224172}, [1.0313637]
在全局相关性的背景下,输入的关联性默认根据其对方差的贡献进行评估。在这里,我们可以看到父节点 \(Z\) 显然是最相关的特征。我们还可以看到噪声的关联性,在这种情况下,它等同于 \(X\) 的关联性。
在上面的示例中,我们直接利用了因果结构并估计了全局相关性。但是,我们也可以将此方法用于黑盒预测器。为此,我们以线性模型为例
>>> from sklearn.linear_model import LinearRegression
>>> from dowhy.gcm.util.general import variance_of_deviations
>>> mdl = LinearRegression()
>>> mdl.fit(data[['X', 'Z']].to_numpy(), Y)
>>> relevance = gcm.feature_relevance_distribution(mdl.predict, data[['X', 'Z']].to_numpy(), subset_scoring_func=variance_of_deviations)
>>> relevance
[0.98705591 8.95981759]
在这种情况下,我们直接将子集评分函数定义为偏差的方差,并获得了相似的结果。
最后,我们来看看个体观测值的相关性,而不是整个总体的相关性。为此,假设我们要解释以下观测值的相关性
>>> single_observation = np.array([[2, 1]])
在这里, \(X = 2\) 和 \(Z = 1\),导致 \(Y = 5\)。让我们评估一下这个单独观测值的相关性
>>> from dowhy.gcm.util.general import means_difference
>>> relevance = gcm.feature_relevance_sample(mdl.predict, data[['X', 'Z']].to_numpy(), baseline_samples=single_observation, subset_scoring_func=means_difference)
>>> relevance
[[2.01652995 3.04522823]]
正如预期的那样,即使 \(X\) 的值比 \(Z\) 大,由于其系数,\(Z\) 对于模型的输出更相关。
注意:与此处的其他方法类似,虽然我们使用线性关系演示并验证了该方法,但它也可以处理任意非线性关系。