rpart决策树仅生成根节点无法分裂,预测结果单一问题咨询
rpart决策树仅输出多数类问题排查与解决
问题描述
尝试构建rpart决策树预测贷款申请人是否违约,操作流程如下:
加载数据集与依赖包:
library(readr) library(dplyr) library(rpart) library(rpart.plot) loans <- read_csv('https://assets.datacamp.com/production/repositories/718/datasets/7805fceacfb205470c0e8800d4ffc37c6944b30c/loans.csv')
转换响应变量类型:
loans <- loans %>% mutate(default = factor(as.character(default), levels = c(0, 1), labels = c('repaid', 'defaulted')))
构建决策树模型:
loans_model <- rpart(default ~ loan_amount + credit_score + debt_to_income, data = loans, method = 'class')
但预测结果全部为repaid:
loans$pred_default <- predict(loans_model, newdata = loans, type = "class") unique(loans$pred_default)
输出:
[1] repaid Levels: repaid defaulted
可视化模型仅显示根节点:
rpart.plot(loan_model)
(对应根节点可视化图片)
原因分析
- 类别不平衡:数据集里
repaid类样本占比过高,rpart默认会优先预测多数类,无需分裂即可获得较高整体准确率,因此不生成子节点。 - 默认参数限制过严:rpart默认的cp(复杂度参数)、minsplit(最小分裂样本数)阈值较高,即使存在潜在分裂特征,也达不到分裂条件。
解决方法
1. 验证类别分布
先确认数据是否存在不平衡:
# 查看各类别样本数 table(loans$default) # 查看各类别占比 prop.table(table(loans$default))
若defaulted类占比极低(如低于10%),则类别不平衡是核心问题。
2. 调整rpart分裂参数
降低cp值、减小minsplit和minbucket,让模型更容易生成子节点:
loans_model <- rpart( default ~ loan_amount + credit_score + debt_to_income, data = loans, method = 'class', cp = 0.001, # 降低复杂度参数,允许更多分裂 minsplit = 10, # 减小分裂所需的最小样本数 minbucket = 5 # 减小叶子节点的最小样本数 )
重新查看模型与预测结果:
# 可视化调整后的决策树 rpart.plot(loans_model) # 重新预测并查看结果 loans$pred_default <- predict(loans_model, newdata = loans, type = "class") unique(loans$pred_default)
3. 处理类别不平衡(可选)
若类别极度不平衡,可通过调整损失权重让模型更关注少数类:
loans_model_weighted <- rpart( default ~ loan_amount + credit_score + debt_to_income, data = loans, method = 'class', # 设置损失矩阵:误判defaulted为repaid的损失设为10,提高少数类权重 parms = list(loss = matrix(c(0, 10, 1, 0), nrow = 2)) )
内容的提问来源于stack exchange,提问作者user21767262
相关产品推荐
相关产品推荐

