本项目来源于数据酷客

1 项目背景

信用风险是商业银行长期以来面临的主要风险。个人消费信贷业务成为我国商业银行新的利润增长
点,而个人信用风险管理手段的落后成为制约个人消费信贷产业发展的瓶颈。在传统方法中,大部
分银行主要依靠信贷审批人员经验来决定,个人喜好对评估结果影响很大
,而且随着业务量的大幅
上升,人员相对不足,造成审批时间长,效率低,成本高。
随着移动互联网技术、智能设备的普及、大数据技术的提高正改变这一状况。消费分期信贷业务经
过长期的开展,积累了大量的用户以及数据。但是面临业务规模难以扩大、坏账率较高等问题。通
常的特点包括“授信额度小”、“授信时间要求快”、“人群分散”等,其评估指标多且冗杂,对风险控制
要求较高。需要在风控流程简单、风控成本控制在较低水平的同时,保证风控效果。大数据分析能
够基于大量多种来源的数据,自动构建个人信用风险评估体系,对我国商业银行发展,特别是消费
信贷业务的发展意义重大。

2 数据描述和解析

2.1 mysql连接python获取数据

首先连接数据库,获取需要进行分析的数据

import pymysqlconnection = pymysql.connect(host='59.64.78.76'
, port=3306
, user='raa_user'
, password='bigdata123'
, db='risk_assessment_analysis'
, charset='utf8mb4'//设置中文字符编码格式
, cursorclass=pymysql.cursors.DictCursor//设置游标的类型,返回的数据用字典格式存储)try:with connection.cursor() as cursor:sql = "select * from risk_assessment_analysis.all_data"cursor.execute(sql)all_data = cursor.fetchall()//fetchall返回的是全部数据
finally:connection.close()# 查看数据前两个元素
print(all_data[:2])

并对数据进行一些格式转换

data = pd.DataFrame(all_data) //将已有数据转变为dataframe类型
data_5 = data.head(5) //显示前五行数据
data_des = data.describe(include='all')//查看数据信息

通过对于数据的查看,我们发现这些数据存在一些错误,比如缺失值和异常值的存在,在后续的步骤中将予以处理。

3 可视化分析

3.1 对于违约的可视化分析

在这个项目中,是否违约的比例对于这个模型来说很重要,如果分布不均匀,那么会对模型预测的精度产生很大的影响。所以可以通过画图的方式来对是否违约这个字段进行直观的分析

counts = data['Default'].value_counts(dropna=False).values
//value.counts函数的作用是统计字段中重复值的个数
//dropna 是否去重

3.2文化程度与是否违约之间的关系

data['education'] = data['education'].astype('category')//将education列中的数据改变成种类数据类型
data['education'] = data['education'].cat.set_categories(['小学', '初中', '高中', '本科以上'],ordered=T)//重命名education里面的种类为小学初中高中本科以上counts=data['Default'].groupby(data['education']).value_counts().values
//在柱状图上面显示数据数量,将default按照education进行分组
count1 = counts[[0, 2, 4,6]]
count2 = counts[[1, 3, 5,7]]

 3.3 三要素和违约率之间的关系/婚姻状况特征分布/在网时长分析

fig,[ax1,ax2] = plt.subplots(1,2,figsize=(16,6))
## 设置子图,fig代表整张图,ax1,ax2代表两张子图,subplots返回的数值有两个

sns.countplot(data['maritalStatus'], hue=data['Default'], ax=ax1)

##按照未婚数量和已婚数量进行计数,并且按照是否违规进行分组

maritalStatus_rate = data.groupby('maritalStatus')['Default'].sum() / data.groupby('maritalStatus')['Default'].count()
sns.barplot(x=['未婚','已婚'],y=maritalStatus_rate.values,ax=ax2)

##按照是否结婚对是否违约进行分组,实际上就是计算未婚中和已婚中的违约人数和总人数。

3.4 消费金额/取款金额/网上消费金额的核密度图和总消费金额图

# 在画布ax1中画出总消费金额的核密度图
sns.kdeplot(data["transTotalAmt"],shade=True,ax=ax1)
# 在画布ax2中画出总消费笔数和总消费金额的回归关系图
sns.regplot(data["transTotalCnt"],data["transTotalAmt"],ax=ax2)

 发现消费金额呈现尾长分布,并且消费笔数和金额成正相关关系

与消费金额相同,取款金额和数目也呈现尾长分布分布和正相关性

网上消费金额的分布相对集中,而消费金额和笔数之前呈现负相关

3.5 年龄和开卡时长的分布

# 在画布ax1中绘制年龄的直方图,颜色为红色
sns.distplot(data["age"],color="red",ax=ax1)

# 在画布ax2中绘制开卡时长的直方图,颜色为默认值
sns.distplot(data["card_age"],ax=ax2)

·a-需要进行绘图的特征,通常为Series对象
·color-设置条形的颜色
·kde-是否添加核密度估计曲线,默认为True
·ax-如果提供画布ax,则在此画布上绘图

由图可见,开卡时长和年龄都是偏态分布,年龄主要集中在24,45岁。开卡时长主要分布在0-30个小时。

4 数据预处理

4.1 查看缺失值存在的列

# 计算每列中特征缺失值个数
na_counts = data.isnull().sum()# 将na_counts取大于0的部分进行降序排序(按照降序排列没有多大必要)
missing_value = na_counts[na_counts > 0].sort_values(axis=0,ascending=False)# 查看存在缺失值的特征
print(missing_value)

发现这六列存在缺失值

4.2 缺失值的处理

通过4.1得知,存在缺失值的列都是离散型数据,其中Default缺少数值较少,删除即可,其他缺失值较多的列采用添加字段“未知”的方法进行补全。

data = data[~data['Default'].isnull()]
data[data['sex'].isnull()] = "未知"
data[data['maritalStatus'].isnull()] = "未知"
data[data['threeVerify'].isnull()] = "未知"
data[data['idVerify'].isnull()] = "未知"
data[data['education'].isnull()] = "未知"
##对于缺失值进行处理

4.3 异常值的处理

首先要对异常值进行查看,用函数 value_counts()来查看每列数据的情况,再根据场景来判断数据是否存在异常值。正常情况下,只存在犯罪和不犯罪两种情况。

将存在的异常值按照众数进行填补。

data['isCrime'] =data['isCrime'].replace(2,0)
##将是否犯罪列中值等于2的值换成0

4.4 查看连续行数据的特征

在这个项目中,所有的连续型数据都应该是大于零的,如果存在小于0的数据,那么一定是异常值,需要进行处理

首先要查看那列的连续型数据存在异常值

# 所有连续型特征列名已保存在continuous_columns中
continuous_columns = ['age','cashTotalAmt','cashTotalCnt','monthCardLargeAmt','onlineTransAmt','onlineTransCnt','publicPayAmt','publicPayCnt','transTotalAmt','transTotalCnt','transCnt_non_null_months','transAmt_mean','transAmt_non_null_months','cashCnt_mean','cashCnt_non_null_months','cashAmt_mean','cashAmt_non_null_months','card_age']
# 查看数据各连续型特征的最小值
data_con_min = data[continuous_columns].min()

从结果来看,网上消费金额和公共事业缴费金额这两个字段的最小值均小于0,并且人数较多,根据实际场景分析,可能存在退款或者收款等情况,需要进行进一步的分析,分析小于0情况的个数

online_trans = data[data['onlineTransAmt'] < 0].count()

发现存在16360个小于0的情况,因此对于这个异常值,需要进一步分析。

当小于0的用户存在交易笔数的时候,说明正常,但是如果交易笔数为0,但是存在消费金额,那么说明是异常值,需要将所有零笔订单的消费金额都变成0。

data['onlineTransAmt'] = data[data["onlineTransCnt"] == 0]['onlineTransAmt'] = 0.000000

4.5 通过盒图来确认异常值

使用网上消费金额来当做数据,绘制盒图。

sns.boxplot(data['onlineTransAmt'], orient='v')

发现有的用户消费金额大于两千万,需要进行查看,发现他们的交易笔数也大于一般客户,说明可能是机构用户,予以删除。

data = data[data["onlineTransAmt"]<2.0e+7]

4.6 数字编码

由于数据中存在中文编码,因此需要将这些中文改成数字的形式:

data["maritalStatus"] = data["maritalStatus"].map({"未知":0,"未婚":1,"已婚":2})

##通过map的方式可以达到此目的,另外使用category方法也可以

4.7 one-hot编码

虽然在上文中,将离散数据改成了数字,但是也添加了原本不存在的关系,比如未婚和已婚变为了2,1但是,并不存在未婚是已婚的两倍的关系。因此需要引入one-hot编码来解决这个问题

将婚姻关系转化为三列,第一列代表婚姻状态是否为未知,第二列是否已婚,第三列是否未婚,这样来消除之前出现的倍数关系。

data[['maritalStatus_0', 'maritalStatus_1', 'maritalStatus_2']] = pd.get_dummies(data['maritalStatus'])

##有pandas的get_dummies方法可以实现one-hot编码

5 建立信用指标体系

为了建立信用体系,需要对于数据集中一些属性进行分类和一定的计算,,比如下图中年消费总额,年取现总额都需要通过之前的属性计算活动。

 5.1 年消费总额、取现总额进行计算

# 计算客户年消费总额。
trans_total = data['transCnt_mean'] * data['transAmt_mean']
#print(data[['transCnt_mean', 'transAmt_mean']])
# 将计算结果保留到小数点后六位。
trans_total = round(trans_total, 6)
# 将结果加在data数据集中的最后一列,并将此列命名为trans_total。
data['trans_total'] = trans_totalprint(data['trans_total'].head(20))

在进行计算时,可能会出现,被除数为零,或者除数被除数都为0的情况,在数据中会出现np.inf, -np.inf(无穷大的情况),因此要对于这些数据进行替换。

#inf 正负无穷设为nan
df.replace([np.inf, -np.inf], np.nan)
#空值设为0
df = df.fillna(0)  # 空值设为0

6 构建风控模型流程

6.1 划分数据集

构建风控模型的第一步就是要对数据集进行有效的划分,分为训练集和测试集。同时还要保证两个数据集中违约和未违约的人数比例保持一致。因此可以采用分层采样的方法进行,大致示意图如下:

在Sklearn中的model_selection模块,存在train_test_split()函数,用作训练集和测试集划分,函数语法为:train_test_split(x,y,test_size=None,random_state =None,stratify=y),其中:

·x,y:分别为预测所需的所有特征,以及需要预测的特征(即违约情况Default)。
·test_size:测试集比例,例如test_size=-0.2则表示划分20%的数据作为测试集。
·random_state:随机种子,因为划分过程是随机的,为了进行可重复的训练,需要固定一个random_state,结果重现。
·stratify:使用分层采样,保证从违约客户和未违约客户中抽取了同样比例的训练集和测试集。
·函数最终将返回四个变量,分别为x的测试集和训练集,以及y的测试集和训练集。

x_train, x_test, y_train, y_test = train_test_split(x,y,test_size=0.2,random_state=33,stratify=y)

6.2 使用逻辑回归创建风险控制模型

逻辑回归通过对数据进行计算后,可以将结果映射到0-1之间,用来匹配实际场景中的是否违约。

使用sklearn中的逻辑回归模型进行预测

from sklearn.linear_model import LogisticRegression# 调用模型,新建模型对象
lr =LogisticRegression()# 带入训练集x_train, y_train进行训练
lr.fit(x_train,y_train)# 对训练好的lr模型调用predict方法,带入测试集x_test进行预测
y_predict=lr.predict(x_test)# 查看模型预测结果
print(y_predict[:10])
print(len(y_predict))

6.3 对于模型进行效果评估

对于模型的评价需要引入真正率(TPR)和假正率(FPR)

TPR:预测结果为正,实际结果也为正占所有正例样本的比例

FPR:预测结果为正,但是实际结果为负占所有负例样本的比例


 利用这两个数值,就可以画出一条roc曲线,如图所示

在逻辑回归模型中,通过将数据映射到0-1之间来对于是否违约进行判断,但是需要设定一个阈值来判断具体的位置,比如设置阈值为0.6,那么大于0.6就被判定为正类,否则是负类。即可以确认一组TPR和FPR。当阈值逐渐变小时,更多的实例会被划分为正例,同时被判断为正的实例中实际上存在很多负类,即两种概率都会增大。

6.4模型参数调优

lr = LogisticRegression(penalty="l1",C=0.6,class_weight="balanced")

 6.5 使用标准化/离散化来提升模型效果

对于一些数据,特别是和金额相关的数据,数据之间的差距很大,并且也比较分散,以最近12个月平均取值来看:

平均值和最大值之间有很大差距,标准差也比较大,对于模型的预测会产生影响,因此需要对数据进行标准化处理,数据的标准化指的是将全部数据都按照比例缩放,让他们都落入一个特定的区间。消除数据对于模型的影响。

其中比较常用的操作就是Z-score:

continuous_columns = ['age','cashTotalAmt','cashTotalCnt','monthCardLargeAmt','onlineTransAmt','onlineTransCnt','publicPayAmt','publicPayCnt','transTotalAmt','transTotalCnt','transCnt_non_null_months','transAmt_mean','transAmt_non_null_months','cashCnt_mean','cashCnt_non_null_months','cashAmt_mean','cashAmt_non_null_months','card_age', 'trans_total','total_withdraw', 'avg_per_withdraw','avg_per_online_spend', 'avg_per_public_spend', 'bad_record','transCnt_mean','noTransWeekPre']# 对data中所有连续型的列进行Z-score标准化data[continuous_columns] = (data[continuous_columns]-data[continuous_columns].mean())/data[continuous_columns].std()

另外,对于连续数据,可以使用等频离散化和等距离散化的方式来提升模型的准确率

1 等频离散化:将数据划分为几个区间,每个区间里面的数据量是相等的。

2 等距离散化:将数据放入一个个小的区间,每个区间的间隔是相等的。

利用pandas里面的qcut函数可以实现这一点。

for cc in continuous_columns:data[cc] = pd.qcut(data[cc], q=5, duplicates='drop')

6.6 使用随机森林进行预测

随机森林的工作原理是首先通过随机的方式从数据中抽取样本和特征,训练出多个不同的决策树,形成森林,在对于数据进行分类时,每棵树都有自己的分类结果,森林选择分类最多结果当做最后的结果。

Bagging方法通过从一份数据中抽取多分不同的样本,在不同的样本上训练决策树;通过特征的随机选取,特征阈值的随机等方式来确保每棵树之间的差异性和相关性。

同时,树的数量也影响着预测的精度。通过for循环的方式来,逐渐增加树的数量,并确定最佳树的数量。

# 定义存储AUC分数的数组
scores_train=[]
scores_test=[]
# 定义存储n_estimators取值的数组
estimators=[]# 设置n_estimators在100-210中每隔20取一个数值
for i in range(100,210,20):estimators.append(i)rf = RandomForestClassifier(n_estimators=i, random_state=12)rf.fit(x_train,y_train)y_predict = rf.predict_proba(x_test)[:,1]scores_test.append(roc_auc_score(y_test,y_predict))

6.7 网格搜索

为了避免手动调参的麻烦,可以使用网格搜索的方式自动调参,来确认最佳参数。

rf = RandomForestClassifier()# 设置需要调试的参数
tuned_parameters = {'n_estimators':[180,190],'max_depth':[8,10]}# 调用网格搜索函数
rf_clf = GridSearchCV(rf,tuned_parameters,scoring="roc_auc",n_jobs=2,cv=5)
rf_clf.fit(x_train, y_train)y_predict = rf_clf.predict_proba(x_test)[:,1]
test_auc = roc_auc_score(y_test, y_predict)
print ('随机森林模型test AUC:')
print (test_auc)

7 效果评价方法

7.1 AUC评估

上文中提到了,在ROC曲线中,它与横纵轴之间的面积被称作AUC,可以给出一个模型具体的准确率。

#用metrics.roc_curve()求出 fpr, tpr, threshold
fpr, tpr, threshold = metrics.roc_curve(y_test,y_predict_best)#用metrics.auc求出roc_auc的值
roc_auc = metrics.auc(fpr,tpr)#将图片大小设为8:6
fig,ax = plt.subplots(figsize=(8,6))#将plt.plot里的内容填写完整
plt.plot(fpr, tpr, label = 'AUC = %0.2f'%roc_auc)#将图例显示在右下方
plt.legend(loc = 'lower right') #画出一条红色对角虚线
plt.plot([0, 1], [0, 1],'r--') #设置横纵坐标轴范围
plt.xlim([-0.01, 1.01])
plt.ylim([-0.01, 1.01])#设置横纵名称以及图形名称
plt.ylabel('True Positive Rate')
plt.xlabel('False Positive Rate')
plt.title('Receiver Operating Characteristic Curve')
plt.show()

7.2 KS评估

通过测量模型对于违约和未违约的区分能力来评估模型,公式为:

KS = max|TPR=FPR|

 7.3 PSI评估

PSI用于测试模型的稳定性,越小说明模型越稳定

·使用训练集训练模型后,在训练集上做预测,可以得到训练集上的预测概率,记为p1
·将p1从小到大排列,并等分为10组,如:0-0.1,0.1-0.2,……
·使用模型在测试集上做预测,得到测试集预测概率,记为p2
·将p2从小到大排列,并等分为10组,保持与p1分组一致
·计算实际占比(p2上个各组的样本占比),预期占比(p1上个各组的样本占比)

若模型更稳定,那么p1和p2上各区间样本占比应该是相近的,不会变动很大,也就是预测出来的概率不会差距很大。

7.4 指标重要性
可以通过sklearn中coef_的方法得到模型中个指标的权重。整数代表正相关,负数代表负相关。

# 查看逻辑回归各项指标系数
coefficient = lr_clf.coef_# 取出指标系数,并对其求绝对值
importance = abs(coefficient)# 通过图形的方式直观展现前八名的重要指标
index=data.drop('Default', axis=1).columns
feature_importance = pd.DataFrame(importance.T, index=index).sort_values(by=0, ascending=True)# # 查看指标重要度
print(feature_importance)# 水平条形图绘制
feature_importance.tail(8).plot(kind='barh', title='Feature Importances', figsize=(8, 6), legend=False)
plt.show()

数据分析5-银行客户风险评估实战相关推荐

  1. 《数据分析方法论和业务实战》读书笔记

    <数据分析方法和业务实战>读书笔记 共9章:前两章入门,3-7章介绍基本方法,8章从项目实战介绍数据分析,9章答疑常见问题. 1 数据分析基础 数据分析的完整流程 数据->信息-〉了 ...

  2. 向大家介绍我的新书:《基于股票大数据分析的Python入门实战》

    我在公司里做了一段时间Python数据分析和机器学习的工作后,就尝试着写一本Python数据分析方面的书.正好去年有段时间股票题材比较火,就在清华出版社夏老师指导下构思了这本书.在这段特殊时期内,夏老 ...

  3. 《Spark商业案例与性能调优实战100课》第19课:商业案例之NBA篮球运动员大数据分析核心业务逻辑代码实战

    <Spark商业案例与性能调优实战100课>第19课:商业案例之NBA篮球运动员大数据分析核心业务逻辑代码实战

  4. 基于股票大数据分析的Python入门实战(视频教学版)的插图汇总

    在我写的这本书,<基于股票大数据分析的Python入门实战(视频教学版)>里,用能吸引人的股票案例,带领大家入门Python的语法,数据分析和机器学习. 京东链接是这个:https://i ...

  5. python 数据分析 实际案例_python实战案例:超市营业额数据分析

    实战是学习的最好途径,效率最高,本文不是很长,通过小小的练习,让大家综合运用基础知识,加深印象巩固记忆. 一.读入数据,了解数据 本数据随机生成的假数据,读者可以自己造,也可以通过下方链接下载,或者后 ...

  6. Python数据挖掘与机器学习_通信信用风险评估实战(1)——读数据

    案例及数据说明 本选题用到的数据包括公共数据集.用户通话数据.违约行为数据. 训练集数据:用户通话数据(201703-201706),违约行为数据(201707),公共数据-基本信息(201703-2 ...

  7. 数据分析六、案例实战---Apr 算法之公众号关联分析

    案例实战---Apr 算法之公众号关联分析 一.案例背景 二.明确目标 三.数据处理 3.1关于数据清洗,略... 3.2数据整理 四.数据分析 五.数据展现 5.1 绘制多组柱状图 5.2案例展现 ...

  8. python数据分析与挖掘项目实战记录

    python数据挖掘项目实战记录 取自<Python数据分析与挖掘实战>一书,整理各个项目中用到的数据处理方法: 数据预处理方法 建立模型方法 绘制图形 对于分类问题:用模型分类:混淆矩阵 ...

  9. 数据分析之AB testing实战(附Python代码)

    大家如果对文章中的数据有需求,请关注公众号:[数据分析与统计学之美],回复关键词:[ab测试]! 目录   1.增长黑客    1)前言    2)运用分析指标框架,驱动互联网产品和运营    3)增 ...

  10. 电商如何做数据分析?方法步骤+实战项目打包送,资深分析师整理

    电商如何做数据分析? 直接开门见山,不说废话,都是干货. 首先,纠正大家的一个想法:数据分析并不是要对工具有太多的要求,会基本的Excel数据透视表,图表可视化等基本操作即可,至于高端点的spss,P ...

