scikit-learn - 使用 sklearn pipeline 进行分类任务时,形状图(树解释器)中出现错误

标签 scikit-learn classification pipeline shap treemodel

我正在使用 sklearn 管道进行分类任务,如下所示:

from sklearn.datasets import fetch_openml
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.impute import SimpleImputer
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import OrdinalEncoder

import shap


# -----------------------------------------------------------------------------
# Data
# -----------------------------------------------------------------------------

X, y = fetch_openml("titanic", version=1, as_frame=True, return_X_y=True)

categorical_columns = ["pclass", "sex", "embarked"]
numerical_columns = ["age", "sibsp", "parch", "fare"]

X = X[categorical_columns + numerical_columns]   # [1309, 7] , there is Nan values.
X_train, X_test, y_train, y_test = train_test_split(X, y, stratify=y, random_state=42)


# -----------------------------------------------------------------------------
# Data preprocessing
# -----------------------------------------------------------------------------


categorical_encoder = OrdinalEncoder(
    handle_unknown="use_encoded_value", unknown_value=-1, encoded_missing_value=-1
)

numerical_imputer = SimpleImputer(strategy="mean")


preprocessing = ColumnTransformer(
    [
        ("cat", categorical_encoder, categorical_columns),   
        ("num", numerical_imputer, numerical_columns),
    ],
    verbose_feature_names_out=False,   
)


# -----------------------------------------------------------------------------
# Pipeline
# -----------------------------------------------------------------------------

rf = Pipeline(
    [
        ("preprocess", preprocessing),
        ("classifier", RandomForestClassifier(random_state=42)),
    ]
)


rf.fit(X_train, y_train)


print(f"RF train accuracy: {rf.score(X_train, y_train):.3f}")
print(f"RF test accuracy: {rf.score(X_test, y_test):.3f}")


# -----------------------------------------------------------------------------
# Shap
# -----------------------------------------------------------------------------

explainer = shap.Explainer(rf["classifier"], feature_names=rf["preprocess"].get_feature_names_out())

X_test_processed = rf['preprocess'].transform(X_test)

shap_values = explainer(X_test_processed)

但是,当我尝试获取 Shap 图时,出现以下错误:

shap.summary_plot(shap_values, X_test_processed)

  • 错误:类型错误:只有整数标量数组可以转换为标量索引

shap.summary_plot(shap_values,X_test_processed,plot_type =“bar”)

  • 错误:类型错误:只有整数标量数组可以转换为标量索引

shap.plots.beeswarm(shap_values)

  • 错误:ValueError:蜂群图不支持对具有多个维度的实例进行绘图解释!

shap.plots.bar(shap_values)

  • 错误:IndexError:列表索引超出范围

我做错了什么?请让我知道解决此问题的任何想法。

最佳答案

之后,shap_values 的形状为 (328, 7, 2),并且 beeswarm 错误消息最有用:所有内容都只是一个二维数组。由于某种原因,你得到了两个类的解释,而不仅仅是正类的解释(负类的解释正好与那些类相反);将 [:, :, 1] 放在 shap_values 后面,然后就会为我显示绘图。

我已经在 Colab 上对此进行了测试,但这并不容易允许 python 3.8,因此也不允许 sklearn 1.1,因此我必须进行一些修改。如果它不适合您,请告诉我,我将在本地构建一个更紧密的环境。

如果能理解为什么 shap 会为你提供这两个类的解释,那就太好了。我确实注意到 y 具有分类 pandas 类型,但转换为 int 不会改变任何内容。

关于scikit-learn - 使用 sklearn pipeline 进行分类任务时,形状图(树解释器)中出现错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73605032/

相关文章:

r - 在R Shiny 中编写formatStyle循环

python - 使用 * 参数从 sklearn 进行子类化的正确方法

python - scikit : Wrong prediction for this case

c# - 如何以优雅的方式在致命异常时关闭 TPL 数据流?

algorithm - 这种 AdaBoost 行为是否正确?

java - 指定 Maven 分类器的依赖关系

function - 不能在函数中调用管道属性。电源外壳

python - 是否可以使用 scikit-learn K-Means Clustering 指定您自己的距离函数?

python-3.x - 创建用于多标签分类的数据集

matlab - matlab中的神经网络分类: get probability of element belonging to i-th class