可解释的提升机#

API参考链接: ExplainableBoostingClassifier, ExplainableBoostingRegressor

详情请参阅参考论文 [1]。 Link

摘要

可解释增强机(EBM)是一种基于树的循环梯度增强广义加性模型,具有自动交互检测功能。EBM通常与最先进的黑盒模型一样准确,同时保持完全可解释性。

工作原理

作为框架的一部分,InterpretML 还包括一种新的可解释性算法——可解释增强机(EBM)。EBM 是一种玻璃盒模型,旨在具有与随机森林和增强树等最先进的机器学习方法相当的准确性,同时具有高度的可理解性和可解释性。EBM 是一种广义加性模型(GAM),其形式为:

\[ g(E[y]) = \beta_0 + \sum f_j(x_j) \]

其中 \(g\) 是链接函数,用于将 GAM 适应不同的设置,如回归或分类。

EBM 相较于传统的 GAMs 有几个主要的改进 [2]。首先,EBM 使用现代机器学习技术(如装袋和梯度提升)来学习每个特征函数 \(f_j\)。提升过程被精心限制为以轮询方式一次训练一个特征,并使用非常低的学习率,以确保特征顺序无关紧要。它通过轮询循环特征来减轻共线性的影响,并为每个特征学习最佳的特征函数 \(f_j\),以展示每个特征如何对模型的问题预测做出贡献。其次,EBM 可以自动检测并包含以下形式的成对交互项:

\[ g(E[y]) = \beta_0 + \sum f_i(x_i) + \sum f_{i,j}(x_i,x_j) \]

这进一步提高了准确性,同时保持了可理解性。EBM 是 GA2M 算法 [1] 的快速实现,使用 C++ 和 Python 编写。该实现是可并行的,并利用 joblib 提供多核和多机并行化。训练过程的算法细节、成对交互项的选择以及案例研究可以在 [1, 3, 4] 中找到。

EBMs 具有高度的可解释性,因为通过绘制 \(f_j\) 可以可视化和理解每个特征对最终预测的贡献。由于 EBM 是一个加法模型,每个特征以模块化的方式对预测做出贡献,这使得理解每个特征对预测的贡献变得容易。

为了进行个体预测,每个函数\(f_j\)作为每个特征的查找表,并返回一个项贡献。这些项贡献简单地相加,并通过链接函数\(g\)传递以计算最终预测。由于模块化(可加性),项贡献可以被排序和可视化,以显示哪些特征对任何个体预测的影响最大。

为了保持各个项的可加性,EBM 需要支付额外的训练成本,这使得它比类似的方法稍慢一些。然而,由于在特征函数 \(f_j\) 内部进行预测时只需要简单的加法和查找操作,EBM 是预测时执行速度最快的模型之一。EBM 的内存使用量轻且预测速度快,这使得它在生产环境中的模型部署特别具有吸引力。

如果您发现视频是学习算法的更好媒介,您可以在下面找到算法的概念概述: Video for explaining how EBM works.

代码示例

以下代码将为成人收入数据集训练一个EBM分类器。提供的可视化将包括全局和局部解释。

from interpret import set_visualize_provider
from interpret.provider import InlineProvider
set_visualize_provider(InlineProvider())
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.metrics import roc_auc_score

from interpret.glassbox import ExplainableBoostingClassifier
from interpret import show

df = pd.read_csv(
    "https://archive.ics.uci.edu/ml/machine-learning-databases/adult/adult.data",
    header=None)
df.columns = [
    "Age", "WorkClass", "fnlwgt", "Education", "EducationNum",
    "MaritalStatus", "Occupation", "Relationship", "Race", "Gender",
    "CapitalGain", "CapitalLoss", "HoursPerWeek", "NativeCountry", "Income"
]
X = df.iloc[:, :-1]
y = df.iloc[:, -1]

seed = 42
np.random.seed(seed)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.20, random_state=seed)

ebm = ExplainableBoostingClassifier()
ebm.fit(X_train, y_train)

auc = roc_auc_score(y_test, ebm.predict_proba(X_test)[:, 1])
print("AUC: {:.3f}".format(auc))
AUC: 0.931
show(ebm.explain_global())