可解释性机器学习:从入门到实战

一、可解释的特性:

目前人工智能应用已经渗透到我们生活的方方面面,成为我们生活中重要的一部分。我们相信,随着机器学习技术的不断进步,未来,有望产生一个能够感知,学习,做出决策和采取独立行动自主系统。 但是,如果这些系统无法向人类解释为何作出这样的决策,那么它们的有效性将会受到限制。用户要理解,信任和管理这些人工智能”合作伙伴“,可解释AI则至关重要。

1.1 可解释的重要性:

  • 模型改进:
    通过可解释分析,可以指导特征工程。一般我们会根据一些专业知识和经验来做特征,同构分析特征重要性,可以挖掘更多有用的特征,尤其是在交互特征方面。当原始特征众多时,可解释性分析将特别重要。
    在做机器学习任务时,我们一般会选择一个指标,比如准确率,然后尽可能优化。假设在一个文本分类任务中,判断文章是与“基督教”(Christianity)有关还是“无神论教”(Atheism)”,模型准确率,90%多,很高了。但是用LIME进行可解释分析发现,Posting(邮件标头的一部分)这个词重要性很高,但这个词汇与无神论本身并没有太多的联系,只是因为在无神论文章中出现的频次很高。这意味着尽管模型准确率很高,但所使用的原因是错误的。我们可以借此来改进模型,是否捕捉到了有意义的特征,以提高泛化性。
    在这里插入图片描述

  • 模型的可信和透明度:
    在我们做型的时候,需要在两个方面之间进行权衡,仅仅想要知道预测是什么,还是要知道模型为什么要给出这样的预测。在一些低风险的情况下,不一定要知道决策是如何做出的,比如推荐系统,广告、视频或者商品推荐等。但是在其他领域,比如在金融和医疗领域,模型的预测结果将会对相关的人产生巨大的影响,有时候我们依然需要专家对结果进行解释。解释为什么一个机器学习模型将某个患者的肿瘤归类为良性或恶性,解释为什么模型会拒绝一个人的贷款申请,这样,专家更有可能信任机器学习模型给出的预测结果。
    长久来看,更好地理解机器学习模型可以节省大量时间、防止收入损失。如果一个模型没有做出合理的决定,在应用这个模型并造成不良影响之前,我们就可以发现这一点。
    我们在面对客户的时候,他们会问 ”我为什么要相信你的模型“。如果客户不相信模型和预测结果,就无法使用这个模型,将其部署在产品中。

  • 识别和防止偏差:

方差和偏差是机器学习中广泛讨论的话题。有偏差的模型经常由有偏见的事实导致,如果数据包含微妙的偏差,模型就会学习下来并认为拟合很好。一个有名的例子是,用机器学习模型来为囚犯建议定罪量刑,这显然反映了司法体系在种族不平等上的内在偏差。其他例子比如用于招聘的机器学习模型,揭示了在特定职位上的性别偏差,比如男性软件工程师和女性护士。机器学习模型在我们生活的各个层面上都是强有力的工具,而且它也会变得越来越流行。所以作为数据科学家和决策制定者来说,理解我们训练和发布的模型如何做出决策,让我们可以事先预防偏差的增大以及消除他们,是我们的责任。

1.2 可解释性的范围:

1.2.1. 算法透明度(Algorithm Transparency):*

How does the algorithm create the model?

算法透明度指的是,如何从数据中学习一个模型,更加强调模型的构建方式以及影响决策的技术细节。比如CNN来对图片进行分类时,模型做出预测,是因为算法学习到了边或者其他纹理。算法透明度需要弄懂算法知识而不是数据以及学到的模型。对于简单的算法,比如线性模型,具有非常高的算法透明度。复杂的模型如深度学习,人们对模型内部了解较少,透明度较差,这将非常重要的一个研究方向。由于业务可能不太精通这些技术细节,本文集中于模型的全局和局部可解释性,而不是算法的可解释性(透明度)。

在这里插入图片描述

1.2.2 全局可解释(Global Interpretability):

How does the trained model make predictions?

为了解释模型的全局输出,需要训练模型了解算法和数据。这个层级的可解释性指的是,模型如何基于整个特征空间和模型结构、参数等作出决策的。什么特征是重要的,特征交互会发生什么。模型的全局可解释性可以帮助理解,针对不同特征,目标变量的分布是什么。实际在,模型具有大量参数的情况下,人们很难想象 特征之间是如何相互作用的,以得到这样的预测结果。

某些模型在这个层级是可以解释的。例如线性模型的权重是可以解释的,树模型如何划分分支和如何得到结点预测值是可以解释的。

