使用R语言如何按类别可视化二分类XGBoost模型的特征重要性
二分类XGBoost按类别展示SHAP特征重要性实现方案
核心逻辑
你之前生成的是全局特征重要性,是所有样本的平均绝对SHAP值统计结果。要区分二分类两个类别的特征重要性,只需将样本按真实标签(或预测标签)分组,分别统计每个分组内各特征的平均绝对SHAP值即可。
修正后可运行代码
首先修正你原代码中的笔误,补充标签匹配和分组统计逻辑:
library(caret) library(dplyr) library(xgboost) library(ggplot2) library(SHAPforxgboost) # --------------- 原有模型训练逻辑(保留即可)--------------- x_train_xgb<-xgb.DMatrix(as.matrix(x_train),label=y_train) x_test_xgb<-xgb.DMatrix(as.matrix(x_test),label=y_test) params_xgb<-list(booster = "dart", objective = "binary:logistic",eta=0.3,gamma=1,max_depth=5, min_child_weight=2,subsample=1,colsample_bytree=1,lambda=1.25,alpha=0.75) xgb_cv<-xgb.cv(params=params_xgb, data=x_train_xgb,nrounds=600,nfold=5,showsd = T, early.stop.round = 35, maximize = F,metrics=c('auc')) gb_dt <- xgb.train(params = params_xgb, data = x_train_xgb, nrounds = xgb_cv$best_iteration, print_every_n = 2, eval_metric=c('auc'), watchlist=list(train=x_train_xgb,eval=x_test_xgb)) xgb_pred<-predict(gb_dt,x_test_xgb) binary_pred_xgb<-as.numeric(xgb_pred > 0.5) confusionMatrix(as.factor(binary_pred_xgb),as.factor(y_test)) # --------------- 新增按类别统计SHAP重要性逻辑 --------------- # 基于测试集计算SHAP值,和测试集标签一一对应 xgb_contrib <- shap.values(gb_dt, X_train = as.matrix(x_test)) shap_value_xgb <- xgb_contrib$shap_score # 生成SHAP长表,移除原代码中笔误的var_cat参数 shap_long_xgb <- shap.prep( shap_contrib = shap_value_xgb, X_train = as.matrix(x_test) ) # 匹配每个样本的真实标签 shap_long_xgb <- shap_long_xgb %>% group_by(ID) %>% mutate(true_label = as.factor(y_test[cur_group_id()])) %>% ungroup() # 按标签分组统计各特征重要性 class_importance <- shap_long_xgb %>% group_by(true_label, variable) %>% summarise( mean_abs_shap = mean(abs(shap_value)), .groups = "drop" ) %>% group_by(true_label) %>% mutate(percentage = round(mean_abs_shap / sum(mean_abs_shap) * 100, 2)) %>% slice_max(order_by = mean_abs_shap, n = 10) %>% # 每个类别取Top10特征 ungroup() # 分面绘制两个类别的特征重要性 ggplot(class_importance, aes(x = reorder(variable, percentage), y = percentage, fill = true_label)) + geom_col(show.legend = FALSE) + geom_text(aes(label = paste0(percentage, "%")), hjust = -0.1, size = 3) + facet_wrap(~true_label, scales = "free_y", labeller = labeller(true_label = c("0" = "负类", "1" = "正类"))) + coord_flip() + labs(x = "特征名称", y = "平均SHAP值占比(%)", title = "不同类别下Top10特征重要性") + theme_minimal()
如果需要按模型预测标签分组统计,只需将上述代码中y_test替换为binary_pred_xgb即可
可选拓展:查看特征对分类结果的影响方向
如果不仅要看重要性,还要看特征取值高低对分类为正类/负类的影响,可直接调用SHAP摘要散点图:
shap.plot.summary(shap_long_xgb)
该图横轴为SHAP值(正代表推高正类概率,负代表推高负类概率),点的颜色代表特征取值高低,可直观看到每个特征对两类结果的影响逻辑。
内容的提问来源于stack exchange,提问作者Candra Parashian
相关产品推荐
相关产品推荐

