传统的统计模型虽然结构简单, 容易解释, 但是也存在一定的局限性,例如精度较低。如果我们想要训练出的预测精度较高的模型,仅仅使用传统的统计模型是远远不够的。为了解决这一问题, 同时又能保留容易解释的模型结构, Yin Lou 于2012 年提出了EBM 模型, 在广义加性模型的框架下, 用提升树模型拟合各个特征, 并创新性地设计了 FAST 算法, 用于寻找特征之间的交互项效庶, 并将排名靠前的交互特征放入模型中, 以进一步提高模型的精度。 目前, 该模型已经被嵌人到微软开发的可解释包 interpret 中, 可以从该开源库中直接调用, 其开源网址为 https://github.com/interpretml/interpret 。本节将主要介绍 EBM 的模型定义、识别二阶交互项、实现算法、 模型解秚性及模型的优少分析。
EBM 模型的全称是 Explainable Boosting Machine, 该模型是将提升树模型 (Boosting Tree) 融人到广义加性模型之中, 并经过一系列的改良操作, 达到解决回归问题和分类问题的目的,精度上也可以接近复杂模型。同时,EBM模型的内在结构清晰明了,本身具有很强的解释性,可以对模型结果进行局部解释和全局解释,帮助人们做出有效的决策,从而提升模型的可信度。前面已经提过,广义加性模型的结构是$$g(E(Y|X))=\sum_{i=1}^N f_{i}(X_i)$$其中$f(x)$称为形函数(shape function),在EBM模型中,可以用提升树模型你和其中的$f_i(X_i)$.而后在此基础上进行的改良是,找到影响力比较大的交互项,再将其加入到广义加性模型中,模型结构变为
$g(E(Y \mid X))=\sum_{i=1}^N f_i\left(X_i\right)+\sum_{i=j} f_{i j}\left(X_i, X_i\right)_i$
广义加性模型一直贯穿于整个 EBM 模型中, 选择适合的拟合方法也是非常值得考量的。当下比较流行的方法包括最小平方法、梯度提升发和后向拟合法,其中后两种是EBM所使用的拟合广义加性模型的方法。
关于寻找二阶交互顶, 如果按照传统方法, 即每力一个交互特征都要重新训练模型, 那么计算就会特别耗时。因此, EBM 模型使用 FAST 算法, 为所有的成对特征的影晌快速排序, 再选择排名靠前的交互洔佂, 一起加入到广义加性模型中进行拟合。
学术界发展了很多方法用于识别交互作用, 常见的有方差分折法 (ANOVA)、部分以来函数 (Partial Dependence Function)、基于卡方检验的方法(GUIDE) 等。EBM 模型提出了新的寻蛲交互特佂的方法 FAST, 用于识别交互特征, 并且根据影响力为交互特征排序。FAST 算法的思想是对所有的二阶交互变量,逐个计算关于模型的剩余平方损失(RSS),
下面就来看一下具体的实现过程。 得到的形函数 $f_{i j}\left(X_i, X_i\right)$ 对模型产生较大的影响。对应的单个特征形函数 $f_i\left(X_i\right), f_j\left(X_j\right)$ 是在一开始就训练好的, 是 主效应。所以交互作用 $f_{i j}\left(X_i, X_j\right)$ 是在主效应训练完之后, 对残差 $Y_{\text {残差 }}进行训练。直观来看, 如果\left(X_i, X_j\right) $之间有较强的相关性,则其 $f_{i j}\left(X_i, X_j\right)$ 会极大地降低残差。以回归问题为例, 假设数据集中有 $N$ 个特征,那么成对的特征共有 $C_{N=}^2=$ $\frac{N(N-1)}{2}$ 种可能。如果要遍历所有的成对特征, 那么整个过程将会非常耗时耗力, 而 FAST 算法可以使计算变得高效。
训练好主效应 $f_i\left(X_i\right), i=1,2, \cdots, N$ 之后, 即可对残差数据集进行拟合。以某一成对特征 $\left(X_i, X_j\right)$ 为例, 对类似于深度为 2 的树, 因为深度为 2 代表的是可以抓取二阶交互特征。分别对 $X_i$ 和 $X_j$ 做切分, 分割点是 $c_i$ 和 $c_j$ 。有了两个分割点之后, 相当于是将两个变量构成的平面切分为了 4 部分, 即 $\left(X_i \geqslant c_i, X_j \geqslant c_j\right),\left(X_i \geqslant c_i, X_j<c_j\right)$, $\left(X_i<c_i, X_j \geqslant c_j\right),\left(X_i<c_i, X_j<c_j\right)$,它并不是使用传统的决策树模型来寻找分裂点。
那么, 怎样才能找到最好的分刲点呢? 上文只介绍了将一维平面划分为 4 个部分的一种选择, 即非常简单粗暴的方法。
为了找到最好的分割点, 我们可以使用贪心搜索算法。我们的目的是要搜寻在所有可能的切割 $\left(c_i, c_j^1, c_j^2\right)$ 中, 使得平方损失 (RSS) 最小的那一对。为了降低复杂度, 算法会提前把所有可能的由两个分割点得到的损失储存起来, 然后在搜索的时候直接查找即可。
关于成对特征的搜索表制作, 则是通过遍历两个变量的取值得到的。如果是离散变量, 就直接遍历所有可能的取值; 如果是连续变量, 则可以通过分箱的方法, 将取值固定在某个区间内即可, FAST 算法中设置的箱数是最多不超过 256 个。以下假设 $X_i$ 的取值空间为 $\left(v_i^1, v_i^2, \cdots, v_i^{d_i}\right)$ ,其中, $d_i$ 代表的是变量 $x_i$ 的所有取值个数。例如, 当 $X_i$ 代表性别时, 它的取值空间为(男,女,对应起来就是 $v_i^1=$ 男, $v_i^2=$ 女, $d_i=2$ 。 那么当有两个变是时, 其取值空间就相当于是一个二维平面。
EBM 模型的解释性可分为全局解释和局部解释两大类。
全局解释是基于数据集中的特征变量对模型结果进行解释, 从中我们不仅可以看到每个特征的形函数 $f_u$, 以图的方式来展示 $f$ 的内部结构, 还可以看到每个特征的全局重要性。 在 EBM 模型中, 每一项 $f_u$ 都有相应的权重。不管是单个特征还是二阶交互特征, 我们都会对其计算相应的权重, 然后排序, 找到重要性靠前的单个特征或交互特征, 提供给模型使用者以进行后续模型分析。
至于模型权重的计算, EBM 模型使用 $\sqrt{E\left(f_u^2\right)}$ 来度量 $f_u$ 的 重要性。 $\sqrt{E\left(f_u^2\right)}$ 就相当于 $f_u$ 的标准差。由于在EBM 中, 不必考虑模型截距项的重要性, 因此令 $E\left(f_u\right)=0$, 那么 $\operatorname{std}\left(f_u\right)=$ $\sqrt{E\left(f_u^2\right)-E^2\left(f_u\right)}=\sqrt{E\left(f_u^2\right)}$ 。举个简单例子, 当 $f_i\left(X_i\right)=w_i X_i$ 时, 且对 $X_i$ 做正则化, 使得 $\sqrt{E\left(x_i\right)^2}=1$, 那么 $\sqrt{E\left(\left(f_i\right)^2\right)}=$ $\sqrt{E\left(\left(w_i X_i\right)^2\right)}=\left|w_i\right|$ 。所以对数据进行正则化之后, 可以将标准差当成权重, 来度量每一项的重要性。 下面以乳腺癌数据为例进行说明, 数据集中包含 30 个特征变量, 目标是预测是否为乳腺癌。训练完 EBM 模型, 可以得到特征变量的全局解释。这里的全局解释包括两个层次, 一是特征重要性排序, 二是每个特征与目标变量之间的函数关系, 即形函数。所示的是特征重要性的排序图。 每个特征的重要性分数就是上述提到的标准差。 第二个层次是指刻画每个特征与目标变量之间的形函数, 以及特征自身取值的分布情况。如图所示, 上方显示的是特征与目标变量之间的关系, 下方显示的是该特征在数据集中的概率分布直方图。
使用训练好的 EBM 模型来预测某人是否有乳腺癌时, 其可以提供局部解释。局部解释主要体现在其能够对每个样本的得分进行解释说明, 包括该样本中每个特征的得分情况, 以及哪些特征对该样本模型预测结果的影响最大。
从上图中可我们看出, 预测该个体发生的概率为 $1$, 显著高于 $0.5$ 的阈值。而实际结果显示该个体确实为1, 所以预测与实际相符。对于模型为何会给出这么高的预测概率, 条形图给出了具体的得分情况, 并按从大到小的顺序进行了排列, 只需要将所有得分加总并进行函数变化, 便可算出相应的概率。局部解释性可以帮助研究者找到影响单一个体的具体原因, 然后结合业务对存在 的问题进行深人研究。
from sklearn.datasets import load_iris,load_breast_cancer
import pandas as pd
from sklearn.model_selection import train_test_split
from interpret import show
from interpret.glassbox import ExplainableBoostingClassifier
data = load_breast_cancer()
df = pd.DataFrame(data['data'],columns=data['feature_names'])
df['target'] = data['target']
X,y = df.iloc[:,:-1],df['target']
X_train,X_test,y_train,y_test = train_test_split(X,y,train_size=0.7)
ebm = ExplainableBoostingClassifier()
ebm.fit(X_train,y_train)
ebm_global = ebm.explain_global()
show(ebm_global)
EBM 模型加入二阶交互项之后,其精度提升了很多,同时可解释性也很强, 我们可以清楚地看到每一项的权重, 可以根据权重来看待每一项特征的重要性。除此之外, EBM模型 还包括以下4个特点。
1) EBM 模型能够自动检测出成对交互作用, 按交互作用的强弱从大到小显示交互特征, 保留前 $k$ 个成对交互特征。同时, 热力图可用于显示成对交互项对响应变量的影响。由于捕捉了交互作用, 因此模型的精度和解释性都得到了增强。
2) EBM 中检测到的交互项效应比用 RuleFit 抓取到的交互项效应会更准确一点。很多模型抓取到的交互都会存在虚假交互的问题, 即 spurious interaction。但是 FAST 算法可以很好地解决这个问题, 并且经过了实验的验证。
3) FAST 算法由于提前计算出了成对特征的搜索表, 所以降低了运行的时间复杂度, 速度快、效率高。
4) EBM模型数据预处理和特征工程都很简单, 能够节省 大量的资源。只需要对缺失值、异常值进行简单的精度处理就能达到较高的精度。而逻辑回归要想达到较高的精度, 需要进行精细的数据处理,这些都要花费较多的人力和物力。
from sklearn.datasets import load_iris,load_breast_cancer
import pandas as pd
from sklearn.model_selection import train_test_split
from interpret import show
from interpret.glassbox import ExplainableBoostingClassifier
data = load_breast_cancer()
df = pd.DataFrame(data['data'],columns=data['feature_names'])
df['target'] = data['target']
X,y = df.iloc[:,:-1],df['target']
X_train,X_test,y_train,y_test = train_test_split(X,y,train_size=0.7)
ebm = ExplainableBoostingClassifier()
ebm.fit(X_train,y_train)
ebm_global = ebm.explain_global()
show(ebm_global)
ebm_local = ebm.explain_local(X_test,y_test)
show(ebm_local)
df.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 569 entries, 0 to 568 Data columns (total 31 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 mean radius 569 non-null float64 1 mean texture 569 non-null float64 2 mean perimeter 569 non-null float64 3 mean area 569 non-null float64 4 mean smoothness 569 non-null float64 5 mean compactness 569 non-null float64 6 mean concavity 569 non-null float64 7 mean concave points 569 non-null float64 8 mean symmetry 569 non-null float64 9 mean fractal dimension 569 non-null float64 10 radius error 569 non-null float64 11 texture error 569 non-null float64 12 perimeter error 569 non-null float64 13 area error 569 non-null float64 14 smoothness error 569 non-null float64 15 compactness error 569 non-null float64 16 concavity error 569 non-null float64 17 concave points error 569 non-null float64 18 symmetry error 569 non-null float64 19 fractal dimension error 569 non-null float64 20 worst radius 569 non-null float64 21 worst texture 569 non-null float64 22 worst perimeter 569 non-null float64 23 worst area 569 non-null float64 24 worst smoothness 569 non-null float64 25 worst compactness 569 non-null float64 26 worst concavity 569 non-null float64 27 worst concave points 569 non-null float64 28 worst symmetry 569 non-null float64 29 worst fractal dimension 569 non-null float64 30 target 569 non-null int32 dtypes: float64(30), int32(1) memory usage: 135.7 KB