基于Python的银行信贷风险可视化与预警建模
银行信贷风险评估模型代码分析
一、背景概要
信贷业务又称为信贷资产或贷款业务,是商业银行最重要的资产业务,通过放款收回本金和利息,扣除成本后获得利润,所以信贷是商业银行的主要赢利手段。
二、代码解析
1 相关技术背景
XGBoost是一套提升树可扩展的机器学习系统。目标是设计和构建高度可扩展的端到端提升树系统。提出了一个理论上合理的加权分位数略图来计算候选集。引入了一种新颖的稀疏感知算法用于并行树学习。提出了一个有效的用于核外树形学习的缓存感知块结构。用缓存加速寻找排序后被打乱的索引的列数据的过程。XGBoost是一个树集成模型,他将K(树的个数)个树的结果进行求和,作为最终的预测值。
2 算法解析
使用机器学习建模的一般流程。分为两大部分:数据处理和模型学习。第一部分需要大量的知识对原始数据进行清理及特征提取;第二部分模型学习,涉及长时间的模型参数调整,调整方向和策略需要根据经验来灵活调整。当模型效果不理想时,考虑的调整策略:
- 调节正负样本的权重参数。
- 更换模型算法。
- 同时几个使用模型进行预测,然后取去测的最终结果。
- 使用原数据,生成新特征。
1. Logistic函数
Logistic回归模型中的因变量只有1和0(发生于不发生)两种。假设在p个独立自变量x1,x2…xp作用下,y取1的概率是p = P(y = 1|X)取0的概率是1-p,取1和取0的概率之比为:P/(1-P);称为事件的优势比(odds),对odds取自然对数得Logistic变换。
2.Logistic回归建模步骤
(a)根据分析目的设置指标变量(因变量和自变量),然后收集数据,根据收集到的数据,对特征再次进行筛选;
#特征重要程度情况 ax = xgb.plot_importance(model) fig = ax.figure fig.set_size_inches(15,10) |
(b)y取1的概率是p= P(y= 1|X), 取0概率是1-p。用
ln(p/(1−p))和自变量列出线性回归方程,估计出模型中的回归系数;
(c)进行模型检验。模型有效性的检验指标有很多,最基本的有正确率,其次有混淆矩阵、ROC曲线、KS值等。
(d)模型应用:输入自变量的取值,就可以得到预测变量的值,或者根据预测变量的值去控制自变量的取值。
实例:
gender |
age |
dist |
edu |
job |
lmt |
basicLevel |
x_0 |
x_1 |
2 |
27 |
640500 |
0 |
8 |
5.963 |
3 |
0 |
0 |
2 |
25 |
640600 |
0 |
3 |
6.467 |
3 |
0 |
0 |
2 |
37 |
641200 |
70 |
5 |
0.596 |
1 |
0 |
0 |
2 |
29 |
340821 |
0 |
4 |
6.3 |
3 |
0 |
0 |
2 |
22 |
732628 |
0 |
2 |
6.7 |
2 |
0 |
0 |
利用Scikit-Learn对这个数据进行逻辑回归分析。首先进行特征筛选,特征筛选的方法有很多,主要包含在Scikit_Learn 的feature_ selection 库中,比较简单的有通过F检验(f_ regression)来给出各个特征的F值和p值,从而可以筛选变量(选择F值大的或者p值小的特征)。其次有递归特征消除( Recursive Feature Elimination, RFE)和稳定性选择(StabilitySelection)等比较新的方法。这里使用了稳定性选择方法中的随机逻辑回归进行特征筛选,然后利用筛选后的特征建立逻辑回归模型,输出平均正确率。
3.数据源内容解读
数据集,可以看到数据样本中有很多列属性。
train_df = pd.read_csv("D:/files/train.csv") test_df = pd.read_csv("D:/files/test.csv") |
4.Python主要数据预处理函数
在数据挖掘中,海量的原始数据中存在着大量不完整(有缺失值)、不一致、有异常的数据,严重影响到数据挖掘建模的执行效率,甚至可能导致挖掘结果的偏差,所以进行数据清洗就显得尤为重要,数据清洗完成后接着进行或者同时进行数据集成、转换、规约等一系列的处理,该过程就是数据预处理。数据预处理一方面是要提高数据的质量,另一方面是要让数据更好地适应特定的挖掘技术或工具。
5.二分类
对于二分类模型,其实既可以构建分类器,也可以构建回归。
# predict train predict_train = model.predict(dtrain) train_auc = evaluate_score(predict_train, y_train) # predict validate predict_valid = model.predict(dvalid) valid_auc = evaluate_score(predict_valid, y_valid) print('train auc = {:.7f} , valid auc = {:.7f}\n'.format(train_auc, valid_auc)) |
三、模型训练
数据处理需要花费大量的精力,说明在机器学习中数据准备的工作很重要,有了好的数据才能预测出好的分类结果,对于二分类问题,一般情况下,首选逻辑回归。
#模型训练 model = xgb.train(dict(xgb_params), dtrain, evals=watchlist, verbose_eval=50, early_stopping_rounds=100, num_boost_round=4000) |
#利用最佳迭代次数,再次利用全量数据训练模型 print('---> training on total dataset to predict test and submit') model = xgb.train(dict(xgb_params), dtrain_all, num_boost_round=best_num_boost_rounds) # predict validate predict_valid = model.predict(dvalid) valid_auc = evaluate_score(predict_valid, y_valid) print('预测的验证集 AUC 指标:', valid_auc) |
===> feature count: 103 scale_pos_weight = 1 train: 91826, valid: 10203, test: 30000 [0] train-auc:0.50000 valid-auc:0.50000 Multiple eval metrics have been passed: 'valid-auc' will be used for early stopping. Will train until valid-auc hasn't improved in 100 rounds. [50] train-auc:0.64097 valid-auc:0.65167 [100] train-auc:0.65153 valid-auc:0.67749 [150] train-auc:0.67276 valid-auc:0.72217 [200] train-auc:0.68959 valid-auc:0.73652 [250] train-auc:0.71319 valid-auc:0.73802 [300] train-auc:0.74216 valid-auc:0.73880 Stopping. Best iteration: [241] train-auc:0.70966 valid-auc:0.73982 train auc = 0.7646057 , valid auc = 0.7385212 ---> cv train to choose best_num_boost_round [0] train-auc:0.50000 test-auc:0.50000 [100] train-auc:0.65790 test-auc:0.64860 [200] train-auc:0.69347 test-auc:0.66955 [300] train-auc:0.74312 test-auc:0.68096 [400] train-auc:0.79174 test-auc:0.69092 [500] train-auc:0.81697 test-auc:0.69518 [600] train-auc:0.83385 test-auc:0.69656 |
查看预测结果
""" 定义方法:评价得分模型 """ def evaluate_score(predict, y_true): #通过sklearn的roc_curve函数计算false positive rate和true positive rate以及对应的thresholds #理论上thresholds应该取遍所有的predict(即模型预测值) #thresholds就是predict(即模型预测值)逆序排列后的结果 false_positive_rate, true_positive_rate, thresholds = roc_curve(y_true, predict, pos_label=1) auc_score = auc(false_positive_rate, true_positive_rate)#计算ROC曲线下的面积 return auc_score train_df.head()#返回数据 y_train_all = train_df['target'] del train_df['id'] del train_df['target'] train_df.head() |
#ROC 曲线 fpr, tpr, _ = roc_curve(y_valid, predict_valid) roc_auc = auc(fpr, tpr) plt.figure(figsize=(10,10)) plt.plot(fpr, tpr, color='darkorange', lw=2, label='ROC curve (area = %0.2f)' % roc_auc) plt.plot([0, 1], [0, 1], color='navy', lw=2, linestyle='--') plt.xlim([-0.02, 1.0]) plt.ylim([0.0, 1.05]) plt.xlabel('False Positive Rate') plt.ylabel('True Positive Rate') plt.title('ROC curve') plt.legend(loc="lower right") plt.show() |
四、数据探索分析
1 加载数据(训练集和测试集样本)
train_df = pd.read_csv("D:/files/train.csv")#将csv文件读入并转化为数据框形式 test_df = pd.read_csv("D:/files/test.csv")#将csv文件读入并转化为数据框形式 """ 训练集样本数: (102029, 105) 测试集样本数: (30000, 105) """ print("训练集样本数:", train_df.shape)#读取矩阵长度,如shape[0]是读取矩阵第一维的长度 print("测试集样本数:", test_df.shape)#读取矩阵长度,如shape[0]是读取矩阵第一维的长度 |
2 违约用户数量分布
#违约用户数量分布 plt.figure(figsize=(10,6))#表示figure 的大小为宽、长(单位为inch) #使用normalize=True参数进行计数排序得出占比,赋值给train_df的target tmp = train_df["target"].value_counts(normalize=True)#train.csv的DA列 _, ax = plt.subplots()#返回一个包含figure和axes对象的元组 sns.barplot(x=tmp.index.tolist(), y=tmp.values, ci=None, ax=ax)#按坐标绘制条形图 #将一个可遍历的数据对象组合为一个索引序列,同时列出数据和数据下标 for i, j in enumerate(tmp.sort_index()):#根据列数据/行数据排序 #可视化text()函数 ax.text(i, j, round(j, 5), ha="center", fontsize=12) del tmp gc.collect()#清理内存 plt.show()#按坐标绘制条形图,显示该条形图 |
3 违约用户性别分布
#违约用户性别分布 plt.figure(figsize=(10,6))#表示figure 的大小为宽、长(单位为inch) #使用normalize=True参数进行计数排序得出占比,赋值给train_df的gender tmp = train_df["gender"].value_counts(normalize=True) #返回一个包含figure和axes对象的元组 _, ax = plt.subplots() sns.barplot(x=tmp.index.tolist(), y=tmp.values, ci=None, ax=ax)#按坐标绘制条形图 for i, j in enumerate(tmp.sort_index()):#根据列数据/行数据排序 ax.text(i, j, round(j, 5), ha="center", fontsize=12) #可视化text()函数 del tmp gc.collect()#清理内存 plt.show() |
4 违约用户年龄分布
#违约用户年龄分布 plt.figure(figsize=(20,6)) # 对 年龄 age 维度进行统计不同值出现的个数,数值进行归一化处理 tmp = train_df["age"].value_counts(normalize=True) ax = plt.subplot(111)#单个整数编码的子绘图网格参数,“111”表示“1×1网格,第一子图 sns.barplot(x=tmp.index.tolist(), y=tmp.values, ci=None, ax=ax)#按坐标绘制条形图 for i, j in enumerate(tmp.sort_index()):#根据列数据/行数据排序 ax.text(i, j, round(j, 5), ha="center", fontsize=12)#可视化text()函数 del tmp gc.collect()#清理内存 plt.show()# |
5 违约用户工作单位类型分布
#违约用户工作单位类型分布 plt.figure(figsize=(20,6)) # 对 用户工作单位类型 job 维度进行统计不同值出现的个数,数值进行归一化处理 tmp = train_df["job"].value_counts(normalize=True) ax = plt.subplot(111)#单个整数编码的子绘图网格参数,“111”表示“1×1网格,第一子图 sns.barplot(x=tmp.index.tolist(), y=tmp.values, ci=None, ax=ax)#按坐标绘制条形图 for i, j in enumerate(tmp.sort_index()):#根据列数据/行数据排序 ax.text(i, j, round(j, 5), ha="center", fontsize=12)#可视化text()函数 del tmp gc.collect()#清理内存 plt.show() |
6 不同借贷产品类型的违约比例分布
# 不同借贷产品类型的违约比例分布 将数据集按照借贷产品类型进行分组统计,分别计算不同组违约的比例 plt.figure(figsize=(20,6)) tmp = train_df.groupby("loanProduct")["target"].mean().to_frame("ratio").reset_index() #返回一个包含figure和axes对象的元组 _, ax = plt.subplots() sns.barplot(x="loanProduct", y="ratio", ci=None, data=tmp, ax=ax) # DataFrame,数组或数组列表,可选 for i, j in enumerate(tmp["ratio"]):#根据列数据/行数据排序 ax.text(i, j, round(j, 5), ha="center", fontsize=12) del tmp gc.collect()#清理内存 plt.show() |
7 不同借贷产品类型的违约随时间变化趋势
#不同借贷产品类型的违约随时间变化趋势 tmp_1 = train_df.loc[train_df["loanProduct"] == 1, "target"].rolling(500).mean().dropna().reset_index(drop=True) tmp_2 = train_df.loc[train_df["loanProduct"] == 2, "target"].rolling(500).mean().dropna().reset_index(drop=True) tmp_3 = train_df.loc[train_df["loanProduct"] == 3, "target"].rolling(500).mean().dropna().reset_index(drop=True) plt.figure(figsize=(20,6))#违约用户工作单位类型分布 ax = plt.subplot(131)#建立子图 tmp_1.plot(ax=ax) ax = plt.subplot(132) tmp_2.plot(ax=ax) ax = plt.subplot(133) tmp_3.plot(ax=ax) plt.show() |
8 预授信金额分布
#预授信金额分布 plt.figure(figsize=(15, 5)) ax = plt.subplot(121) sns.kdeplot(train_df[train_df['target'] == 1]['lmt']) ax.set_title('Normal User') ax = plt.subplot(122) sns.kdeplot(train_df[train_df['target'] == 0]['lmt']) ax.set_title('Risk User') plt.show() |
9 基础评级分布
#基础评级分布 plt.figure(figsize=(15, 5)) ax = plt.subplot(121) sns.countplot(train_df[train_df['target'] == 1]['basicLevel']) ax.set_title('Normal User') ax = plt.subplot(122) sns.countplot(train_df[train_df['target'] == 0]['basicLevel']) ax.set_title('Risk User') plt.show() |
10 用户的民族分布情况
#用户的民族分布情况 plt.figure(figsize=(20, 5)) ax = plt.subplot(121) sns.countplot(train_df[train_df['target'] == 1]['ethnic']) ax.set_title('Normal User') ax = plt.subplot(122) sns.countplot(train_df[train_df['target'] == 0]['ethnic']) ax.set_title('Risk User') plt.show() |
11 用户最高学历分布情况
#用户最高学历分布情况 plt.figure(figsize=(20, 5)) ax = plt.subplot(121) sns.countplot(train_df[train_df['target'] == 1]['highestEdu']) ax.set_title('Normal User') ax = plt.subplot(122) sns.countplot(train_df[train_df['target'] == 0]['highestEdu']) ax.set_title('Risk User') plt.show() |
12 用户的联系人关系分布
#用户的联系人关系分布 plt.figure(figsize=(20, 5)) ax = plt.subplot(121) sns.countplot(train_df[train_df['target'] == 1]['linkRela']) ax.set_title('Normal User') ax = plt.subplot(122) sns.countplot(train_df[train_df['target'] == 0]['linkRela']) ax.set_title('Risk User') plt.show() |
13 用户申请信用卡时段分布
#用户申请信用卡时段分布 plt.figure(figsize=(20, 5)) ax = plt.subplot(121) sns.countplot(train_df[train_df['target'] == 1]['setupHour']) ax.set_title('Normal User') ax = plt.subplot(122) sns.countplot(train_df[train_df['target'] == 0]['setupHour']) ax.set_title('Risk User') plt.show() |
14 用户申请信用卡时段分布
#用户申请信用卡时段分布 plt.figure(figsize=(20, 5)) ax = plt.subplot(121) sns.countplot(train_df[train_df['target'] == 1]['weekday']) ax.set_title('Normal User') ax = plt.subplot(122) sns.countplot(train_df[train_df['target'] == 0]['weekday']) ax.set_title('Risk User') plt.show() |
15 用户失效信用卡数分布
#用户失效信用卡数分布 plt.figure(figsize=(20, 5)) ax = plt.subplot(121) sns.countplot(train_df[train_df['target'] == 1]['ncloseCreditCard']) ax.set_title('Normal User') ax = plt.subplot(122) sns.countplot(train_df[train_df['target'] == 0]['ncloseCreditCard']) ax.set_title('Risk User') plt.show() |
16 用户未支付个人贷款金额分布
#用户未支付个人贷款金额分布 plt.figure(figsize=(20, 5)) ax = plt.subplot(121) sns.kdeplot(train_df[train_df['target'] == 1]['unpayIndvLoan']) ax.set_title('Normal User') ax = plt.subplot(122) sns.kdeplot(train_df[train_df['target'] == 0]['unpayIndvLoan']) ax.set_title('Risk User') plt.show() |
17 用户未支付其他贷款金额分布
#用户未支付其他贷款金额分布 plt.figure(figsize=(20, 5)) ax = plt.subplot(121) sns.kdeplot(train_df[train_df['target'] == 1]['unpayNormalLoan']) ax.set_title('Normal User') ax = plt.subplot(122) sns.kdeplot(train_df[train_df['target'] == 0]['unpayNormalLoan']) ax.set_title('Risk User') plt.show() |
18 用户五年内未支付贷款金额
#用户五年内未支付贷款金额 plt.figure(figsize=(20, 5)) ax = plt.subplot(121) sns.kdeplot(train_df[train_df['target'] == 1]['5yearBadloan']) ax.set_title('Normal User') ax = plt.subplot(122) sns.kdeplot(train_df[train_df['target'] == 0]['5yearBadloan']) ax.set_title('Risk User') plt.show() |
基于Python的银行信贷风险可视化与预警建模相关推荐
- 基于python 的电影票房可视化系统
一.介绍 电影票房可视化系统是一个实时分析电影票房的系统,应用Python爬虫.Flask框架.Echarts等技术实现. 二.系统运行图 首页 实时票房排名 票房排行top10 电影类型票房占有率 ...
- 基于python的可视化分析_基于Python 的数据分析与可视化平台研究
基于 Python 的数据分析与可视化平台研究 宋永生 ; 黄蓉美 ; 王军 [期刊名称] <现代信息科技> [年 ( 卷 ), 期] 2019(003)021 [摘要] 数据分析与可视化 ...
- 基于 Python 的招聘信息可视化分析系统
温馨提示:文末有 CSDN 平台官方提供的博主 Wechat / QQ 名片 :) 1. 项目简介 本项目利用 Python 从某招聘网站抓取海量招聘数据,进行数据清洗和格式化后存储到关系型数据库中( ...
- 基于python的电影爬虫可视化系统设计与实现
大数据时代的到来,随着人们线上互动以及网络交易,用户的信息数据完全充斥着网络,个体对产品及服务的偏好可以从这些数据中完全体现出来,为商家以及平台提供了更好的发展方向.但是要人为获取数据库中的大量数据信 ...
- python气象绘图速成_基于Python气象数据处理与可视化分析
基于 Python 气象数据处理与可视化分析 张鑫 ; 曹蕾 ; 韩基良 [期刊名称] <气象灾害防御> [年 ( 卷 ), 期] 2020(027)001 [摘要] 全国综合气象信息共享 ...
- 基于python的电影数据可视化分析与推荐系统
温馨提示:文末有 CSDN 平台官方提供的博主 Wechat / QQ 名片 :) 1. 项目简介 本项目利用网络爬虫技术从国外某电影网站和国内某电影评论网站采集电影数据,并对电影数据进行可视化分析, ...
- 《MATLAB 神经网络43个案例分析》:第5章 基于BP_Adaboost的强分类器设计——公司财务预警建模
<MATLAB 神经网络43个案例分析>:第5章 基于BP_Adaboost的强分类器设计--公司财务预警建模 1. 前言 2. MATLAB 仿真示例一 3. MATLAB 仿真示例二 ...
- python基于web可视化_独家 | 基于Python实现交互式数据可视化的工具(用于Web)
转自:数据派ID:datapi 作者:Alark Joshi 翻译:陈雨琳 校对:吴金笛 本文2200字,建议阅读8分钟. 本文将介绍实现数据可视化的软件包. 这学期(2018学年春季学期)我教授了一 ...
- python交互式数据可视化_基于Python实现交互式数据可视化的工具,你用过几种?...
作者:Alark Joshi 翻译:陈雨琳 来源:数据派THU(ID:DatapiTHU) 我教授了一门关于数据可视化的数据科学硕士课程.我们的数据科学硕士项目是一个为期15个月的强化项目,这个项目已 ...
最新文章
- 2021-08-09 图像灰度二值化
- 基于投影仪的定位技术
- 关于Unity中的UGUI优化,你可能遇到这些问题
- IOCP不可忽视的细节
- VirtualBox 安装 Linux时 报错This kernel requires an X86-64 CPU,but only detected an i686 CPU错误的解决办法
- Angular Web App部署Linux Nginx Https
- 黑盒测试概念简述,黑盒测试优缺点、黑盒用例设计方法简单介绍及黑盒测试方法使用总结
- 搭建小程序表情包教程
- 20155307 2016-2017-2 《Java程序设计》第4周学习总结
- SQL Server 2008入门系列之设置数据库服务器的访问权限
- Head First 设计模式目录
- AWVS12 安装教程(详细附图)
- 首都师范 博弈论 5 5 1大联盟合作博弈中如何量化决策影响力 班扎夫权力指数
- 使用IDEA反编译class文件
- Linux查看日志命令(汇总)
- 解决word标题样式错乱
- ps怎样新建渐变|自定义渐变
- oracle 全文索引 优化,通过案例学调优之--Oracle 全文索引
- 国产OGRE商业游戏
- 5G NR — SA 与 NSA 组网