1.2.3 局部可解释(Local Interpretability):

Why did the model make a certain prediction for an/a group of instance?

局部可解释性更加关注单条样本或一组样本。这种情况下我们可以将模型看做是一个黑盒,不再考虑模型的复杂情况。单条样本来看,模型给出的预测值和某些特征可能是线性关系,甚至是单调关系。因此局不可解释性可能相比全局可解释,更加准确点。

二、与模型无关的方法:

获得可解释性的一个非常容易的方法是使用一系列可解释的模型,比如线性回归,逻辑回归,决策树等。这些模型已经有很多文章详细解释,本文不再介绍,以与模型无关的方法为主。与模型无关也就是可以适用于任何模型,和模型的内部结构无关。

2.1 Permutation Feature Importance:

Permutation Importance是一种计算模型特征重要性的算法。特征重要性是指,一个特征对预测的贡献有多大。某些模型,例如LR、决策树,lightgbm等模型可以直接计算特征重要性。

基本思想:
假设要研究特征 i i i的重要性,那么将这列数据打乱,其他列的数据保持不变,然后观察预测的metric(eg.准确率)或者loss变化了多少,根据变化量来决定特征重要性。如果打乱以后对准确率没什么影响的话,可以认为这个特征没什么作用,特征重要性很低。

2.1.1 实例:

1. 读取数据预测每个人的年收入:
使用的数据集从1994年的人口普查局数据库中提取。根据人的一些基本信息来预测一个人每年的收入是否超过5万美元。数据的下载链接

feature_names = ["Age", "Workclass", "fnlwgt", "Education", "Education-Num", "Marital Status","Occupation", "Relationship", "Race", "Sex", "Capital Gain", "Capital Loss","Hours per week", "Country"]
data = np.genfromtxt('adult.data', delimiter=', ', dtype=str)
data = pd.DataFrame(data, columns=feature_names+['label'])

2. 数据预处理:

labels = data.iloc[:,14]
le= LabelEncoder()
le.fit(labels)
labels = le.transform(labels)
class_names = le.classes_
# data = data[:,:-1]

categorical_features = [1,3,5, 6,7,8,9,13]

categorical_names = {}
for feature in categorical_features:
    le = LabelEncoder()
    le.fit(data.iloc[:, feature])
    data.iloc[:, feature] = le.transform(data.iloc[:, feature])
    categorical_names[feature] = le.classes_
    
data[feature_names] = data[feature_names].astype(float)
encoder = OneHotEncoder(categorical_features=categorical_features)

3. 训练XGBoost模型以及XGB的特征重要性:

np.random.seed(1)
train, test, labels_train, labels_test = sklearn.model_selection.train_test_split(data[feature_names], labels, train_size=0.80)

# encoder.fit(data)
# encoded_train = encoder.transform(train)
# encoded_test = encoder.transform(test)

gbtree = xgb.XGBClassifier(n_estimators=2000, max_depth=4, learning_rate=0.05, n_jobs=8)
gbtree.fit(train, labels_train,eval_set=[(test, labels_test)], eval_metric='auc', verbose=100, early_stopping_rounds=100)

在这里插入图片描述
4. Permutation Feature Importance-slearn:

from sklearn.inspection import permutation_importance
result = permutation_importance(clf, train_x, train_y, n_repeats=10,random_state=42)
featImp = pd.DataFrame()
featImp['feat'] = feature_names
featImp['importance'] = result.importances_mean
featImp = featImp.sort_values('importance',ascending = False)

plt.figure(figsize=[20,10])
sns.barplot(x = 'importance', y = 'feat',data = featImp[:20],orient='h')
plt.show

在这里插入图片描述
从上述两个重要性可以看出,xgb自带的特征重要性和Permutation Importance求出的有所差异,可以综合的生成特征重要性,辅助特征选择。如果Permutation Feature Importance是负的,说明扰乱以后预测效果反而提升了,这种特征应该删除,其他较小的可以删除。

5. Permutation Feature Importance-eli5:

import eli5
from eli5.sklearn import PermutationImportance
perm = PermutationImportance(clf, n_iter=10)
perm.fit(train_x, train_y)
eli5.show_weights(perm, feature_names=train_x.columns.tolist())

在这里插入图片描述
eli5求出的结果和sklearn给出的实现基本一样,后面的几个特征的重要性稍微有些差异,说明这种方法的稳定性还是可靠的。

2.2 Partial Dependency Plots:

通过permutation importance可以得到特征的重要性,但是不知道不同的特征值如何影响预测结果的。PDP可以求得特征和预测结果的关系。

