1

我有一个基因数据集,得分在 0 到 1 之间导致疾病的可能性(得分为 1 的基因已知会导致疾病,而得分为 0.74 的基因可能会导致疾病)。我正在尝试建立一个机器学习模型来预测回归分类中新基因的疾病评分。

我想查看已知疾病基因但得分较低的基因(例如得分为 1 但我的模型得分低于 0.8 的基因)的 shap 决策图。我正在努力将这些基因组合在一起进行绘图。

我的数据看起来像:

X:
Index   Feature1  Feature2   ... FeatureN
Gene1     1           0.2          10
Gene2     1           0.1          7
Gene3     0           0.3          10
#index is actually the index and not a column

Y:
Score
1
0.6
0.4

我运行一个带有嵌套交叉验证的 xgboost 回归器,查看 MSE,预测 r2,并绘制观察值与预期值。我可以在观察到的与预期的图中看到,在 Y 中得分为 1 的基因有许多由模型预测的低分,我想了解为什么模型使用 shap 来执行此操作。不幸的是,我无法提供示例数据。

我正在尝试调整为标签分类给出的示例 shap 代码:

import shap

xgbr = xgboost.XGBRegressor()
xgbr.fit(X_train, Y_train)

select = range(8) #I have 8 features after feature selection with BorutaShap
features = X.iloc[select]
features_display = X.loc[features.index]

explainer = shap.TreeExplainer(xgbr)
expected_value = explainer.expected_value

#Example code from https://slundberg.github.io/shap/notebooks/plots/decision_plot.html: 

y_pred = xgbr.predict(X) 
y_pred = (shap_values.sum(1) + expected_value) > 0
misclassified = y_pred != y_test[select]
shap.decision_plot(expected_value, shap_values, features_display, link='logit', highlight=misclassified)

我该如何选择y_pred,所以预测/基因应该是 1,但实际上低于 0.8(或任何低数字)?

编辑:针对给定的答案,我尝试过:

explainer = shap.TreeExplainer(xgbr)
shap_values = explainer.shap_values(X_test)

y_pred = xgbr.predict(X_test)
m = (y_pred <= 0.5) & (Y_test == 1)

shap.initjs()
shap.decision_plot(explainer.expected_value, shap_values,  X_test[m],  return_objects=True)

这运行但m长度为 171(我的 Y_test 数据中的全部行数),然后该图绘制了所有 171 它看起来像 - 我从查看数据知道应该只有一个基因 <= 0.5 和但实际上得分为 1。

4

2 回答 2

2

首先,您提到预测回归分类中新基因的疾病评分,您是什么意思?输出似乎是二元的,0或者1,因此这是一个二元分类问题。您应该改用xgboost's 分类器。更新:根据评论,让我们假设一个回归问题来模拟您的情况。尽管对于下面的示例,我们应该设置'objective':'multi:softmax'为输出实际标签。

根据您的问题,您似乎要做的是在那些未正确预测的样本上对测试集进行索引,并分析误导性特征,这在合理范围内是有意义的。

让我们用一些示例数据集重现您的问题:

from sklearn.datasets import load_iris

from sklearn.model_selection import train_test_split
import shap
import xgboost

X,y = shap.datasets.iris()
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3)

model = xgboost.train(params={"learning_rate": 0.01}, 
                      dtrain=xgboost.DMatrix(X_train, label=y_train), 
                      num_boost_round =100)

使用整个测试集的 SHAP 图是直截了当的。例如force_plot

explainer = shap.TreeExplainer(model)
shap_values = explainer.shap_values(X_test)

shap.initjs()
shap.force_plot(explainer.expected_value, shap_values, X_test)

在此处输入图像描述

现在,如果我们想对错误分类的样本做同样的事情,我们需要查看输出概率。由于 iris 数据集有几个类,假设我们想要可视化force_plot那些应该被分类为的样本2,但是我们有一个输出值如下1.7

y_pred = model.predict(xgboost.DMatrix(X_test))
m = (y_pred <= 1.7) & (y_test == 2)

现在我们让我们使用掩码对X_test集合执行布尔索引,并更新shap_values

shap.initjs()
c= explainer.shap_values(X_test[m])
shap.force_plot(explainer.expected_value, shap_values, X_test[m])

在此处输入图像描述

这告诉我们,花瓣的长度和宽度主要是推动回归到更高的值。因此,它们可能是在错误分类中起主要作用的变量。

同样,对于 a decision_plot

shap.decision_plot(explainer.expected_value, shap_values, 
                   X_test[m], feature_order='hclust', 
                   return_objects=True)

在此处输入图像描述

于 2020-10-14T15:08:47.520 回答
0

由于我没有你的数据集,我无法检查代码,但这里有一些想法可能会为你指明方向。

看来你没有训练你的回归者。它应该像线一样

xgbr = xgboost.XGBRegressor()
xgbr.train(X, Y)

现在你可以使用xgbr.predict(X);)

你还需要训练解说员:

explainer = shap.TreeExplainer(xgbr)
with warnings.catch_warnings():
     warnings.simplefilter("ignore")
     sh = explainer.shap_values(X)

现在您可以选择值:

misclassified = (y_pred <= 0.7) & (Y == 1)
shap.decision_plot(expected_value, sh, features_display, link='logit', highlight=misclassified)

在您使用之前,shap我建议您检查您的回归器与您的数据的匹配程度。因此,为此我建议您将部分数据用于测试,而不要在训练中使用它。然后,您可以通过计算和比较测试集和训练集的 MSE 来评估拟合优度。差异越大,您的预测器执行得越差。

于 2020-10-14T14:10:29.797 回答