信贷风险预测实战:基于CART决策树的模型构建与优化

1次阅读
没有评论

共计 2491 个字符,预计需要花费 7 分钟才能阅读完成。

image.webp

为什么需要更好的信贷风险评估方法

传统信贷风险评估常依赖逻辑回归,但它有个致命弱点——只能捕捉线性关系。现实中,收入与违约率可能是 U 型曲线(中产最稳定),而逻辑回归无法拟合这种模式。我曾见过一个案例:某银行用逻辑回归模型,结果误批了 23% 的高风险客户,就因为收入 - 年龄的交互效应没处理好。

信贷风险预测实战:基于 CART 决策树的模型构建与优化

决策树家族横向评测

信贷场景需要平衡准确性和可解释性,这是选型的关键:

  • CART 决策树 :白盒模型,通过max_depth=3 就能生成业务人员能看懂的规则,适合风控评审会演示
  • 随机森林:虽然准确率提升 2 -3%,但难以解释为什么拒绝某个客户,合规部门经常挑战
  • XGBoost:在特征重要性评估上更精准,但部署依赖 lib 库,对有些银行的老系统不友好

实际项目中,我们先用 CART 快速验证特征有效性,再用 XGBoost 做最终模型,两者配合效果最佳。

从原始数据到可用模型

数据清洗实战技巧

# 处理缺失值:分类型特征用众数,连续型用中位数
from sklearn.impute import SimpleImputer

cat_imputer = SimpleImputer(strategy='most_frequent')
data[['education', 'job_type']] = cat_imputer.fit_transform(data[['education', 'job_type']])

num_imputer = SimpleImputer(strategy='median')
data[['income', 'debt_ratio']] = num_imputer.fit_transform(data[['income', 'debt_ratio']])

特征分箱的学问

等距分箱会害死模型!金融数据多为右偏分布,应该用分位数分箱:

# 使用 pandas 的 qcut 自动按样本量分箱
import pandas as pd
data['income_bin'] = pd.qcut(data['income'], q=5, labels=False, duplicates='drop')

WOE 编码让特征更听话

证据权重 (Weight of Evidence) 编码能把非线性关系转化为线性:

def woe_encoder(df, feature, target):
    total_good = df[target].value_counts()[0]
    total_bad = df[target].value_counts()[1]

    woe_dict = {}
    for category in df[feature].unique():
        good = df[(df[feature]==category) & (df[target]==0)].shape[0]
        bad = df[(df[feature]==category) & (df[target]==1)].shape[0]

        # 防止除以 0
        good_ratio = (good + 0.5) / (total_good + 1)
        bad_ratio = (bad + 0.5) / (total_bad + 1)

        woe = np.log(good_ratio / bad_ratio)
        woe_dict[category] = woe

    return df[feature].map(woe_dict)

调参不是玄学

决策树最关键的三个参数:

  1. max_depth:从 3 开始尝试,每增加 1 层都要测试业务解释成本
  2. min_samples_leaf:建议设置≥总样本的 5%,防止过拟合
  3. ccp_alpha:成本复杂度剪枝参数,用下面方法找最优值:
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import GridSearchCV

params = {'ccp_alpha': [0.001, 0.01, 0.1]}
clf = GridSearchCV(DecisionTreeClassifier(), params, scoring='roc_auc')
clf.fit(X_train, y_train)

# 可视化剪枝效果
import matplotlib.pyplot as plt
plt.plot(clf.cv_results_['mean_test_score'], marker='o')

生产环境生存指南

处理类别不平衡的三板斧

  • 样本层面:SMOTE 过采样(适合数据少时)
  • 算法层面:class_weight=’balanced’(最省事)
  • 评估层面:用 F1-score 代替准确率(业务更关注坏客户识别率)

严防特征泄露

时间穿越是最隐蔽的坑!一定要:

  • sklearn.pipeline 封装所有预处理步骤
  • 在特征工程阶段坚决不用未来信息(如用全年数据算均值)
  • 部署时保存分箱边界和 WOE 映射表

可视化决策路径

用 graphviz 生成审批流程图,风控总监最爱看这个:

from sklearn.tree import export_graphviz
import graphviz

dot_data = export_graphviz(
    clf,
    feature_names=X.columns,
    class_names=['Good', 'Bad'],
    filled=True
)
graph = graphviz.Source(dot_data)
graph.render('loan_decision_tree')  # 生成 PDF 文件

模型之后才是开始

当模型输出客户评分后,真正的挑战才开始:如何与业务规则联动?比如:

  • 模型拒绝但人工想通过的案例怎么处理?
  • 当国家突然调整 LPR 利率时,如何快速调整阈值?
  • 反欺诈规则和信用评估模型谁先谁后?

建议开发一个决策引擎中间层,把模型分转化为可配置的规则链。我们现在的系统允许业务人员拖拽调整规则优先级,模型只是其中的一个决策节点。

写在最后

信贷风控没有银弹,CART 决策树的价值在于它像玻璃一样透明。当审批委员会质问 ” 为什么拒绝这个客户 ” 时,你能指着树状图说:” 看,因为这个人的收入在第三箱但负债率在第五箱,历史类似客户违约率达 67%”——这种解释力在金融行业比单纯的 AUC 值更重要。

正文完
 0
评论(没有评论)