部分依赖图(Partial Dependency Plots-PDP)展示的是,对一个机器学习模型,一个或者两个特征的边际效应。由PDP我们可以得到目标值(target)和特征的关系,是线性、单调还是更复杂的关系。如果线性模型,特征和目标值之间则是线性关系。PDP的计算需要满足一个假设,所有的特征,是两两不相关的,如果相关就会出现问题,见PDP的缺点部分。

回归问题的部分依赖函数:
f ^ x S ( x S ) = E x C [ f ^ ( x S , x C ) ] = ∫ f ^ ( x S , x C ) d P ( x C ) \hat{f}_{x_{S}}\left(x_{S}\right)=E_{x_{C}}\left[\hat{f}\left(x_{S}, x_{C}\right)\right]=\int \hat{f}\left(x_{S}, x_{C}\right) d \mathbb{P}\left(x_{C}\right) f^xS(xS)=ExC[f^(xS,xC)]=f^(xS,xC)dP(xC)

  • x S x_S xS:PDP所需要绘制的特征;
  • x C x_C xC:模型中使用的其他特征;

其实上述式子,便是一个连续分布边际概率的求解公式。我们可以通过Monte Carlo方法在训练集上得到估计值,求特征 x C x_C xC对预测的影响:
f ^ x S ( x S ) = 1 n ∑ i = 1 n f ^ ( x S , x C ( i ) ) \hat{f}_{x_{S}}\left(x_{S}\right)=\frac{1}{n} \sum_{i=1}^{n} \hat{f}\left(x_{S}, x_{C}^{(i)}\right) f^xS(xS)=n1i=1nf^(xS,xC(i))

PDP分析步骤:

  1. 训练一个机器学习模型(假设特征是 F 1 … F 4 F_1 … F_4 F1F4 y y y是目标变量, F 1 F_1 F1是最重要的特征);
  2. 我们想探索探索 y y y F 1 F_1 F1的直接关系, F 1 F_1 F1的取值是 ( a 1 , a 2 , a 3 , . . . , a n ) (a_1, a_2, a_3,...,a_n) (a1,a2,a3,...,an)
  3. a 1 a_1 a1代替 F 1 F_1 F1列,利用训练的模型对这些数据进行预测,求所有样本的预测的平均值;
  4. ( a 2 , a 3 , . . . , a n ) ( a_2, a_3,...,a_n) (a2,a3,...,an)重复步骤3,即遍历特征 F 1 F_1 F1的所有不同值;
  5. PDP的X轴为特征 F 1 F_1 F1的各个值,而Y轴是对应不同 F 1 F_1 F1值的平均预测平均值;

例如我们的数据集包含三个样本,每个样本有三个特征,A,B,C。

在这里插入图片描述

我们想要知道特征A是如何影响预测结果的。假设特征A一共有三种类型: A 1 , A 2 , A 3 A_1, A_2, A_3 A1,A2,A3。训练数据其他特征保持不变,特征A依次修改为各个特征值,然后对预测求平均值。

在这里插入图片描述

最后PDP需要的是我针对不同特征值的平均预测值。

在这里插入图片描述

2.2.1 优缺点:

优点:

  • 计算直观:在某个特征取特定值时,对预测取平均值;
  • 解释清晰:PDP展示了随着特征值的改变,预测值的改变情况;
  • 容易实现

缺点:

  • 最多考虑两个特征:空间维度的限制,超过三维我们无法想象。如果不用图像显示特征分布,很难解释规律性。
  • 独立性假设,需要满足特征两两独立,如果特征之间存在相关性,所求结果不合理;
  • 异步效应可能被隐藏:特征变化对整个数据集带来的影响,也许一半数据集预测增加,一半介绍,取平均将是不变;

2.2.2 实例:

和上述一样,仍然选择预测每个人的年收入是否会超过50k这个数据集,使用XGBoost模型

1. Age的PDP:

pdp_fare = pdp.pdp_isolate(
    model=gbtree, dataset=data, model_features=feature_names, feature='Age'
)
fig, axes = pdp.pdp_plot(pdp_fare, 'Age')

在这里插入图片描述
y轴是预测值的变化量,蓝色区域是置信区间。从图中可以看出,中年人,30多岁到60岁,有更高的PDP值,有更高的可能收入大于50K,相比少年和年老的 人,这和我们的常识是相统一的。

4.不同Age的收入大于50k的比率:

fig, axes, summary_df = info_plots.target_plot(
    df=data, feature='Age', feature_name='age', target='label', show_percentile=True
)

在这里插入图片描述
从图中发现,随着年龄的上升,收入大于50k的概率越来越高,超过一定年龄后会下降,这和PDP得出的结果是对应的。

