二元分类中的特征重要性和仅提取一个类别的SHAP值

假设我们有一个二元分类问题,我们的目标是分为1和0两个类别。我打算使用树分类器根据特征来预测1和0。此外,我可以使用SHAP值来对预测1和0的特征重要性进行排序。到目前为止,一切顺利!

现在假设我想知道仅预测1的特征的重要性,有什么推荐的方法吗?我可以将数据分成两部分(名义上:df_tot = df_zeros + df_ones),然后在分类器中使用df_ones,并提取其SHAP值,但这样做的话,目标只会包含1,因此模型实际上并不会学习如何分类。所以我想知道如何处理这样的问题?


回答:

让我们准备一些二元分类数据:

from seaborn import load_datasetfrom sklearn.model_selection import train_test_splitfrom lightgbm import LGBMClassifierimport shaptitanic = load_dataset("titanic")X = titanic.drop(["survived","alive","adult_male","who",'deck'],1)y = titanic["survived"]features = X.columnscat_features = []for cat in X.select_dtypes(exclude="number"):    cat_features.append(cat)#   think about meaningful ordering instead    X[cat] = X[cat].astype("category").cat.codes.astype("category")X_train, X_val, y_train, y_val = train_test_split(X,y,train_size=.8, random_state=42)clf = LGBMClassifier(max_depth=3, n_estimators=1000, objective="binary")clf.fit(X_train,y_train, eval_set=(X_val,y_val), early_stopping_rounds=100, verbose=100) 

为了回答你的问题,要按类别提取SHAP值,可以按类别标签进行子集划分:

explainer = shap.TreeExplainer(clf)shap_values = explainer.shap_values(X_train)sv = np.array(shap_values)y = clf.predict(X_train).astype("bool")# shap values for survivalsv_survive = sv[:,y,:]# shap values for dyingsv_die = sv[:,~y,:]

然而,一个更有趣的问题是你可以用这些值做什么。

一般来说,通过查看summary_plot(针对整个数据集)可以获得有价值的见解:

shap.summary_plot(shap_values[1], X_train.astype("float"))

enter image description here

解释(全局):

  • 性别、舱位等级和年龄是决定结果的最具影响力的特征
  • 男性、较不富裕、年龄较大的人生存机会减少

可以按以下方式提取前三个全局最具影响力的特征:

idx = np.abs(sv[1,:,:]).mean(0).argsort()features[idx[:-4:-1]]# Index(['sex', 'pclass', 'age'], dtype='object')

如果你想按类别进行分析,可以单独为幸存者(sv[1,y,:])这样做:

# top3 features for probability of survivalidx = sv[1,y,:].mean(0).argsort()features[idx[:-4:-1]]# Index(['sex', 'pclass', 'age'], dtype='object')

对于未幸存者(sv[0,~y,:])也是如此:

# top3 features for probability of dieingidx = sv[0,~y,:].mean(0).argsort()features[idx[:3]]# Index(['alone', 'embark_town', 'parch'], dtype='object')

注意,这里我们使用了平均SHAP值,并且表示我们对幸存者的最大值和未幸存者的最小值感兴趣(最低值,接近0,也可能意味着没有恒定的、单向的影响)。使用绝对值的平均值也可能有意义,但解释将是最具影响力的,无论方向如何。

为了做出明智的选择,是否更喜欢平均值还是绝对值的平均值,必须了解以下事实:

  • SHAP值可以是正的也可以是负的
  • SHAP值是对称的,增加/减少一个类别的概率会以相同的量减少/增加另一个类别的概率(由于p₁ = 1 – p₀)

证明:

#shap valuessv = np.array(shap_values)#base valuesev = np.array(explainer.expected_value)sv_died, sv_survived = sv[:,0,:] # + constantprint(sv_died, sv_survived, sep="\n")# [-0.73585563  1.24520748  0.70440429 -0.15443337 -0.01855845 -0.08430467  0.02916375 -0.04846619  0.         -0.01035171]# [ 0.73585563 -1.24520748 -0.70440429  0.15443337  0.01855845  0.08430467 -0.02916375  0.04846619  0.          0.01035171]

你很可能会发现性别和年龄对幸存者和非幸存者都起到了最具影响力的作用;因此,与其分析每个类别中最具影响力的特征,不如看看是什么让两个性别和年龄相同的乘客一个幸存,另一个未幸存(提示:在数据集中找到这样的案例,将一个作为背景,并分析另一个的SHAP值,或者尝试分析一个类别与另一个类别作为背景)。

你可以使用dependence_plot进行进一步的分析(在全局或按类别基础上):

shap.dependence_plot("sex", shap_values[1], X_train)

enter image description here

解释(全局):

  • 男性生存的概率较低(较低的SHAP值)
  • 舱位等级(财富)是下一个最具影响力的因素:较高的舱位等级(较少的财富)降低了女性生存的几率,反之亦然,对男性来说

Related Posts

使用LSTM在Python中预测未来值

这段代码可以预测指定股票的当前日期之前的值,但不能预测…

如何在gensim的word2vec模型中查找双词组的相似性

我有一个word2vec模型,假设我使用的是googl…

dask_xgboost.predict 可以工作但无法显示 – 数据必须是一维的

我试图使用 XGBoost 创建模型。 看起来我成功地…

ML Tuning – Cross Validation in Spark

我在https://spark.apache.org/…

如何在React JS中使用fetch从REST API获取预测

我正在开发一个应用程序,其中Flask REST AP…

如何分析ML.NET中多类分类预测得分数组?

我在ML.NET中创建了一个多类分类项目。该项目可以对…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注