游乐游手机版
首页/AI热点日报/热点详情

基于SHAP的二分类RF模型特征贡献与交互网络解析

类型:热点整理2026-06-26
二分类任务中,SHAP值的结构与多分类模型类似,但又略有不同。以随机森林(RF)为例,模型会为类别0和类别1分别输出一组SHAP值——但这里有一个关键点:在二分类任务里,两个类别互为对立面,因此它们的SHAP值恰好互为相反数,并且总和为零。换句话说,类别0和类别1的SHAP绝对值均值是完全一致的。相
二分类任务中,SHAP值的结构与多分类模型类似,但又略有不同。以随机森林(RF)为例,模型会为类别0和类别1分别输出一组SHAP值——但这里有一个关键点:在二分类任务里,两个类别互为对立面,因此它们的SHAP值恰好互为相反数,并且总和为零。换句话说,类别0和类别1的SHAP绝对值均值是完全一致的。相比之下,像XGBoost这样的部分二分类模型,则只输出一组SHAP值,用来统一刻画样本朝类别1方向变化的贡献。所以,在对RF模型进行可视化时,通常只拿类别1的SHAP值及其交互值作为分析对象。在实际操作中其实很简单:计算出SHAP值后,再额外提取出类别1的那部分数据,就可以直接用来构建特征贡献与特征交互网络图了。 必须强调一点:本节所用数据均为模拟数据,没有任何现实意义。所有代码和图表均基于个人对机器学习的理解进行实现,仅供技术交流参考。

基础代码

  
import pandas as pd  
import numpy as np  
import matplotlib.pyplot as plt  
import warnings  
# 忽略所有警告
warnings.filterwarnings("ignore")  
path = r"2026-6-8公众号Python机器学习AI.csv"  
df = pd.read_csv(path)  
  
from sklearn.model_selection import train_test_split  
  
# 划分特征和目标变量
X = df.drop(['target'], axis=1)    
y = df['target']    
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(  
    X,    
    y,   
    test_size=0.3,   
    random_state=42,   
    stratify=df['target']   
)  
  
from sklearn.ensemble import RandomForestClassifier  
from sklearn.model_selection import GridSearchCV  
  
# 定义随机森林模型
rf_model = RandomForestClassifier(  
    random_state=42,  
    n_jobs=-1  
)  
  
# 定义随机森林超参数网格
hyperparameter_grid = {  
    'n_estimators': [100, 200, 300],        # 树的数量
    'max_depth': [None, 3, 6, 10],          # 树的最大深度
    'min_samples_split': [2, 5, 10],        # 内部节点再划分所需的最小样本数
    'min_samples_leaf': [1, 2, 4],          # 叶子节点所需的最小样本数
    'max_features': ['sqrt', 'log2', None], # 每次分裂考虑的最大特征数
    'bootstrap': [True, False]              # 是否使用 bootstrap 抽样
}  
  
# 初始化网格搜索
grid_search = GridSearchCV(  
    estimator=rf_model,  
    param_grid=hyperparameter_grid,  
    cv=5,                  # 5折交叉验证
    n_jobs=-1,             # 使用所有可用CPU
    verbose=2,             # 输出详细搜索过程
    scoring='accuracy'     # 评价指标
)  
  
# 在训练集上进行网格搜索
grid_search.fit(X_train, y_train)  
  
  
# 使用最佳参数模型
best_rf_model = grid_search.best_estimator_  
  
import shap  
  
# 为测试集计算 SHAP 交互值
explainer = shap.TreeExplainer(best_rf_model)  
shap_interaction_values = explainer.shap_interaction_values(X_test)  
  
# 计算 SHAP 值
shap_values = explainer.shap_values(X_test)  
print("SHAP values:", shap_values.shape)  
print(shap_interaction_values.shape)
  