5. Education-Num和Age的交互PDP(交叉特征):

plots_list = interpreter.partial_dependence.plot_partial_dependence([('Age', 'Education-Num')], 
                                                                    im_model, grid_range=(0,1), 
                                                                    figsize=(12, 5),
                                                                    grid_resolution=100)

在这里插入图片描述
从图中发现,教育水平低的话,中年人收入大于50k的可能性仍然不高。随着接受教育时间的增加,同等年龄收入大的可能性更大一些。

7. Education-Num和Age交叉特征

fig, axes, summary_df = info_plots.target_plot_interact(
    df=data, features=['Age', 'Education-Num'], feature_names=['Age', 'Education-Num'], target='label'
)

在这里插入图片描述
从图中可以看出,真实的收入水平和Age&Education-Num的关系和刚才求得的PDP值非常接近,

2.3 ICE(Individual Conditional Expectation):

PDP有一个缺点,它描述的是特征变化对整个数据集的影响,ICE能深入到单个样本,分析特征变化对单个样本的影响。求解过程和上述PDP类似,但是ICE会给出每一个样本的预测值。
在这里插入图片描述
ICE的作者[2]认为,至少通过这种方式,任何有兴趣的点将不会因为求平均值而难以发现,论文中给出的例子如下图所示:

在这里插入图片描述

如上述例子,如果仅看图b的PDP,会认为特征x_2和预测值无关 ,实际上如果看图a,会发现结论是错误的。这样通过绘制individual conditional expectation(ICE)曲线,一切将会变得显而易见。在求解Fare的PDP时,我们会得到一个蓝色的置信区间,而置信区间便是由一条条的ICE曲线汇合得到的。
在这里插入图片描述

2.4 LIME:

Local Interpretable Model-Agnostic Explanation(LIME) ,通过名字便可以看出,该模型是一个局部可解释模型,并且是一个与模型自身的无关的可解释方法。通过扰动输入样本(perturb the input),来对模型的预测结果进行解释。该算法不止适用于表格型(tabular)数据,而且适用于文本和图片任务。

论文作者提出了解释器需要满足的四个条件:

  • 可解释性: 对模型和特征两个方面都有要求。决策树、线性回归和朴素贝叶斯都是具有可解释的模型,前提是特征也要容易解释才行。否则像是词嵌入(Word Embedding)的方式,即使是简单的线性回归也无法做到可解释性。而且解释性还要取决于目标群体,比如向不了解模型的业务人员去解释这些模型。相比之下,线性模型也要比简单的贝叶斯更容易理解。

  • 局部忠诚( local fidelity):既然我们已经使用了可解释的模型与特征,就不可能期望简单的可解释模型在效果上等同于复杂模型(比如原始CNN分类器)。所以解释器不需要在全局上达到复杂模型的效果,但至少在局部上效果要很接近,而此处的局部代表我们想观察的那个样本的周围。

  • 与模型无关: 任何其他模型,像是SVM或神经网络,该解释器都可以工作。

  • 全局视角: 准确度,AUC等有时并不是一个很好的指标,我们需要去解释模型。解释器的工作在于提供对样本的解释,来帮助人们对模型产生信任。

2.4.1 可解释性和性能的平衡:

ξ ( x ) = argmin ⁡ g ∈ G L ( f , g , π x ) + Ω ( g ) \xi(x)=\underset{g \in G}{\operatorname{argmin}} \mathcal{L}\left(f, g, \pi_{x}\right)+\Omega(g) ξ(x)=gGargminL(f,g,πx)+Ω(g)

  • f f f:分类器(复杂模型);
  • g g g:可解释模型(简单模型,eg.LR);
  • G G G:可解释模型集合;
  • Ω ( g ) \Omega(g) Ω(g):可解释模型的复杂度度量;
  • x x x:特征;
  • ξ ( x ) \xi(x) ξ(x):目标函数;
  • π x \pi_x πx:相似度度量函数;
  • L L L:损失函数;

2.4.2 LIME分析步骤:

  1. 对整个数据进行训练,模型 f f f可以是Lightgbm,XGBoost等;
  2. 选择一个样例 x x x,进行可解释的N次扰动,生成局部样本 x ‘ x^` x
  3. 定义一个相似度度量的函数 π x \pi_x πx,选取最能描述复杂模型输出结果的K个特征,
  4. 使用复杂模型对 x x x x ‘ x^` x进行预测;
  5. 对采样后的样本,拟合一个简单的模型,比如Lasso Regression得到模型的权重;

