将自定义模型包装器传入SHAP KernelExplainer时如何保持特征名称对齐?
将自定义模型包装器传入SHAP KernelExplainer时如何保持特征名称对齐?
这个问题我之前也碰到过,核心原因是你的自定义预测函数没有给SHAP提供特征名称的元数据——SHAP对原生sklearn模型会自动读取feature_names_in_这类属性,但对普通函数就没办法自动识别特征名,所以只能默认用“Feature 1”这种占位符。下面给你两种靠谱的解决办法:
方法一:把包装器改成类,添加特征名称属性
把你的自定义预测逻辑封装成一个类,模仿sklearn模型的结构添加feature_names_in_属性,SHAP会自动识别这个属性并使用对应的特征名:
import shap import pandas as pd from sklearn.ensemble import RandomForestClassifier from sklearn.model_selection import train_test_split from sklearn.datasets import load_breast_cancer # 加载数据 data = load_breast_cancer() X = pd.DataFrame(data.data, columns=data.feature_names) y = data.target X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) # 训练模型 model = RandomForestClassifier().fit(X_train, y_train) # 改成类形式的包装器 class ModelWrapper: def __init__(self, model, feature_names): self.model = model self.feature_names_in_ = feature_names # SHAP会自动读取这个属性 def predict_proba(self, data): # 保持你的标准化输出逻辑 return self.model.predict_proba(data) # 初始化包装器并传入特征名 wrapper = ModelWrapper(model, X_train.columns) # 初始化SHAP解释器 explainer = shap.KernelExplainer(wrapper.predict_proba, shap.sample(X_train, 10)) shap_values = explainer.shap_values(X_test.iloc[:5, :]) # 现在summary_plot会显示正确的特征名 shap.summary_plot(shap_values[1], X_test.iloc[:5, :])
方法二:在summary_plot中手动指定特征名
如果不想修改包装器结构,可以直接在绘制SHAP图的时候通过feature_names参数手动传入列名,这种方式更直接:
# 沿用你原来的代码,只修改绘图部分 shap.summary_plot(shap_values[1], X_test.iloc[:5, :], feature_names=X_test.columns)
额外注意点
- 确保你传入SHAP的背景数据(
shap.sample(X_train, 10))是带列名的DataFrame,而不是numpy数组,这样能避免SHAP在处理过程中丢失特征名关联。 - 如果你后续还要用其他SHAP绘图函数(比如
force_plot),方法一的类包装器会更省心,因为它能让你的包装器和原生sklearn模型有一致的接口,适配更多SHAP功能。
备注:内容来源于stack exchange,提问作者Zümra Arslanhan
相关产品推荐
相关产品推荐