SHAP values: (90, 13, 2)  
(90, 13, 13, 2)
先读取数据集,将target设为目标变量,其余留作特征。按7:3的比例划分训练集和测试集,并且利用stratify参数确保两集的类别比例保持一致。接着,构建随机森林分类器,配合GridSearchCV在多个超参数组合上进行5折交叉验证,最终以准确率为指标筛出最优模型。模型到手后,再用shap.TreeExplainer对测试集计算SHAP值和交互值,这样就能搞清楚每个特征独立的贡献,以及两两特征之间的交互影响。 从结果来看,shap_values的维度是(90, 13, 2)——代表90个测试样本、13个特征、2个类别。最后一个维度分别对应类别0和类别1的SHAP值。而shap_interaction_values的维度是(90, 13, 13, 2),意味着对每一个测试样本,模型都计算了13个特征之间两两交互的贡献矩阵,并且同样按两个类别分开。所以,RF模型二分类的SHAP输出形式和多分类模型很像,需要按研究目标进一步提取。既然我们的关注点放在类别1上,那就可以直接用shap_values[:, :, 1]和shap_interaction_values[:, :, :, 1]来提取类别1的特征贡献值和交互值,后续的网络图构建也就顺理成章了。
  
fig, ax = plot_feature_interaction_and_importance_optimized_cb(  
    interaction_df,  
    importance_df,  
    interaction_cmap=interaction_cmap_literature,  
    importance_cmap=importance_cmap_literature,  
    title="diseased",  
    background_style="curve_shadow",  
    shadow_all_pairs=True,  
    shadow_color="lightgray",  
    shadow_alpha=0.16,  
    shadow_base_width=1.4,  
    edge_curve_strength=0.42,  
    edge_curve_jitter=0.035,  
    edge_alpha=0.55,  
    cbar_borderpad=4,  
    cbar_title_y=1,  
    edge_width_range=(0.25, 6.0),  
    node_size_range=(70, 1400),  
    label_offset=0.16,  
    figsize=(8, 8),  
    sa ve_path="feature_network.png",  
)

现在,基于这个二分类糖尿病模型的SHAP结果,我们绘制出患病类别对应的特征贡献与交互网络图。这张图里,节点大小和颜色深度代表特征的重要性——越大的节点、越深的颜色,意味着该特征对模型判别为患病类别的平均贡献越大。连线的粗细和颜色则体现特征之间的交互强度:红色越明显、线条越粗,说明这两个特征在共同影响预测时,交互作用越强。 从最终呈现的结果来看,cp是整个网络中最突出的特征,节点大、颜色深,说明它对模型识别患病样本的贡献最高。紧随其后的是thal、ca、exang和oldpeak,这几个也表现出了不低的重要性。至于交互关系,ca与cp之间的那根红色粗线格外醒目,提示模型在判别患病类别时,这两个特征存在较强的协同作用。另外,thal、exang、oldpeak与其他特征之间也有一些交互,不过强度相对弱一些。整体而言,这张网络图清晰地告诉我们:模型预测患病类别时,主要依赖少数几个关键特征以及它们之间的交互组合,其中cp、thal、ca是驱动判别的主力。

值得一提的是,只要调整函数中的interaction_cmap和importance_cmap参数,这套代码就可以在保持网络结构和数值映射不变的前提下,快速生成不同色系风格的网络图。这样一来,不管是不同论文的主题色系,还是期刊风格偏好,都可以一键切换,非常灵活。 不过有件事得说清楚:SHAP特征贡献与交互网络图的主要价值,是从整体上识别那些驱动模型预测的关键变量,以及它们之间潜在的交互关系——比如哪些特征贡献更大、哪些组合可能一起影响预测。但它并不能告诉我们单个特征在不同取值区间内的具体作用方向。举个例子,你没法直接从这张图里看出某个特征在什么范围内倾向于推动模型预测为类别1,又或者在什么范围内更倾向于预测为类别0。要想摸清这层关系,就需要引入SHAP依赖图来做更细致的分析了。相关方法可以翻阅历史文章里关于SHAP依赖图与交互图的解析。 最后再说一句:SHAP解释反映的只是模型内部学到的统计关联,不是因果推断。所以,看到某个特征对预测的影响大,并不能直接认为它真的会导致疾病或改变风险——二者之间只是相关关系,请务必注意。

该文章案例

在附带的资料中,和往期文章一样,我们会把这个案例的每个步骤逐步拆解开,力求让读者能达到最好的学习效果。内容都经过了详细的解读,帮助大家理解模型实现和数据分析的每个细节。

介绍

到这里,本节的内容就告一段落了。案例资料中包含了代码、注释、数据说明以及参考文献,方便大家学习和复现。

来源:https://developer.volcengine.com/articles/7655014278075777070

相关热点

继续查看同栏目近期热点。

延伸阅读

补充最近整理过的热点入口。