我们人为的选择K个特征,特征越少,可解释性越好,特征越多简单模型也将具有更好的忠诚度。对数据进行扰动的时候,不可以进行随机、完全无意义的扰动。对于图像,按照超像素(可理解的图像块);文本,随机的对单个词进行筛选;表格型数据,每次单独改变一个特征。

2.4.3 优缺点:

优点:

  1. 表格型数据、文本和图片均适用;
  2. 解释对人友好,容易明白;
  3. 给出一个忠诚性度量,判断可解释模型是否可靠;
  4. LIME可以使用原模型所用不到的一些特征数据,比如文本中一个词是否出现;

缺点:

  1. 表格型数据中,相邻点很难定义,需要尝试不同的kernel来看LIME给出的可解释是否合理;
  2. 扰动时,样本服从高斯分布,忽视了特征之间的相关性;
  3. 稳定性不够好,重复同样的操作,扰动生成的样本不同,给出的解释可能会差别很大;

2.4.4 实例:

和上述一样,仍然选择预测每个人的年收入是否会超过50k这个数据集,使用XGBoost模型

  • 选择一个样本,重要性最高的5个特征,进行可解释分析:
np.random.seed(1)
i = 16

explainer = lime.lime_tabular.LimeTabularExplainer(train,feature_names = feature_names,class_names=class_names,
                                                   categorical_features=categorical_features, 
                                                   categorical_names=categorical_names, kernel_width=3)

exp = explainer.explain_instance(test[i], predict_fn, num_features=5)
exp.show_in_notebook(show_all=False)

在这里插入图片描述
我们发现预测收入大于50k的概率是0.9。LIME给出解释,做出这样的预测是考虑到,婚姻状态,教育,每小时工作时间和年龄,而资本收益带来的是负的影响。

另一个例子:

i = 10
exp = explainer.explain_instance(test[i], predict_fn, num_features=5)
exp.show_in_notebook(show_all=True)

在这里插入图片描述

2.5 SHAP(SHapley Additive exPlanation):

2.5.1 shapley值:

shapley由伊德·夏普利(Lloyd Shapley)教授提出,用于解决合作博弈的贡献和收益分配问题。N人合作中,单个成员的贡献不一样,收益分配也应该不一样。理想的分配方式是:收益=贡献;
目标问题: N N N个人合作,创造了 v ( N ) v(N) v(N)的价值,如何对所创造的价值进行分配。

基本条件: 全集 N = { x 1 , x 2 , ⋯ , x n } N=\{x_1,x_2,⋯,x_n\} N={x1,x2,,xn}有N个元素 x i x_i xi,任意多个人形成的子集 S ⊆ N S⊆N SN,有 v ( S ) v(S) v(S)表示S子集中所包括的元素共同合作所产生的价值。最终分配的价值(Shapley Value) ϕ i ( N , v ) \phi_i(N,v) ϕi(N,v)

需满足分配四原则:

  1. 有效性(Efficiency):所有价值均被分配
  2. 对称性(Symmetry):假设x_i和x_j可以互相替代,那他们收益应该一样;
  3. Dummy: 未做贡献的话收益为0;
  4. 可加性(Additivity):如果同一批人完成两项任务,那么两项任务的收益一起分配应该和分开分配的结果一致:

假设有500个题目,三个人去做,一天内完成。一天,A单独能完成100道,B完成125道,C完成50道。 v ( A ) = 100 , v ( B ) = 125 , v ( C ) = 50 v({A})=100, v({B})=125, v({C})=50 v(A)=100,v(B)=125,v(C)=50

两个人合作的话,会快一些, v ( A , B ) = 270 , v ( B , C ) = 350 , v ( A , C ) = 375 v({A, B})=270, v({B, C})=350, v({A, C})=375 v(A,B)=270,v(B,C)=350,v(A,C)=375。三个人合作,一天可以完成 v ( A , B , C ) = 500 v({A, B, C}) = 500 v(A,B,C)=500。分别考虑6种不同的分组情况,然后计算三个人分别对应的边际收益。

第i个人加入到组织S的边际收益是: ϕ i ( S ) = v ( S ∪ { i } ) − v ( S ) \phi_i(S) = v(S \cup \{i\}) - v(S) ϕi(S)=v(S{i})v(S)
在这里插入图片描述
借鉴上述博弈论中Shapley值的计算方法,在机器学习训练任务中,一个特征的贡献值可由下面的公式计算:

