机器学习实战:Python基于Logistic回归进行金融风控预测(一)
1. Logistic回归在金融风控中的核心价值
第一次接触金融风控项目时,我被要求用最简单的算法构建预测模型。当时团队里有工程师提议上XGBoost,但我坚持先用Logistic回归试水——结果这个"基础款"模型不仅实现了85%的准确率,还因为出色的可解释性获得了风控部门的好评。这让我深刻体会到,在金融领域,模型的可解释性往往比单纯的高精度更重要。
Logistic回归通过sigmoid函数将线性组合映射到(0,1)区间,输出值直接对应违约概率。比如当模型输出0.23时,可以明确解释为"该用户有23%的违约可能性"。这种直观的概率输出,让业务人员能够快速理解模型逻辑,这在需要人工复核的金融场景中至关重要。我经手的一个信用卡审批系统,就是基于概率阈值设定不同审批流程:
- 概率<0.1:自动通过
- 0.1≤概率<0.3:人工复核
- 概率≥0.3:自动拒绝
实际部署时,我们还会输出关键特征贡献度。例如发现"近3个月查询次数"这个特征的权重系数达到0.8,远高于其他特征,这促使风控团队调整了征信查询频次的评分权重。这种透明的决策过程,是黑盒模型难以提供的。
2. 金融数据预处理实战技巧
处理过某银行30万条贷款数据后,我总结出金融数据预处理的三个关键点:
缺失值处理不能简单用均值填充。比如"月收入"字段缺失时,我们结合了其他特征构建填充策略:
def fill_income(row):
if pd.isna(row['income']):
if row['education'] == 'PhD':
return df[df['education']=='PhD']['income'].median()
elif row['property_own'] == 1:
return df['income'].quantile(0.75)
return row['income']
特征分箱能显著提升模型稳定性。对"年龄"字段,我们采用最优分箱:
from sklearn.preprocessing import KBinsDiscretizer
binner = KBinsDiscretizer(n_bins=5, encode='ordinal', strategy='quantile')
df['age_bin'] = binner.fit_transform(df[['age']])
时间窗口特征是金融数据的精髓。我们常构造如下特征:
- 近3个月平均还款延迟天数
- 历史最大连续逾期次数
- 最近一次申请距今的天数
一个实际案例:在某消费贷项目中,添加"近6个月夜间交易占比"这个特征后,KS值提升了12%。这反映出异常交易时间模式与违约风险的正相关性。
3. 金融场景的特征工程方法论
金融风控的特征工程需要兼顾业务逻辑和统计有效性。我常用的特征筛选流程是:
- IV值初筛:删除IV<0.02的特征
from sklearn.feature_selection import f_classif
iv = pd.DataFrame({
'feature': X.columns,
'iv': f_classif(X, y)[0]
})
selected = iv[iv['iv'] > 0.02]['feature']
-
相关性过滤:去除相关系数>0.8的特征对中IV较低者
-
稳定性检验:通过PSI指标验证特征跨时间稳定性
def calc_psi(base, current, bins=10):
base_perc = np.histogram(base, bins=bins)[0]/len(base)
current_perc = np.histogram(current, bins=bins)[0]/len(current)
return np.sum((current_perc - base_perc) * np.log(current_perc/base_perc))
金融特征工程的特殊性在于需要业务解释性。例如:
- 将"负债收入比"离散化为[0,0.3), [0.3,0.6), [0.6,∞)三档
- 对"信用卡额度使用率"做平方变换,放大高负债用户的特征差异
- 构造"最近3个月申请次数/历史总申请次数"的动态比例特征
在某小微企业贷项目中,我们创造性地加入了"法定代表人与实控人关系强度"这个特征,通过股权关联度和通话记录综合计算,最终成为TOP3的重要特征。
4. 模型训练与调优实战
金融场景的Logistic回归调优需要特别注意以下参数:
class_weight:处理极端不平衡数据
model = LogisticRegression(
class_weight={0:1, 1:10}, # 违约样本权重放大10倍
solver='liblinear',
penalty='l1'
)
正则化选择:L1正则更利于特征选择
param_grid = {
'C': [0.001, 0.01, 0.1, 1, 10],
'penalty': ['l1', 'l2']
}
grid = GridSearchCV(estimator=model, param_grid=param_grid, scoring='roc_auc')
金融模型评估要关注业务指标:
- KS值:衡量模型区分度,>0.3可用
- PSI:验证模型稳定性,<0.1为佳
- 滚动率分析:观察坏账迁移情况
我常用的跨时间验证方法:
time_split = TimeSeriesSplit(n_splits=5)
for train_idx, test_idx in time_split.split(X):
X_train, X_test = X.iloc[train_idx], X.iloc[test_idx]
y_train, y_test = y.iloc[train_idx], y.iloc[test_idx]
# 训练和评估...
在利率市场化项目中,我们通过引入弹性网络正则化,在保持模型稀疏性的同时避免了L1正则的过度特征筛选,使AUC提升了5%:
LogisticRegression(
penalty='elasticnet',
l1_ratio=0.5, # L1和L2的混合比例
solver='saga'
)
5. 模型部署与业务应用
将Logistic回归模型部署到生产环境时,我推荐使用PMML格式而非pickle:
from sklearn2pmml import sklearn2pmml
sklearn2pmml(pipeline, "model.pmml", with_repr=True)
金融模型上线后需要持续监控:
- 特征稳定性:每月计算PSI
- 模型衰减:季度性回溯测试
- 规则冲突:与现有风控规则的覆盖检查
一个实用的AB测试框架:
def ab_test(new_model, old_model, sample_data):
new_score = new_model.predict_proba(sample_data)[:,1]
old_score = old_model.predict_proba(sample_data)[:,1]
return {
'ks_delta': ks_2samp(new_score, old_score)[0],
'auc_delta': roc_auc_score(y_true, new_score) - roc_auc_score(y_true, old_score)
}
在消费金融场景中,我们开发了动态阈值调整机制:
def auto_adjust_threshold(profit_matrix, default_rate):
"""
profit_matrix: 2x2矩阵,[[TP收益, FP损失],[FN损失, TN收益]]
default_rate: 当前违约率
"""
return optimize.minimize(
lambda x: -calculate_profit(x, profit_matrix, default_rate),
x0=0.5,
bounds=[(0.3, 0.7)]
).x
最近一个银行项目证明,将Logistic模型与简单规则引擎结合,既能保持模型效果,又能满足监管对规则透明度的要求——这也是为什么在金融领域,Logistic回归始终占据重要地位。
更多推荐
所有评论(0)