基于Python决策树模型的信贷违约预测(完整版)

提示:文章内容来源于金融统计分析课题作业

文章目录

前言

对于银行等贷款金融机构来说,监控借款客户的违约风险是保证贷款安全的重要措施。建立一个信贷违约预测模型一方面可以事先对借款客户进行风险识别,为确认是否放贷、放贷多少、风险补偿多少提供决策依据;另一方面,可以对已借款客户进行违约风险监督,当客户的生活、经济状况发生变化时,能及时警示风险,采取措施保护债权。

一、模型简介

决策树模型是一种基于树结构的监督学习算法,常用于解决分类问题(同样可以用于解决回归问题)。它通过对输入数据集进行分割,最终生成一个树状模型,其中每个节点表示一个特征,每个叶节点表示一个类别或数值。 决策树的构建过程通常从根节点开始,选择一个最优的特征来进行数据集的分割。常用的特征选则依据有信息增益、基尼指数。 对决策树模型不了解的看官可以看看我的精选笔记😳[低调]:机器学习 | 关于决策树分类模型,你学得怎么样了?

 二、建模思路

1、准备一份信贷违约统计数据,并对数据进行特征编码(因为机器学习算法通常需要处理数值型数据,而不能直接处理类别型或文本型数据。)

2、处理数据中的一些无效数据,如:缺失值、错误值(例:年龄144)等

3、初步建立决策树模型,此时决策树模型中的参数尚未调整优化

4、评估初步建立的模型,这一步会用到预测正确率、AUC得分、ROC曲线和KS曲线

5、对决策树模型进行参数调优,如决策树最大深度等

6、使用第5步得出的参数,重新建立最最优参数决策树模型

7、K折交叉验证最优参数模型,并画出建立的决策树模型

三、代码实现

import pandas as pd

data_path = 'credit_risk_dataset.csv'
data = pd.read_csv(data_path)
data.head()

obj_cols_data = data.select_dtypes(exclude = 'number')
for column in obj_cols_data.columns:
    print(column)
    print(obj_cols_data[column].value_counts())
    print('\n')

# 将非数值列转换成数值列
dict1 = {'RENT':0, 'MORTGAGE':1, 'OWN':2, 'OTHER':3}
dict2 = {'EDUCATION':0,'MEDICAL':1,'VENTURE':2,'PERSONAL':3,'DEBTCONSOLIDATION':4,'HOMEIMPROVEMENT':5}
dict3 = {'A':0,'B':1,'C':2,'D':3,'E':4,'F':5,'G':6}
dict4 = {'N':0, 'Y':1}

data.person_home_ownership.replace(dict1, inplace=True)

data.loan_intent.replace(dict2, inplace=True)
data.loan_grade.replace(dict3, inplace = True)
data.cb_person_default_on_file.replace(dict4, inplace = True)
data

data = data.loc[(data.person_age>=20) & (data.person_age<=100)]
# 工作年限不超过年龄
data = data.loc[data.person_age>=data.person_emp_length]
data = data.dropna()
data

import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei']  # 显示中文
plt.rcParams['axes.unicode_minus'] = False  # 显示负号

rows = 3
cols = 4

