智能风控:Python 金融风险管理与评分卡建模 - 梅子行/毛鑫宇
<Img src="https://cosmos-x.oss-cn-hangzhou.aliyuncs.com/s33648744.jpg" alt="s33648744" width=300 />
本书基于 Python 讲解了信用风险管理和评分卡建模,从风险业务、统计分析方法、机器学习模型 3 个维度展开,详细讲解了信用风险量化相关的数据 分析与建模手段。
关于作者
梅子行/毛鑫宇 是金融科技风控领域专家:
- 风控从业者:在金融机构从事风险管理工作多年
- 技术实践者:专注于机器学习在风控领域的应用
- 知识分享者:在知乎、GitHub 等平台分享风控技术文章
- 开源贡献者:参与风控相关开源项目开发
作者团队以其"实战导向、代码驱动"的写作风格著称,他们将信贷风控的实战经验与 Python 技术相结合,提供了大量可落地的代码和案例。
经典摘录
风控的核心不是拒绝风险,而是识别、定价和管理风险。
评分卡是将用户特征转化为信用分数的数学模型。
好的风控模型是在准确率和稳定性之间找到平衡。
特征工程的质量决定了模型效果的上限。
风控模型不仅要预测准确,还要可解释、可追溯。
数据是风控的燃料,算法是风控的引擎。
风控是金融业务的生命线。
核心内容
1. 信用风险管理基础
信用风险概述
1. 信用风险定义
- 借款人违约导致损失的风险
- 金融机构面临的主要风险
- 巴塞尔协议核心关注点
2. 风险类型
违约风险 (Default Risk):
- 借款人无法按时还款
- 最直接的信用风险
敞口风险 (Exposure Risk):
- 风险暴露的大小
- 贷款金额、剩余期限
回收风险 (Recovery Risk):
- 违约后能收回多少
- 抵押物、追偿能力
3. 风险管理流程
贷前:
- 反欺诈
- 信用评估
- 授信审批
- 定额定价
贷中:
- 放款审核
- 用信监控
- 行为评分
贷后:
- 还款监控
- 逾期管理
- 催收
- 资产处置
4. 关键指标
不良率 (NPL Ratio):
- 不良贷款/总贷款
- 衡量资产质量
逾期率 (Delinquency Rate):
- 逾期贷款/总贷款
- 早期预警指标
核销率 (Charge-off Rate):
- 核销金额/平均贷款余额
- 实际损失
回收率 (Recovery Rate):
- 收回金额/违约金额
- 催收效果
2. 评分卡模型
评分卡类型
1. 申请评分卡 (A 卡)
用途:
- 贷前审批
- 新客户信用评估
- 决定是否放款
数据源:
- 申请表信息
- 征信报告
- 外部数据
特点:
- 样本量大
- 特征稳定
- 要求高准确率
2. 行为评分卡 (B 卡)
用途:
- 贷中管理
- 存量客户评估
- 提额、定价依据
数据源:
- 还款历史
- 用信行为
- 账户变动
特点:
- 数据丰富
- 时效性强
- 可频繁更新
3. 催收评分卡 (C 卡)
用途:
- 贷后管理
- 逾期客户评估
- 催收策略制定
数据源:
- 逾期信息
- 催收记录
- 还款承诺
特点:
- 针对逾期客户
- 预测还款概率
- 优化催收资源
4. 反欺诈评分卡 (F 卡)
用途:
- 识别欺诈申请
- 第一道防线
- 拒绝明显欺诈
数据源:
- 设备指纹
- 行为数据
- 黑名单
- 关联网络
特点:
- 实时性要求高
- 规则 + 模型
- 宁错杀不放过
3. 特征工程
特征处理流程
1. 数据探索
缺失值分析:
```python
import pandas as pd
import numpy as np
# 缺失值统计
missing = df.isnull().sum()
missing_ratio = df.isnull().sum() / len(df)
# 缺失值可视化
import matplotlib.pyplot as plt
plt.figure(figsize=(10, 6))
missing_ratio.sort_values(ascending=False).head(20).plot.bar()
plt.title('Top 20 Features with Missing Values')
plt.ylabel('Missing Ratio')
异常值检测:
# 箱线图检测异常值
plt.boxplot(df['amount'])
# 3σ原则
mean = df['amount'].mean()
std = df['amount'].std()
outliers = df[(df['amount'] \< mean - 3*std) |
(df['amount'] > mean + 3*std)]
-
特征选择
过滤法:
from sklearn.feature_selection import VarianceThreshold# 低方差过滤vt = VarianceThreshold(threshold=0.01)X_filtered = vt.fit_transform(X)# 相关系数过滤corr_matrix = df.corr()# 删除高相关特征包装法:
from sklearn.feature_selection import RFEfrom sklearn.linear_model import LogisticRegression# 递归特征消除model = LogisticRegression()rfe = RFE(estimator=model, n_features_to_select=10)rfe.fit(X, y)嵌入法:
from sklearn.ensemble import RandomForestClassifier# 特征重要性rf = RandomForestClassifier()rf.fit(X, y)importances = rf.feature_importances_ -
特征转换
分箱 (Binning):
# 等宽分箱df['age_bin'] = pd.cut(df['age'], bins=5)# 等频分箱df['income_bin'] = pd.qcut(df['income'], q=5)# 自定义分箱bins = [0, 18, 25, 35, 45, 55, 60, 100]labels = ['\<18', '18-25', '25-35', '35-45', '45-55', '55-60', '60+']df['age_bin'] = pd.cut(df['age'], bins=bins, labels=labels)编码:
# Label Encodingfrom sklearn.preprocessing import LabelEncoderle = LabelEncoder()df['city_encoded'] = le.fit_transform(df['city'])# One-Hot Encodingdf = pd.get_dummies(df, columns=['city']) -
WOE 编码
定义:
def calculate_woe(df, feature, target):"""计算特征的 WOE 值"""grouped = df.groupby(feature)[target].agg(['sum', 'count'])grouped['good'] = grouped['count'] - grouped['sum']total_bad = df[target].sum()total_good = len(df) - total_badgrouped['bad_dist'] = grouped['sum'] / total_badgrouped['good_dist'] = grouped['good'] / total_good# WOE = ln(good_dist / bad_dist)grouped['woe'] = np.log(grouped['good_dist'] / grouped['bad_dist'])return grouped['woe'].to_dict()
### 4. 模型评估指标
评估指标体系
-
混淆矩阵
from sklearn.metrics import confusion_matrix# 混淆矩阵cm = confusion_matrix(y_true, y_pred)# 可视化import seaborn as snssns.heatmap(cm, annot=True, fmt='d', cmap='Blues') -
基础指标
准确率 (Accuracy):
from sklearn.metrics import accuracy_scoreaccuracy = accuracy_score(y_true, y_pred)精确率 (Precision):
from sklearn.metrics import precision_scoreprecision = precision_score(y_true, y_pred)# 预测为坏客户中,真正的坏客户比例召回率 (Recall):
from sklearn.metrics import recall_scorerecall = recall_score(y_true, y_pred)# 真正的坏客户中,被预测出来的比例F1 分数:
from sklearn.metrics import f1_scoref1 = f1_score(y_true, y_pred)# 精确率和召回率的调和平均 -
KS 统计量
定义:
def calculate_ks(y_true, y_score):"""计算 KS 统计量"""from sklearn.metrics import roc_curvefpr, tpr, thresholds = roc_curve(y_true, y_score)ks = max(tpr - fpr)return ks解读:
- KS < 0.2: 模型效果差
- 0.2 <= KS < 0.3: 一般
- 0.3 <= KS < 0.4: 良好
- KS >= 0.4: 优秀
-
AUC-ROC 曲线
from sklearn.metrics import roc_curve, aucimport matplotlib.pyplot as pltfpr, tpr, thresholds = roc_curve(y_true, y_score)roc_auc = auc(fpr, tpr)plt.figure(figsize=(8, 6))plt.plot(fpr, tpr, label=f'AUC = {roc_auc:.3f}')plt.plot([0, 1], [0, 1], 'k--')plt.xlabel('False Positive Rate')plt.ylabel('True Positive Rate')plt.title('ROC Curve')plt.legend() -
PSI 稳定性指标
def calculate_psi(expected, actual):"""计算 PSI (Population Stability Index)"""def get_bins(data):return np.histogram(data, bins=10, density=True)[0]expected_dist = get_bins(expected)actual_dist = get_bins(actual)psi = np.sum((actual_dist - expected_dist) *np.log(actual_dist / expected_dist))return psi解读:
- PSI < 0.1: 稳定
- 0.1 <= PSI < 0.25: 轻微变化
- PSI >= 0.25: 显著变化