树模型在信贷风控怎么用——从决策树到 XGBoost

导语:评分卡解释性强,但抓不住复杂交叉。想提精度,就用树模型(XGBoost/LightGBM)。代价是:黑箱。

一、它解决什么问题

捕捉"收入中等 + 多头多 + 夜间活跃"这类非线性交叉风险,把 KS/AUC 往上提几个点。

二、原理(直觉)

  • 决策树:按"哪个变量切一刀最能分开好坏"递归分裂,直到纯净或到限制。
  • 集成(GBDT/XGBoost):训很多棵弱树,每棵修正前一棵的残差,加权求和。树多→拟合强。

三、信贷里怎么做

  1. 特征工程(行为/交易/征信/设备),不用先分箱(树自己切)。
  2. 训练:调 max_depth(树深,防过拟合)、learning_rate(小一点稳)、subsample(行采样)。
  3. 评估:KS、AUC,重点看**训练集 vs 验证集 vs 时间外样本(OOT)**是否一致。
  4. 可解释:用 SHAP 看每个变量贡献,或把树提取成规则给业务用。

四、代码骨架

python 复制代码
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.metrics import roc_auc_score
import xgboost as xgb
---------- 1. 数据准备 ----------
假设 df 已包含特征列和标签列 y(0=好客户,1=坏客户)
按时间切分:观察期样本用于训练/验证,表现期之后的样本作为 OOT
df_train_val = df[df["month"] <= "2024-06"]   # 观察期
df_oot = df[df["month"] > "2024-06"]          # 时间外样本(OOT)
features = ["income", "multi_loan_cnt", "night_active_ratio", "device_risk_score"]
X = df_train_val[features]
y = df_train_val["y"]
训练集 / 验证集(按时间顺序切,避免未来信息泄漏)
X_train, X_val, y_train, y_val = train_test_split(
X, y, test_size=0.2, random_state=42, stratify=y
)
X_oot, y_oot = df_oot[features], df_oot["y"]
---------- 2. 参数设置 ----------
params = {
"max_depth": 4,          # 树深:控制模型复杂度,防止过拟合
"learning_rate": 0.05,   # 学习率:调小一点更稳,但需要更多树
"subsample": 0.8,        # 行采样:每棵树只用 80% 样本,增强泛化
"colsample_bytree": 0.8, # 列采样:每棵树只用 80% 特征
"eval_metric": "auc",
"objective": "binary:logistic",
"n_estimators": 500,
"early_stopping_rounds": 50,  # 验证集 AUC 连续 50 轮不提升则提前停止
}
---------- 3. 训练 ----------
model = xgb.XGBClassifier(**params)
model.fit(
X_train, y_train,
eval_set=[(X_val, y_val)],
verbose=False,
)
---------- 4. KS / AUC 评估 ----------
def ks_score(y_true, y_prob):
"""计算 KS 统计量:好坏样本累计分布的最大差距"""
df_ks = pd.DataFrame({"y": y_true, "prob": y_prob})
df_ks = df_ks.sort_values("prob", ascending=False).reset_index(drop=True)
df_ks["cum_bad"] = (df_ks["y"] == 1).cumsum() / (df_ks["y"] == 1).sum()
df_ks["cum_good"] = (df_ks["y"] == 0).cumsum() / (df_ks["y"] == 0).sum()
return (df_ks["cum_bad"] - df_ks["cum_good"]).abs().max()
for name, X_eval, y_eval in [
("训练集", X_train, y_train),
("验证集", X_val, y_val),
("OOT", X_oot, y_oot),
]:
prob = model.predict_proba(X_eval)[:, 1]
auc = roc_auc_score(y_eval, prob)
ks = ks_score(y_eval, prob)
print(f"{name}: AUC={auc:.4f}, KS={ks:.4f}")
重点:训练集 / 验证集 / OOT 的 KS、AUC 应基本一致,
若 OOT 明显下滑,说明存在过拟合或特征泄漏,需回查特征与切分逻辑。

五、常见坑

  • KS 虚高:特征里混进"未来信息"(如用了表现期才有的变量)→ 线上必崩。严格按观察/表现期切。
  • 过拟合:树太深,训练 KS 高、OOT 掉。看 OOT。
  • 黑箱难解释:监管/业务要理由,务必配 SHAP 或转规则。
  • 训练/线上不一致:特征的缺失、分箱逻辑上线要对齐。

六、小结

树模型提精度,但必须配可解释和 OOT 验证。评分卡管"稳",树模型管"准",实战常并用:树模型做主模型,评分卡做可解释备份/兜底。

相关推荐
锋行天下8 小时前
langgraph 后端发自定义数据,前端接收方法概括
人工智能·python
泯泷9 小时前
单个 AI 再强,为什么也干不过一支 AI 团队?
人工智能·llm·agent
浪遏9 小时前
认识 wm:从多平台发布到可扩展 CLI 的架构设计
人工智能
深蓝AI9 小时前
英伟达换帅当天,我先跑了一遍 GPU 环境体检:版本矩阵比人事更值得盯
人工智能·gpu
专注仿真10 小时前
知识问答模型用到的算法集详解及代码实例
python·算法·代码·大模型训练·控制算法
罗西的思考11 小时前
【轻量化复刻大模型 / KIMI K3】AttnRes 模块交互式演示
人工智能·算法·机器学习
stormzhangV11 小时前
涨薪 50% 怎么做到的?
人工智能·面试·aigc
老金带你玩AI12 小时前
如何在5分钟之内创建Grok Bot的超级团队
人工智能
程序员cxuan12 小时前
离谱,AI 大佬顺手搓了个 YouTube ,而我顺手给他搓了个中文插件
人工智能·后端·程序员
zixu_star13 小时前
上下文工程:Prompt、记忆和上下文如何管理?
人工智能·prompt