ϕ j ( v a l ) = ∑ S ⊆ { x 1 , … , x p } \ { x j } ∣ S ∣ ! ( p − ∣ S ∣ − 1 ) ! p ! ( v a l ( S ∪ { x j } ) − v a l ( S ) ) \phi_{j}(v a l)=\sum_{S \subseteq\left\{x_{1}, \ldots, x_{p}\right\} \backslash\left\{x_{j}\right\}} \frac{|S| !(p-|S|-1) !}{p !}\left(v a l\left(S \cup\left\{x_{j}\right\}\right)-v a l(S)\right) ϕj(val)=S{x1,,xp}\{xj}p!S!(pS1)!(val(S{xj})val(S))

  • S S S:特征的子集;
  • x x x:样本特征值;
  • v a l x ( S ) val_x(S) valx(S):针对集合S特征值的预测;
  • p p p:总的特征数;

和上述例子是类似的,但是增加了一个权重。

计算Shapley值,要考虑每个特征是否在集合S中,随着特征数的增加,计算复杂度会呈指数上升,所以Strumbelj等人提出了一种通过Monte-Carlo采样实现的近似算法:
ϕ ^ j = 1 M ∑ m = 1 M ( f ^ ( x + j m ) − f ^ ( x − j m ) ) \hat{\phi}_{j}=\frac{1}{M} \sum_{m=1}^{M}\left(\hat{f}\left(x_{+j}^{m}\right)-\hat{f}\left(x_{-j}^{m}\right)\right) ϕ^j=M1m=1M(f^(x+jm)f^(xjm))

  • f ^ ( x + j m ) \hat{f}(x_{+j}^{m}) f^(x+jm):特征 j j j不变,其他特征被随机数据点替换,得到的预测结果;
  • f ^ ( x − j m ) \hat{f}(x_{-j}^{m}) f^(xjm):和上述类似,特征 j j j同样被替换;
  • M:迭代M次;

特征的近似Shapley值求解步骤:

输出: j j j个特征的Shapley值
输入: 迭代次数 M,样本点 x, 特征索引 j j j,训练数据 X X X, 训练模型 f f f

for m = 1,…M:

  1. 从训练数据中随机采样,样本 z 0 = ( z ( 1 ) , z ( 2 ) , . . . z ( j ) , . . . , z ( p ) ) z_0 = (z_{(1)}, z_{(2)}, ...z_{(j)}, ...,z_{(p)}) z0=(z(1),z(2),...z(j),...,z(p))
  2. 假设样本待预测样本为 x 0 = ( x ( 1 ) , x ( 2 ) , . . . x ( j ) , . . . , x ( p ) ) x_0 = (x_{(1)}, x_{(2)}, ...x_{(j)}, ...,x_{(p)}) x0=(x(1),x(2),...x(j),...,x(p))
  3. 将样本x中的特征随机替换为z中的特征,得到两个新的向量:

x + j = ( x ( 1 ) , … , x ( j − 1 ) , x ( j ) , z ( j + 1 ) , … , z ( p ) ) x_{+j}=\left(x_{(1)}, \ldots, x_{(j-1)}, x_{(j)}, z_{(j+1)}, \ldots, z_{(p)}\right) x+j=(x(1),,x(j1),x(j),z(j+1),,z(p))

x − j = ( x ( 1 ) , … , x ( j − 1 ) , z ( j ) , z ( j + 1 ) , … , z ( p ) ) x_{-j}=\left(x_{(1)}, \ldots, x_{(j-1)}, z_{(j)}, z_{(j+1)}, \ldots, z_{(p)}\right) xj=(x(1),,x(j1),z(j),z(j+1),,z(p))

  1. 计算每次的边际收益
    ϕ j m = f ^ ( x + j ) − f ^ ( x − j ) \phi_j^m = \hat{f}\left(x_{+j}\right)-\hat{f}\left(x_{-j}\right) ϕjm=f^(x+j)f^(xj)

取平均,计算特征 j j j的Shape值: ϕ ^ j = 1 M ∑ m = 1 M ( f ^ ( x + j m ) − f ^ ( x − j m ) ) \hat{\phi}_{j}=\frac{1}{M} \sum_{m=1}^{M}\left(\hat{f}\left(x_{+j}^{m}\right)-\hat{f}\left(x_{-j}^{m}\right)\right) ϕ^j=M1m=1M(f^(x+jm)f^(xjm))

2.5.2 优缺点:

优点:

  • SHAP值的计算是公平分配到不同的特征的,而LIME是选择一部分特征进行解释;
  • 可以进行对比分析,同一个特征在不同样本之间的SHAP值进行比较,但是LIME不能;
  • 具有坚实的理论基础,LIME使用LR等简单模型进行拟合,但是并不清楚为什么这样是work的;

