R中partykit::glmtree无法完成违约评分分箱,寻求解决方法
问题背景
需要用R的partykit包中glmtree函数,对代表违约(default=1)可能性的评分进行分箱,要求每个分箱内违约率相近。此前方法可行,但当评分的违约预测能力大幅提升后,glmtree无法输出有效解。
合成数据示例
library(tidyverse) sigmoid <- function(x) { 1 / (1 + exp(-x)) } n_sample <- 10^5 score <- runif(n_sample, min = -5, max = 5) defaults <- rbinom(length(score), size = 1, prob = sigmoid(score)) df <- tibble(score = score, default_flag = defaults) partykit::glmtree(formula = default_flag ~ score, data = as.data.frame(df), family = binomial)
评分等分分箱后的违约率分布
执行以下代码将评分等分为100个分箱,并绘制违约率分布:
df %>% mutate(score_bin = cut(score, breaks = 100)) %>% group_by(score_bin) %>% summarise(default_rate = sum(default_flag)/ n()) %>% plot()

用户疑问与核心问题
- 用户直觉:
glmtree无法找到解,会不会是因为存在大量效果优异的分割点,都能将数据分成违约率差异明显的组?这个推测是否合理? - 核心问题:如何让
partykit::glmtree在上述示例中成功完成分箱?
已尝试的方案
- 将
maxit参数增加至100 - 增大
minsize参数 - 使用
ctree函数可快速得到分箱解
解决方案
1. 调整正则化参数
当变量预测能力极强时,glmtree易因分割点过多或过度拟合无法收敛,可通过alpha(L1正则化)、lambda(L2正则化)限制模型复杂度:
partykit::glmtree(formula = default_flag ~ score, data = as.data.frame(df), family = binomial, alpha = 0.5, # 0为纯L2正则化,1为纯L1正则化,0-1为混合正则化 lambda = 0.1) # 正则化强度,可根据数据调整
2. 限制树的最大深度
通过maxdepth参数控制分割层数,避免模型尝试过多无意义的分割:
partykit::glmtree(formula = default_flag ~ score, data = as.data.frame(df), family = binomial, maxdepth = 3) # 限制树最多3层分割
3. 放宽分割检验的显著性阈值
默认检验标准可能过于严格,可通过testtype和对应alpha参数(此alpha为检验显著性水平,与正则化参数区分)调整:
partykit::glmtree(formula = default_flag ~ score, data = as.data.frame(df), family = binomial, testtype = "Bonferroni", alpha = 0.1) # 阈值从默认0.05提高至0.1,放宽检验标准
4. 先预分箱再建模
若上述方法无效,可先对评分做粗分箱,再基于分箱后的变量建模:
# 先将评分分为10个初始分箱 df <- df %>% mutate(score_pre_bin = cut(score, breaks = 10)) # 基于预分箱变量运行glmtree partykit::glmtree(formula = default_flag ~ score_pre_bin, data = as.data.frame(df), family = binomial)
关于用户直觉的验证
你的推测是合理的:当评分预测能力极强时,几乎所有分割点都能显著区分违约率高低的组,导致glmtree在选择最优分割点时陷入困境——大量分割点的检验统计量都极高,模型难以收敛到稳定解。而ctree的分割逻辑更侧重显著性检验,因此这种场景下更容易输出结果。
内容的提问来源于stack exchange,提问作者PalimPalim
相关产品推荐
相关产品推荐

