作者:林夕
本文长度为10000字,建议阅读10+分钟
对于信任和管理我们的人工智能“合作伙伴”,可解释AI则至关重要。
目录
一、可解释的特性
目前人工智能应用已经渗透到我们生活的方方面面,成为我们生活中重要的一部分。我们相信,随着机器学习技术的不断进步,未来有望产生一个能够感知、学习、做出决策和采取独立行动自主系统。但是,如果这些系统无法向人类解释为何作出这样的决策,那么它们的有效性将会受到限制。用户要理解,信任和管理这些人工智能“合作伙伴”,可解释AI则至关重要。
通过可解释分析,可以指导特征工程。一般我们会根据一些专业知识和经验来做特征,同构分析特征重要性,可以挖掘更多有用的特征,尤其是在交互特征方面。当原始特征众多时,可解释性分析将特别重要。在做机器学习任务时,我们一般会选择一个指标,比如准确率,然后尽可能优化。假设在一个文本分类任务中,判断文章是与“基督教”(Christianity)有关还是“无神论教”(Atheism)”,模型准确率,90%多,很高了。但是用LIME进行可解释分析发现,Posting(邮件标头的一部分)这个词重要性很高,但这个词汇与无神论本身并没有太多的联系,只是因为在无神论文章中出现的频次很高。这意味着尽管模型准确率很高,但所使用的原因是错误的。我们可以借此来改进模型,是否捕捉到了有意义的特征,以提高泛化性。
在我们做型的时候,需要在两个方面之间进行权衡,仅仅想要知道预测是什么,还是要知道模型为什么要给出这样的预测。在一些低风险的情况下,不一定要知道决策是如何做出的,比如推荐系统,广告、视频或者商品推荐等。但是在其他领域,比如在金融和医疗领域,模型的预测结果将会对相关的人产生巨大的影响,有时候我们依然需要专家对结果进行解释。解释为什么一个机器学习模型将某个患者的肿瘤归类为良性或恶性,解释为什么模型会拒绝一个人的贷款申请,这样,专家更有可能信任机器学习模型给出的预测结果。长久来看,更好地理解机器学习模型可以节省大量时间、防止收入损失。如果一个模型没有做出合理的决定,在应用这个模型并造成不良影响之前,我们就可以发现这一点。我们在面对客户的时候,他们会问 ”我为什么要相信你的模型“。如果客户不相信模型和预测结果,就无法使用这个模型,将其部署在产品中。
方差和偏差是机器学习中广泛讨论的话题。有偏差的模型经常由有偏见的事实导致,如果数据包含微妙的偏差,模型就会学习下来并认为拟合很好。一个有名的例子是,用机器学习模型来为囚犯建议定罪量刑,这显然反映了司法体系在种族不平等上的内在偏差。其他例子比如用于招聘的机器学习模型,揭示了在特定职位上的性别偏差,比如男性软件工程师和女性护士。机器学习模型在我们生活的各个层面上都是强有力的工具,而且它也会变得越来越流行。所以作为数据科学家和决策制定者来说,理解我们训练和发布的模型如何做出决策,让我们可以事先预防偏差的增大以及消除他们,是我们的责任。
How does the algorithm create the model?
算法透明度指的是,如何从数据中学习一个模型,更加强调模型的构建方式以及影响决策的技术细节。比如CNN来对图片进行分类时,模型做出预测,是因为算法学习到了边或者其他纹理。算法透明度需要弄懂算法知识而不是数据以及学到的模型。对于简单的算法,比如线性模型,具有非常高的算法透明度。复杂的模型如深度学习,人们对模型内部了解较少,透明度较差,这将非常重要的一个研究方向。由于业务可能不太精通这些技术细节,本文集中于模型的全局和局部可解释性,而不是算法的可解释性(透明度)。
How does the trained model make predictions?
为了解释模型的全局输出,需要训练模型了解算法和数据。这个层级的可解释性指的是,模型如何基于整个特征空间和模型结构、参数等作出决策的。什么特征是重要的,特征交互会发生什么。模型的全局可解释性可以帮助理解,针对不同特征,目标变量的分布是什么。实际在,模型具有大量参数的情况下,人们很难想象 特征之间是如何相互作用的,以得到这样的预测结果。
某些模型在这个层级是可以解释的。例如线性模型的权重是可以解释的,树模型如何划分分支和如何得到结点预测值是可以解释的。
Why did the model make a certain prediction for an/a group of instance?
局部可解释性更加关注单条样本或一组样本。这种情况下我们可以将模型看做是一个黑盒,不再考虑模型的复杂情况。单条样本来看,模型给出的预测值和某些特征可能是线性关系,甚至是单调关系。因此局部可解释性可能相比全局可解释,更加准确点。
获得可解释性的一个非常容易的方法是使用一系列可解释的模型,比如线性回归、逻辑回归、决策树等。这些模型已经有很多文章详细解释,本文不再介绍,以与模型无关的方法为主。与模型无关也就是可以适用于任何模型,和模型的内部结构无关。
Permutation Importance是一种计算模型特征重要性的算法。特征重要性是指,一个特征对预测的贡献有多大。某些模型,例如LR、决策树,lightgbm等模型可以直接计算特征重要性。
基本思想:假设要研究特征的重要性,那么将这列数据打乱,其他列的数据保持不变,然后观察预测的metric(eg.准确率)或者loss变化了多少,根据变化量来决定特征重要性。如果打乱以后对准确率没什么影响的话,可以认为这个特征没什么作用,特征重要性很低。
1. 读取数据预测每个人的年收入使用的数据集从1994年的人口普查局数据库中提取。根据人的一些基本信息来预测一个人每年的收入是否超过5万美元。
数据的下载链接:
https://www.kaggle.com/uciml/adult-census-income#adult.csv
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给出的实现基本一样,后面的几个特征的重要性稍微有些差异,说明这种方法的稳定性还是可靠的。
通过permutation importance可以得到特征的重要性,但是不知道不同的特征值如何影响预测结果的。PDP可以求得特征和预测结果的关系。
部分依赖图(Partial Dependency Plots-PDP)展示的是,对一个机器学习模型,一个或者两个特征的边际效应。由PDP我们可以得到目标值(target)和特征的关系,是线性、单调还是更复杂的关系。如果线性模型,特征和目标值之间则是线性关系。PDP的计算需要满足一个假设,所有的特征,是两两不相关的,如果相关就会出现问题,见PDP的缺点部分。
回归问题的部分依赖函数:
其实上述式子,便是一个连续分布边际概率的求解公式。我们可以通过Monte Carlo方法在训练集上得到估计值,求特征对预测的影响:
PDP分析步骤:
例如我们的数据集包含三个样本,每个样本有三个特征,A,B,C。
我们想要知道特征A是如何影响预测结果的。假设特征A一共有三种类型:。训练数据其他特征保持不变,特征A依次修改为各个特征值,然后对预测求平均值。
最后PDP需要的是我针对不同特征值的平均预测值。
优点:
缺点:
和上述一样,仍然选择预测每个人的年收入是否会超过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,相比少年和年老的 人,这和我们的常识是相统一的。
2.不同Age的收入大于50k的比率
fig, axes, summary_df = info_plots.target_plot(
df=data, feature='Age', feature_name='age', target='label', show_percentile=True
)
从图中发现,随着年龄的上升,收入大于50k的概率越来越高,超过一定年龄后会下降,这和PDP得出的结果是对应的。
3. 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的可能性仍然不高。随着接受教育时间的增加,同等年龄收入大的可能性更大一些。
4. 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值非常接近,
PDP有一个缺点,它描述的是特征变化对整个数据集的影响,ICE能深入到单个样本,分析特征变化对单个样本的影响。求解过程和上述PDP类似,但是ICE会给出每一个样本的预测值。
ICE的作者[2]认为,至少通过这种方式,任何有兴趣的点将不会因为求平均值而难以发现,论文中给出的例子如下图所示:
如上述例子,如果仅看图b的PDP,会认为特征x_2和预测值无关 ,实际上如果看图a,会发现结论是错误的。这样通过绘制individual conditional expectation(ICE)曲线,一切将会变得显而易见。在求解Fare的PDP时,我们会得到一个蓝色的置信区间,而置信区间便是由一条条的ICE曲线汇合得到的。
Local Interpretable Model-Agnostic Explanation(LIME) ,通过名字便可以看出,该模型是一个局部可解释模型,并且是一个与模型自身的无关的可解释方法。通过扰动输入样本(perturb the input),来对模型的预测结果进行解释。该算法不止适用于表格型(tabular)数据,而且适用于文本和图片任务。
论文作者提出了解释器需要满足的四个条件:
我们人为的选择K个特征,特征越少,可解释性越好,特征越多简单模型也将具有更好的忠诚度。对数据进行扰动的时候,不可以进行随机、完全无意义的扰动。对于图像,按照超像素(可理解的图像块);文本,随机的对单个词进行筛选;表格型数据,每次单独改变一个特征。
优点:
缺点:
和上述一样,仍然选择预测每个人的年收入是否会超过50k这个数据集,使用XGBoost模型。
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)
shapley由伊德·夏普利(Lloyd Shapley)教授提出,用于解决合作博弈的贡献和收益分配问题。N人合作中,单个成员的贡献不一样,收益分配也应该不一样。理想的分配方式是:收益=贡献;目标问题: 个人合作,创造了的价值,如何对所创造的价值进行分配。
基本条件: 全集有N个元素,任意多个人形成的子集,有表示S子集中所包括的元素共同合作所产生的价值。最终分配的价值(Shapley Value)。
需满足分配四原则:
假设有500个题目,三个人去做,一天内完成。一天,A单独能完成100道,B完成125道,C完成50道。
两个人合作的话,会快一些,。三个人合作,一天可以完成。分别考虑6种不同的分组情况,然后计算三个人分别对应的边际收益。
第i个人加入到组织S的边际收益是:
借鉴上述博弈论中Shapley值的计算方法,在机器学习训练任务中,一个特征的贡献值可由下面的公式计算:
和上述例子是类似的,但是增加了一个权重。
计算Shapley值,要考虑每个特征是否在集合S中,随着特征数的增加,计算复杂度会呈指数上升,所以Strumbelj等人提出了一种通过Monte-Carlo采样实现的近似算法:
特征的近似Shapley值求解步骤:
输出: 第个特征的Shapley值输入: 迭代次数 M,样本点 x, 特征索引 ,训练数据 , 训练模型
for m = 1,...M:
取平均,计算特征的Shape值:
优点:
缺点:
为了方便对比,选择和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,:])
图解:
这个图说明了,对于单个样本,预测值的高低是如何造成的,由哪些特征造成的。和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)
图解:
从图中可以看出,年龄(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值更高,小孩和未婚的更低,符合常识。
微软新提出了一个可以训练可解释机器学习模型和解释模型的开源框架。一方面这个框架,实现了可解释提升模型(Explainable Boosting Machine-EBM)。EBM是的一种实现,在基础上添加了一些诸如bagging和boosting等模型融合的方法。微软表示,EMB的性能媲美XGBoost和Lightgbm等集成树模型,同时保持模型的可解释性。
接下来看GAMs。
3.1.1 GAMS
线性模型具有非常好的可解释性,通过权重可以分析每个特征是如何影响预测结果的。但是线性模型过于简单。线性模型非常严重的缺陷是无法拟合交叉特征和非线性关系。非线性关系可以通过以下几种方式解决,对特征进行转换(log,exp等),将特征分箱然后onehot,另一种便是GAMs。
标准线性模型:
GAM:
GAMs和标准线性模型非常相似,只不过是将用一个灵活的函数表示。本质上依然是对特征的影响进行求和。
同时线性模型无法学习到交叉特征,在GAM的基础上添加了交叉项:
实际使用了下,微软把没弄好的东西丢了出来,训练时间非常长,在小数据集上效果尚可,不排除是随机数的影响,而且XGBoost是默认参数。在大数据集上,训练时间相当长,指标(AUC)和lgb有差距。还是有待改善吧,还需要在更多的数据集上进行尝试。
实验结果:
Model
heart-disease(303,13) | breast-cancer(569,30) | adult-data(32561,19) | credit-fraud(284807,30) | |
---|---|---|---|---|
SGD | 0.885 | 0.993 | 0.891 | 0.980 |
LR | 0.915 | 0.996 | 0.907 | 0.974 |
RandomForest | 0.908 | 0.991 | 0.903 | 0.942 |
XGBoost | 0.879 | 0.995 | 0.922 | 0.979 |
Lightgbm | 0.869 | 0.994 | 0.929 | 0.984 |
EBM | 0.925 | 0.995 | 0.929 | 0.969 |
3.2 非事实解释(Counterfactual Explanations)
讲一个有意思的场景。假设我想去贷款,然后被银行的机器学习模型拒绝了。我会想,为什么我会被拒绝,以及如何能提高我被接受的概率。机器学习模型用到的特征包括,我自身的属性,包括收入、银行卡数量、年龄等。如何对这些特征做出最小的改变,使得模型的预测从拒绝变成接受呢?通过构建违反常规的样本,来改变模型的预测,从而达到对模型进行可解释的目的。
类似在风控任务中,为什么这个人违约率高?如果,对其修改某个特征后,概率会降低。这样可以解释,是因为某个特征值,模型预测的概率比较高。
如何定义一个好的非事实解释:
参考资料
文章:
[1] Interpretable Machine Learning A Guide for Making Black Box Models Explainable.:
https://christophm.github.io/interpretable-ml-book/ [2] 可解释的机器学习:
https://zhuanlan.zhihu.com/p/71907204 [3] Kaggle课程-Machine Learning Explainability:
https://www.kaggle.com/learn/machine-learning-explainability [4] 机器学习模型可解释性的详尽介绍:
https://www.jiqizhixin.com/articles/2019-10-30-9 [5] A Brief History of Machine Learning Models Explainability:
https://medium.com/@Zelros/a-brief-history-of-machine-learning-models-explainability-f1c3301be9dc [6] Shapley, LIME and SHAP:
https://ypei.me/posts/2018-12-02-lime-shapley.html [7] Interpreting machine learning models:
https://towardsdatascience.com/interpretability-in-machine-learning-70c30694a05f [8] What If... you could inspect a machine learning model, with minimal coding required?:
https://pair-code.github.io/what-if-tool/ [9] Papers on Explainable Artificial Intelligence:
https://github.com/anguyen8/XAI-papers [10] Limitations of Interpretable Machine Learning Methods:
https://compstat-lmu.github.io/iml_methods_limitations/ [11] Comparison between SHAP (Shapley Additive Explanation) and LIME (Local Interpretable Model-Agnostic Explanations):
https://stats.stackexchange.com/questions/379744/comparison-between-shap-shapley-additive-explanation-and-lime-local-interpret [12] One Feature Attribution Method to (Supposedly) Rule Them All:
Shapley Values: https://towardsdatascience.com/one-feature-attribution-method-to-supposedly-rule-them-all-shapley-values-f3e04534983d [13] Introduction to AI Explanations for AI Platform:
https://cloud.google.com/ml-engine/docs/ai-explanations/overview [14] Hands-on Machine Learning Model Interpretation:
https://towardsdatascience.com/explainable-artificial-intelligence-part-3-hands-on-machine-learning-model-interpretation-e8ebe5afc608
论文:
[15] Friedman, J. (2001). Greedy Function Approximation: A Gradient Boosting Machine. The Annals of Statistics, 29(5):1189–1232. :
https://statweb.stanford.edu/~jhf/ftp/trebst.pdf [16] 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:
https://arxiv.org/abs/1309.6392 [17] Lundberg S M, Erion G G, Lee S I. Consistent individualized feature attribution for tree ensembles[J]. arXiv preprint arXiv:1802.03888, 2018.:
https://arxiv.xilesou.top/abs/1802.03888 [18] 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.:
https://dl_acm.xilesou.top/citation.cfm?Id=2939778 [19] Lundberg S M, Lee S I. A unified approach to interpreting model predictions[C]//Advances in Neural Information Processing Systems. 2017: 4765-4774.:
http://papers.nips.cc/paper/7062-a-unified-approach-to-interpreting-model-predicti [20] Nori H, Jenkins S, Koch P, et al. InterpretML: A Unified Framework for Machine Learning Interpretability[J]. arXiv preprint arXiv:1909.09223, 2019.:
https://arxiv.org/pdf/1909.09223.pdf
[21] AI Explainability Whitepaper-Google:
https://storage.googleapis.com/cloud-ai-whitepapers/AI%20Explainability%20Whitepaper.pdf
开源库:
[22] eli5:
https://github.com/TeamHG-Memex/eli5 [23] pdpbox:
https://github.com/SauceCat/PDPbox [24] shap:
https://github.com/slundberg/shap [25] lime:
https://github.com/marcotcr/lime [26] interpret:
https://github.com/interpretml/interpret [27] skater:
https://github.com/oracle/Skater