缺点:

  • 计算非常耗时,指数级别的复杂度;
  • SHAP可能存在误导,他计算的并不是将这个特征去掉以后训练模型得到的结果
  • 计算某个样本的SHAP值时,需要获取整个训练数据集;
  • 如果特征之间存在相关性,这种基于扰动的方法,可能会出现不切实际的数据;

2.5.3 实例:

为了方便对比,选择和LIME同样的数据集,预测用户的收入。读取数据,数据预处理,和模型训练部分和前面相同,不再赘述。

1. 选择和LIME同样的一条样本进行可解释分析:

# explain the model's predictions using SHAP values
explainer = shap.TreeExplainer(gbtree)
shap_values = explainer.shap_values(test)

# 对一个样本求shap值,各个特征对output所带来的变化
shap.force_plot(explainer.expected_value, shap_values[16,:], test.iloc[16,:])

在这里插入图片描述
图解:

  • base value:全体样本Shap平均值;
  • output value:当前样本的Shap输出值;
  • 正向作用特征:Education-num, Relationship, Age;
  • 反向作用的特征:Country, Capital Gain

这个图说明了,对于单个样本,预测值的高低是如何造成的,由哪些特征造成的。和LIME的解释对比可以发现,基本是一致的,均是因为Age,Education,Capital Gain等做出的决策。

2. 另一个样例:

shap.force_plot(explainer.expected_value, shap_values[10,:], test.iloc[10,:])

在这里插入图片描述
从图中发现,大部分特征都是呈现反向作用,所以预测的值较低。

3. 将上图旋转90°,然后将所有的test拼接在一起,可以看到在整个数据集上Shap分布:

shap.force_plot(explainer.expected_value, shap_values, test)

在这里插入图片描述
4. 从特征维度,观察特征对Shap的影响:

shap.summary_plot(shap_values, test)

在这里插入图片描述
图解:

  • 横坐标是SHAP值(对模型输出的影响)
  • 纵坐标是不同的特征
  • 颜色越红,特征值越大,越蓝特征值越小;

从图中可以看出,年龄(Age)越大,对收入的正向作用越大,但是到达一定年龄,对收入的贡献将不变,同时发现,存在年龄小但收入高的群体。同样,随着接受教育时间(Education-Num)变大,收入随之提高。同时,资本收益(Capital Gain)对收入的影响最大。

5. 特征重要性:
在这里插入图片描述
对所有样本的SHAP绝对值取平均,得到类似lgb、xgb特征重要性的数据。

6. 观察某个特征的SHAP分布:

数值型特征:Age
在这里插入图片描述
从图中,我们可以发现,随着年龄的增加SHAP值不断增加,但是超过一定年龄后,SHAP值反而会下降。同时,高资本收益的人群分布在30岁往后,同样年龄,高资本收益的人群,收入更高,十分合理(hhhh)。

类别型特征:Relationship
在这里插入图片描述
每一个用户在家庭中所处的关系,从左到右分别是【‘Husband’, ‘Not-in-family’, ‘Other-relative’, ‘Own-child’, ‘Unmarried’, ‘Wife’】,已婚的SHAP值更高,小孩和未婚的更低,符合常识。

三、其他方法:

3.1 Interpret:

微软新提出了,一个可以训练可解释机器学习模型和解释模型的,开源框架。一方面这个框架,实现了可解释提升模型(Explainable Boosting Machine-EBM)。EBM是 G A 2 M GA^2M GA2M的一种实现,在基础上添加了一些诸如bagging和boosting等模型融合的方法。微软表示,EMB的性能媲美XGBoost和Lightgbm等集成树模型,同时保持模型的可解释性。

接下来看GAMs。

3.1.1 GAMS:

线性模型具有非常好的可解释性,通过权重可以分析每个特征是如何影响预测结果的。但是线性模型过于简单。线性模型非常严重的缺陷是无法拟合交叉特征和非线性关系。非线性关系可以通过以下几种方式解决,对特征进行转换(log,exp等),将特征分箱然后onehot,另一种便是GAMs

标准线性模型: y = β 0 + β 1 x 1 + . . . + β n x n + ϵ y = \beta_0 + \beta_1x_1 + ... + \beta_nx_n + \epsilon y=β0+β1x1+...+βnxn+ϵ
GAM: g ( E Y ( y ∣ x ) ) = β 0 + f 1 ( x 1 ) + f 2 ( x 2 ) + … + f p ( x p ) = β 0 + ∑ f j ( x j ) g\left(E_{Y}(y | x)\right)=\beta_{0}+f_{1}\left(x_{1}\right)+f_{2}\left(x_{2}\right)+\ldots+f_{p}\left(x_{p}\right)= \beta_0 + \sum{f_j(x_j)} g(EY(yx))=β0+f1(x1)+f2(x2)++fp(xp)=β0+fj(xj)

