Ami*_*t S 4 python machine-learning random-forest scikit-learn shap
我用 SHAP 来解释我的 RF
RF_best_parameters = RandomForestRegressor(random_state=24, n_estimators=100)
RF_best_parameters.fit(X_train, y_train.values.ravel())
shap_explainer_model = shap.TreeExplainer(RF_best_parameters)
Run Code Online (Sandbox Code Playgroud)
TreeExplainer 类有一个属性expected_value
。我的第一个猜测是,根据 X_train,该字段是预测 y 的平均值(我也在此处阅读了此内容)
但事实并非如此。
命令的输出:
shap_explainer_model.expected_value
Run Code Online (Sandbox Code Playgroud)
是 0.2381。
命令的输出:
RF_best_parameters.predict(X_train).mean()
Run Code Online (Sandbox Code Playgroud)
是 0.2389。
正如我们所看到的,这些值并不相同。那么这里的意思是什么呢expected_value
?
这是由于该方法与随机森林算法一起使用时的特殊性所致;引用相关 Github 线程shapexplainerexplainerexpected_value中的响应与模型期望值不同:
这是因为 sklearn 如何在其构建的树模型中记录训练样本。随机森林使用数据的随机子样本来训练每棵树,sklearn 中正是使用该随机子样本来记录模型中的叶子样本权重。由于 TreeExplainer 使用记录的叶子样本权重来表示训练数据集,因此它将取决于训练期间使用的随机采样。这会导致像您所看到的那样的微小变化。
我们实际上可以验证其他算法不存在这种行为,例如梯度提升树:
from sklearn.datasets import make_regression
from sklearn.model_selection import train_test_split
from sklearn.ensemble import GradientBoostingRegressor, RandomForestRegressor
import numpy as np
import shap
shap.__version__
# 0.37.0
X, y = make_regression(n_samples=1000, n_features=10, random_state=0)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)
gbt = GradientBoostingRegressor(random_state=0)
gbt.fit(X_train, y_train)
mean_pred_gbt = np.mean(gbt.predict(X_train))
mean_pred_gbt
# -11.534353657511172
gbt_explainer = shap.TreeExplainer(gbt)
gbt_explainer.expected_value
# array([-11.53435366])
np.isclose(mean_pred_gbt, gbt_explainer.expected_value)
# array([ True])
Run Code Online (Sandbox Code Playgroud)
但对于 RF,我们确实得到了一个“小变化”,正如主要 SHAP 开发人员在上面的线程中提到的那样:
rf = RandomForestRegressor(random_state=0)
rf.fit(X_train, y_train)
rf_explainer = shap.TreeExplainer(rf)
rf_explainer.expected_value
# array([-11.59166808])
mean_pred_rf = np.mean(rf.predict(X_train))
mean_pred_rf
# -11.280125877556388
np.isclose(mean_pred_rf, rf_explainer.expected_value)
# array([False])
Run Code Online (Sandbox Code Playgroud)