fig, axes = plt.subplots(rows, cols, figsize=(12, 9))
for i, column in enumerate(data.columns):
    ax = axes[i // cols, i % cols]
    data[column].hist(ax=ax)
    ax.set_title(column)
plt.tight_layout()
plt.show()

X=data.drop(columns='cb_person_default_on_file')
y=data['cb_person_default_on_file']
from sklearn.model_selection import train_test_split
X_train,X_test,y_train,y_test=train_test_split(X,y,test_size=0.2,random_state=1)
from sklearn.tree import DecisionTreeClassifier  # 需要参数优化
model=DecisionTreeClassifier(max_depth=3,random_state=123)  # max_depth设置决策树最大深度(简单理解就是判断次数)
model.fit(X_train,y_train)
y_pre=model.predict(X_test)
score=model.score(X_test,y_test)
print('accuracy score:','{:.2%}'.format(score))

from sklearn.metrics import confusion_matrix
m=confusion_matrix(y_test,y_pre)
m_df=pd.DataFrame(m,index=['0_true','1_true'],columns=['0_predict','1_predict'])
print(m_df)

y_pre_proba=model.predict_proba(X_test)
proba_df=pd.DataFrame(y_pre_proba,columns=['0_不违约概率','1_违约概率'])
print(proba_df)

features=data.drop(columns='cb_person_default_on_file').columns
importance=model.feature_importances_
imp_df=pd.DataFrame()
imp_df['features']=features
imp_df['importance']=importance
imp_df.sort_values(by='importance',ascending=False,inplace=True)
print(imp_df)

from sklearn.metrics import classification_report
print(classification_report(y_test,y_pre))
from sklearn.metrics import roc_curve
fpr,tpr,threshed=roc_curve(y_test,y_pre_proba[:,1])
d=pd.DataFrame()
d['threshed']=list(threshed)
d['false_positive_ratio']=list(fpr)
d['true_positive_ratio']=list(tpr)
d['TPR-FPR_ratio']=d.true_positive_ratio-d.false_positive_ratio
print(d)
from sklearn.metrics import roc_auc_score
auc_score=roc_auc_score(y_test,y_pre_proba[:,1])
print('auc_score:','{:.2%}'.format(auc_score))

plt.figure(figsize=(15,5))
plt.subplot(121)
plt.plot(d.false_positive_ratio,d.true_positive_ratio)
plt.fill_between(d.false_positive_ratio,0,d.true_positive_ratio,alpha=0.8)
plt.text(0.5,0.5,'AUC_score = {:.2%}'.format(auc_score))
plt.title('ROC_Curve')
plt.xlabel('false_positive_ratio')
plt.ylabel('true_positive_ratio')
plt.grid()
ks_v=np.max(d.true_positive_ratio-d.false_positive_ratio)
threshed_=d.loc[d['TPR-FPR_ratio']==ks_v].iat[0,0]
print('KS值:','{:.2%}'.format(ks_v))
# KS值小于0.2,模型区分能力较弱;
# KS值在0.2~0.3之间,模型具有一定区分能力;
# KS值在0.3~0.5之间,模型具有较强区分能力;
# KS值不是越大越好,如果KS值大于0.75,往往代表模型有异常。商业实践中,KS值处于0.2~0.3之间就已经挺不错了
plt.subplot(122)
plt.plot(d.threshed[1:],d.true_positive_ratio[1:],label='true_positive_ratio')
plt.plot(d.threshed[1:],d.false_positive_ratio[1:],label='false_positive_ratio')
plt.plot(d.threshed[1:],d.true_positive_ratio[1:]-d.false_positive_ratio[1:],label='TPR-FPR_ratio')
plt.annotate('threshed = {:.2%}'.format(threshed_)+'\n'+'KS_value = {:.2%}'.format(ks_v),xy=(threshed_,ks_v),
             arrowprops={'facecolor':'green', 'shrink':0.0})
plt.title('KS_curve')
plt.xlabel('threshed')
plt.ylabel('ratio')
plt.legend()
plt.grid()

from sklearn.model_selection import GridSearchCV
parameters={'max_depth':[1,2,3,4,5,6,7,8,9],'criterion':['gini','entropy']}
the_model=DecisionTreeClassifier()
grid_search=GridSearchCV(the_model,parameters,cv=5,scoring='roc_auc')
grid_search.fit(X_train,y_train)
best_max_depth=grid_search.best_params_['max_depth']
best_criterion=grid_search.best_params_['criterion']
print(grid_search.best_score_)
print('best_params: ',grid_search.best_params_)

# max_depth设置决策树最大深度(简单理解就是判断次数)
# 将模型参数设置为最优参数,重新建立模型:
model=DecisionTreeClassifier(max_depth=best_max_depth,criterion=best_criterion,random_state=123)
model.fit(X_train,y_train)
y_pre=model.predict(X_test)
score=model.score(X_test,y_test)
print('accuracy score:','{:.2%}'.format(score))

m=confusion_matrix(y_test,y_pre)
m_df=pd.DataFrame(m,index=['0_true','1_true'],columns=['0_predict','1_predict'])
print(m_df)

y_pre_proba=model.predict_proba(X_test)
proba_df=pd.DataFrame(y_pre_proba,columns=['0_no_default_prob','1_default_prob'])
print(proba_df)

features=data.drop(columns='cb_person_default_on_file').columns
importance=model.feature_importances_
imp_df=pd.DataFrame()
imp_df['features']=features
imp_df['importance']=importance
imp_df.sort_values(by='importance',ascending=False,inplace=True)
print(imp_df)

print(classification_report(y_test,y_pre))
fpr,tpr,threshed=roc_curve(y_test,y_pre_proba[:,1])
d=pd.DataFrame()
d['threshed']=list(threshed)
d['false_positive_ratio']=list(fpr)
d['true_positive_ratio']=list(tpr)
d['TPR-FPR_ratio']=d.true_positive_ratio-d.false_positive_ratio
print(d)
auc_score=roc_auc_score(y_test,y_pre_proba[:,1])
print('auc_score:','{:.2%}'.format(auc_score))

plt.figure(figsize=(15,5))
plt.subplot(121)
plt.plot(d.false_positive_ratio,d.true_positive_ratio)
plt.fill_between(d.false_positive_ratio,0,d.true_positive_ratio,alpha=0.8)
plt.text(0.5,0.5,'AUC_score = {:.2%}'.format(auc_score))
plt.title('ROC_Curve after gridsearch')
plt.xlabel('false_positive_ratio')
plt.ylabel('true_positive_ratio')
plt.grid()
ks_v=np.max(d.true_positive_ratio-d.false_positive_ratio)
threshed_=d.loc[d['TPR-FPR_ratio']==ks_v].iat[0,0]
print('KS值:','{:.2%}'.format(ks_v))
# KS值小于0.2,模型区分能力较弱;
# KS值在0.2~0.3之间,模型具有一定区分能力;
# KS值在0.3~0.5之间,模型具有较强区分能力;
# KS值不是越大越好,如果KS值大于0.75,往往代表模型有异常。商业实践中,KS值处于0.2~0.3之间就已经挺不错了
plt.subplot(122)
plt.plot(d.threshed[1:],d.true_positive_ratio[1:],label='true_positive_ratio')
plt.plot(d.threshed[1:],d.false_positive_ratio[1:],label='false_positive_ratio')
plt.plot(d.threshed[1:],d.true_positive_ratio[1:]-d.false_positive_ratio[1:],label='TPR-FPR_ratio')
plt.annotate('threshed = {:.2%}'.format(threshed_)+'\n'+'KS_value = {:.2%}'.format(ks_v),xy=(threshed_,ks_v),
             arrowprops={'facecolor':'green', 'shrink':0.0})
plt.title('KS_curve after gridsearch')
plt.xlabel('threshed')
plt.ylabel('ratio')
plt.legend()
plt.grid()
plt.suptitle('Decision_Tree_Classifier')
plt.show()

from sklearn.model_selection import cross_val_score
cv = 5
K_acc = cross_val_score(model, X, y, cv = cv)
K_roc_auc = cross_val_score(model, X, y, cv = 5, scoring = 'roc_auc')
print('K_acc:',K_acc)
print('K_acc_mean:',K_acc.mean())
print('K_acc_std:',K_acc.std())
print('K_roc_auc:',K_roc_auc)
print('K_roc_auc_mean:',K_roc_auc.mean())
print('K_roc_auc_std:',K_roc_auc.std())

# 画出决策树
from sklearn import tree  
plt.figure(figsize=(18,12))
tree.plot_tree(model);
plt.show()

四、总结

决策树模型显示,在最大深度为3的参数下得出如下结果,命中率(TPR)=34%。模型整体的预测正确率达到了83%。对于二分类问题,ROC曲线和KS曲线是较为理想的模型评估手段,本文使用这两种图形对模型的结构进行评估。根据ROC曲线的位置,可以判断预测准确率。曲线越接近左上角(X越小,Y越大),预测准确率越高。ROC曲线下的面积(AUC)。AUC值越大,预测准确率越高。模型的ROC曲线陡峭,接近(0,1)左上角,AOC值达到了90.18%,这说明模型的预测准确率较高。

KS曲线以命中率和假警报率作为纵轴,以阈值作为横轴,是一种用于衡量分类模型性能的工具,可以很好地衡量命中率和假警报率之间的关系。如下所示,随着阈值的上升,假警报率随之下降;命中率则在0.4892之前保持不变,当阈值超过当阈值接近0.4892时,命中率开始快速下降。因此在0.4892处有最大的KS值79.09%。如果KS曲线贴近横坐标轴,表示分类器的性能较差;如果曲线贴近纵坐标轴,表示分类器的性能较好。从图中可知,该模型的性能处于较好水平。

查看模型的特征重要度,可以看到loan_grade占很大的权重。原因可能是因为loan_grade已经包含了其他特征变量的信息。

文章就到写到这了,点赞关注后私信小编,可获取完整代码和数据库哦❤

注:(可以自取代码和数据了)如果没有及时回复,可搜索微信公众号:课题怪。然后私信:C20231114 可获取代码、D20231114 可获取数据。

【资源介绍】 基于深度学习的个人贷款违约预测系统设计与实现python源码(注释拉满+详细运行教程).zip 该项目是个人毕设项目,答辩评审分达到95分,代码都经过调试测试,确保可以运行!欢迎下载使用,可用于小白学习、进阶。 该资源主要针对计算机、通信、人工智能、自动化等相关专业的学生、老师或从业者下载使用,亦可作为期末课程设计、课程大作业、毕业设计等。 项目整体具有较高的学习借鉴价值!基础能力强的可以在此基础上修改调整,以实现不同的功能。 欢迎下载交流,互相学习,共同进步! 运行 exercise_20190910.py 该脚本主要进行数据读取、预处理和可视化分析。在命令行中运行以下命令: bash python exercise_20190910.py 运行后,脚本会读取 data 文件夹中的 .csv 文件,进行数据处理,并生成多个可视化图表,展示不同类型卡的持卡人的性别、年龄、账户余额等信息。 3.2 运行 fix_money.py 该脚本定义了一个 fix_money 函数,用于去除字符串中的指定字符,并将结果转换为数值类型。你可以在命令行中运行以下命令进行测试: bash python fix_money.py 运行后,脚本会输出 $4,100 去除 $ 和 , 后的数值结果。 3.3 运行 read_file.py 该脚本定义了 read_file 和 one_hot 函数,用于读取指定目录下的 .csv 文件和进行独热编码。在命令行中运行以下命令: bash python read_file.py 运行后,脚本会读取 data 文件夹中的 .csv 文件,并打印出 accounts 数据集。 更多细节见运行教程文档,不懂就问! 特别强调:请用自己账号在csdn官方下载,否则不提供任何形式技术支持和答疑!
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值