GAMs和标准线性模型非常相似,只不过是将 β j x j \beta_jx_j βjxj用一个灵活的函数表示 f j ( x j ) f_j(x_j) fj(xj)。本质上依然是对特征的影响进行求和。

同时线性模型无法学习到交叉特征, G A 2 M GA^2M GA2M在GAM的基础上添加了交叉项:
g ( E [ y ] ) = β 0 + ∑ f j ( x j ) + ∑ f i j ( x i , x j ) g(E[y])=\beta_{0}+\sum f_{j}\left(x_{j}\right)+\sum f_{ij}\left(x_{i}, x_{j}\right) g(E[y])=β0+fj(xj)+fij(xi,xj)

实际使用了下,微软把没弄好的东西丢了出来,训练时间非常长,在小数据集上效果尚可,不排除是随机数的影响,而且XGBoost是默认参数。在大数据集上,训练时间相当长,指标(AUC)和lgb有差距。还是有待改善吧,还需要在更多的数据集上进行尝试。

实验结果:

Modelheart-disease(303,13)breast-cancer(569,30)adult-data(32561,19)credit-fraud(284807,30)
SGD0.8850.9930.8910.980
LR0.9150.9960.9070.974
RandomForest0.9080.9910.9030.942
XGBoost0.8790.9950.9220.979
Lightgbm0.8690.9940.9290.984
EBM0.9250.9950.9290.969

3.2 非事实解释(Counterfactual Explanations):

讲一个有意思的场景。假设我想去贷款,然后被银行的机器学习模型拒绝了。我会想,为什么我会被拒绝,以及如何能提高我被接受的概率。机器学习模型用到的特征包括,我自身的属性,包括收入,银行卡数量,年龄等。如何对这些特征做出最小的改变,使得模型的预测从拒绝变成接受呢。通过构建违反常规的样本,来改变模型的预测,从而达到对模型进行可解释的目的。

类似在风控任务中,为什么这个人违约率高。如果,对其修改某个特征后,概率会降低。这样可以解释,是因为某个特征值,模型预测的概率比较高。

如何定义一个好的非事实解释:

  1. 尽可能和想要的预测更接近;
  2. 对于特征值进行尽可能少的改变;
  3. 修改后的特征值尽可能符合实际情况;

参考资料

文章:
Interpretable Machine Learning A Guide for Making Black Box Models Explainable.
可解释的机器学习
Kaggle课程-Machine Learning Explainability
机器学习模型可解释性的详尽介绍
A Brief History of Machine Learning Models Explainability
Shapley, LIME and SHAP
Interpreting machine learning models
What If… you could inspect a machine learning model, with minimal coding required?
Papers on Explainable Artificial Intelligence
Limitations of Interpretable Machine Learning Methods
Comparison between SHAP (Shapley Additive Explanation) and LIME (Local Interpretable Model-Agnostic Explanations)
One Feature Attribution Method to (Supposedly) Rule Them All: Shapley Values
Introduction to AI Explanations for AI Platform
Hands-on Machine Learning Model Interpretation

Papers:
[1] Friedman, J. (2001). Greedy Function Approximation: A Gradient Boosting Machine. The Annals of Statistics, 29(5):1189–1232.
[2] Goldstein, A., Kapelner, A., Bleich, J., and Pitkin, E., Peeking Inside the Black Box: Visualizing Statistical Learning With Plots of Individual Conditional Expectation. (2015) Journal of Computational and Graphical Statistics, 24(1): 44-65
[3] Lundberg S M, Erion G G, Lee S I. Consistent individualized feature attribution for tree ensembles[J]. arXiv preprint arXiv:1802.03888, 2018.
[4] Ribeiro M T, Singh S, Guestrin C. Why should i trust you?: Explaining the predictions of any classifier[C]//Proceedings of the 22nd ACM SIGKDD international conference on knowledge discovery and data mining. ACM, 2016: 1135-1144.
[5] Lundberg S M, Lee S I. A unified approach to interpreting model predictions[C]//Advances in Neural Information Processing Systems. 2017: 4765-4774.
[6] Nori H, Jenkins S, Koch P, et al. InterpretML: A Unified Framework for Machine Learning Interpretability[J]. arXiv preprint arXiv:1909.09223, 2019.
[7] AI Explainability Whitepaper-Google

开源库:

  • 25
    点赞
  • 132
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

linxid

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值