最新文章

  1. string Format转义大括号
  2. WCF-Discovery的协议基础:WS-Disvovery(客户端驱动探测服务)
  3. c++ shared_ptr的使用
  4. Python编程基础:第四十七节 抽象类Abstract Classes
  5. Python变量和对象类型速记手册
  6. 2020CCPC绵阳
  7. 6个座位办公室最佳位置_2021最佳动力艇大奖:6个类别29个入围名单揭晓
  8. Dataphin的代码自动化能力如何助力商业决策
  9. 不是我的错,也不是Atlas的!
  10. fiddler抓包时,出现的 Tunnel to ***** : 443
  11. Exchange Server 2010高可用性配置
  12. python k线顶分型_顶分型底分型代码
  13. [CF1149C](Tree Generator)
  14. 药一点门诊收费管理系统
  15. 电梯服务器系统,OTS电梯服务器TT使用说明.pdf
  16. 打印机显示链接到计算机,电脑连接打印机突然显示错误怎么办
  17. uniapp适配pc_uniapp+Html5端实现PC端适配
  18. 计算机专业实践报告立题依据,开题报告立题依据 .doc
  19. SAS2x28扩展卡
  20. 10 个免费的高清图库网站,强烈推荐

热门文章

  1. 在linux下打开chm文件
  2. 关于Release版除法反汇编的小结
  3. 如何用excel制作饼图
  4. 电脑主板各部件详细图解
  5. c语言源程序要求每行只能书写一条语句,C语言试题库(含答案)
  6. tas5707php,TAS5707PHP
  7. python一维数组定义,python如何定义数组
  8. 关于md导入时本地图片外链失败的解决方法
  9. GNU 软件文档下载
  10. Only老K说-Java设计模式之原型模式(Prototype)