Prosper,于2006年2月5日上线,是美国第一家P2P借贷平台。借款人通过Prosper寻求个人贷款,期限为3年或5年,贷款利率根据借款人的Prosper评级等确定;投资者(包括个人和机构)可以购买贷款关联的票据进行出借;平台负责借款人的信用审核、贷款资金发放和追讨等,并将借款人还款转给投资者,向借款人一次性收取服务费,向投资者收取管理年费。
本项目通过利用网贷平台Prosper的贷款数据,以违约率为切入口,进行机器学习,构建贷款违约预测模型。
由于平台方在2009年07月对数据的统计口径做出了较大调整,因此我们需要分别对调整前后的数据进行预测。
数据来源
Prosper Loan Data | Kaggle一、提出问题信贷公司,其核心业务同样是金融机构的三性原则:资产的安全性,流动性,盈利性,其中安全性是前提和基础,流动性是条件和手段,盈利性则是根本目的。为了确保业务的正常开展,安全性是业务流程中的重中之重。因此需要分析的主要因素有:违约分析,业务项目分析,政策分析等等。今天的主要分析目标是:违约率。
二、查看数据import pandas as pd#读取数据pros = pd.read_csv('.\ProsperLoanData.csv',skipinitialspace=True)pros.head()
基本特征:
ListingCreationDate:表创建时间(可能是交易开始计息时间)LoanOriginationDate:贷款发起的日期FirstRecordedCreditLine:第一条信用额度建立的日期DateCreditPulled:信贷资料被扣除的日期LoanStatus:贷款的当前状态:已取消、已付、已完成、当前、违约、最终付款、已到期EmploymentStatus:受雇佣状态(Self-employed、Employed等)EmploymentStatusDuration:受雇佣状态持续时间(以月为计算单位)IsBorrowerHomeowner:借款人是否拥有房屋CreditScoreRangeLower/CreditScoreRangeUpper:消费信用最低/最高分In:最近6个月查过多少次征信记录BorrowerRate:借款标利率,作为P2P平台资金借贷价格的代理变量,BorrowerRate不包含其他费用,是筹资者付给投资人的报酬,也是融资最直接和最重要的成本,其体现了资金供求双方在综合考虑各种因素情况下所认可的资金使用成本.Term:期限,筹资者通过网贷平台进行借款时所承诺的最终偿还期限,借款期限体现该资产的流动性,期限较长的资产应存在着流动性溢价(利率上涨).CreditGrade/ProsperRating(Alpha):信用等级,前者反映的是2009年7月1日前客户的信用等级,后者反映的是2009年7月1日后的信用等级.信用等级越高,其偿债能力越强.StatedMonthlyIncome:客户月收入,月收入越高,投资者对该借款本息按时回流越有信心.Delin:信用资料提交时借款人过去7年违约次数,该指标在一定程度上可以体现借款标的发布者的信用状况LoanOriginalAmount:借款人在借款时已经向prosper借入的资金,如果没有历史记录则为0,显然,借入本金越多,其还款压力越大,但是这项指标大的话也可能该客户对prosper依赖性较强.DebtToIncomeRatio:借款人的债务收入比,债务收入比越高筹资者财务状况越差,还款能力较低.其向P2P平台借款时,投资者应要求有更高的回报.Occupation:贷款人职业IncomeRange:贷款人年收入范围BorrowerState:贷款人所在州三、数据清洗,特征提取特征很多,首先应该考虑数据研究的目的,然后留下与目的相关的特征,删除与目标无关的特征。本次研究目标是违约率,也就是LoanStatus这一项,将他作为标签,然后分析各项相关性。
首先删除一些相关性不大,或者需要细分的变量,由于数据中给出了贷前贷后的特征数据,本案重点分析贷前特征对违约的影响:
''''ListingCreationDate','ClosedDate','DateCreditPulled','LoanOrigination','ListingKey','GroupKey','LoanKey','MemberKey','ListingNumber','CurrentlyInGroup'LoanMonthsSinceOrigination', 'LoanFirstDefaultedCycleNumber','LoanCurrentDaysDelinquent','LP_CustomerPayments','LP_CustomerPrincipalPayments','LP_InterestandFees','LP_CollectionFees','LP_ServiceFees','LP_GrossPrincipalLoss','LP_NetPrincipalLoss','LP_NonPrincipalRecoverypayments''''
[img]https://pic4.zhimg.com/v2-cdde9c5d7b64e5f38
数据转换
1 LoanStatus
平台把借款状态分为12种:
Cancelled(取消)、Chargedoff(冲销,投资人有损失)、Completed(正常完成,投资人无损失)、Current(贷款还款中)、Defaulted(坏账,投资人有损失)、FinalPaymentInProgress(最后还款中,投资人无损失)、Past Due(逾期还款,投资人无损失),Cancelled的只有5笔,所以直接去掉。
依据交易是在正常还款期内还是已关闭,将LoanStatus分成两组,再根据投资人有无损失将已关闭的交易分为Completed和Defaulted:Current(贷款还款中)、Defaulted(包含Defaulted、Chargedoff)、Completed(包含Completed、FinalPaymentInProgress、Past Due)三组
def loan_status(x): if x=='Current': y='Current' elif x=='Chargedoff' or x=='Defaulted': y='Defaulted' elif x=='Cancelled': y='Cancelled' else: y='Completed' return y#LoanStatus数据转换#将转换的数据添加到新列Statuspros['Status']=pros['LoanStatus'].apply(loan_status)pros = pros[pros['Status']!='Cancelled']2 BankcardUtilization
按信用资料提交时借款人信用卡总透支额和信用卡总额度之比,分成5组(mild use,medium use,heavy use,super use,no use),对于0或NA的客户,用no use替代
def bank_card_use(s,oneforth=0.31,twoforce=0.6): if s#将缺失率大于80%的变量删除pros.drop(['TotalProsperLoans','TotalProsperPaymentsBilled', 'OnTimeProsperPayments', 'ProsperPaymentsLessThanOneMonthLate', 'ProsperPaymentsOneMonthPlusLate' , 'ProsperPrincipalBorrowed', 'ProsperPrincipalOutstanding' , 'ScorexChangeAtTimeOfListing'], axis=1, inplace=True)从上表中,可知代表信用等级的CreditGrade和ProsperRating (Alpha)变量缺失值较多,是因为平台是以2009年7月为分界点,使用不一样的评级方法而产生。
CreditScore缺失值处理
CreditScore缺失了590条,所占比例约为0.5%左右,所占比例不大,使用中位数填充
pros['CreditScore'].fillna(pros['CreditScore'].median(),inplace=True)BorrowerState缺失值处理
BorrowerState缺失5512条数据,缺失率4.84%,缺失比例较大,所以可以考虑将缺失值单独作为一项因子,暂时设置为“NOTA”
pros['BorrowerState'].fillna('NOTA',inplace=True)DebtToIncomeRatio缺失值处理
DebtToIncomeRatio缺失8554条数据,缺失率7.51%,所占比例非常大。我们发现另外两个重要变量,用户声明的月收入StatedMonthlyIncomeMonthly和LoanPayment每月还贷数额,均无空值,我们可以直接将其比值用以填充。
pros['DebtToIncomeRatio'].fillna(pros['MonthlyLoanPayment'] / (pros['StatedMonthlyIncome'] + 1), inplace = True) #这里的+1用以应对StatedMonthlyIncome为0的情况 Delin缺失值处理
Delin缺失值为987条,在平台借款违约比例较大,所以将Delin缺失值全部置为1
pros['Delin'].fillna(1,inplace=True)In缺失值处理In缺失值为696条,所占比例不大,违约比例跟整体数据相近,故将In的缺失值置为2。
pros['In'].fillna(2,inplace=True)EmploymentStatusDuration缺失值处理
EmploymentStatusDuration缺失值为7621条,所占比例很大,且违约比例很大。猜想,工作越稳定还款能力越强,故将EmploymentStatusDuration的缺失值置为48。
pros['EmploymentStatusDuration'].fillna(48,inplace=True)ProsperRating (Alpha)缺失处理在2009年之后,大约有3万条,筛选出ProsperRating (Alpha)变量的缺失值,大约有144条,所占比例较小,所以采用直接删除的方式进行处理。
ProsperRatingM=pros[(pros['ProsperRating (Alpha)'].isnull())&(pros['Category']=='After 200907')]pros.drop(ProsperRatingM.index,axis=0,inplace=True)
CreditGradeM = pros[(pros['CreditGrade'].isnull())&(pros['Category']=='Before 200907')]pros.drop(CreditGradeM.index,axis=0,inplace=True)探索式分析:借款期限、信用卡透支率、年收入对违约概率的影响从下图可以观察到,借款期限在36个月的违约率比较大;信用卡透支率越高违约风险越大;随着年收入的增加,违约率在逐渐降低
从上图可以观察到,借款期限在36个月的违约率比较大;信用卡透支率越高违约风险越大;随着年收入的增加,违约率在逐渐降低
CreditGrade、ProsperRating (Alpha)以及信用分数对违约概率的影响从下图可见,2009年7月之前CreditGrade评级越高的人违约率越低,大部分借款人的评级都在D级以上;2009年7月之后 ProsperRating (Alpha)信用等级越高的人违约率越低,大部分人都在D以上;平台借款人的分数到多集中在600-800之间,随着信用分数的增加,违约率在逐渐降低。
从上图可见,2009年7月之前CreditGrade评级越高的人违约率越低,大部分借款人的评级都在D级以上;2009年7月之后 ProsperRating (Alpha)信用等级越高的人违约率越低,大部分人都在D以上;平台借款人的分数到多集中在600-800之间,随着信用分数的增加,违约率在逐渐降低。
受雇佣状态持续时间长的借款人违约概率小受雇佣状态持续时间(EmploymentStatusDuration)可够衡量一个人工作生活的稳定情况,受雇佣状态持续时间长的违约的概率小。如下图所示,随着EmploymentStatusDuration的增长,违约概率逐渐减小。
过去七年违约次数多的借款人违约概率大过去七年违约次数(Delin)能够衡量一个人在过去七年中征信情况,违约一次或以上的人在借款时违约概率更大。如下图所示,Delin
债务收入比大的违约概率大从下图可以观察到,随着借款人债务收入比的增大,违约概率越来越大。尤其是债务比达到0.22的时候,违约概率明显偏大。
建模3.1字符串变量转换成数字变量数据中存在分类变量是字符串类型,将其用数字代替
def switch_data(full): #Status full.loc[full['Status']=='Completed','Status']=1 full.loc[full['Status']=='Defaulted','Status']=0 full.loc[full['Status']=='Current','Status']=2 #IsBorrowerHomeowner full.loc[full['IsBorrowerHomeowner']==False,'IsBorrowerHomeowner']=0 full.loc[full['IsBorrowerHomeowner']==True,'IsBorrowerHomeowner']=1 #CreditGrade full.loc[full['CreditGrade']=='NC','CreditGrade']=0 full.loc[full['CreditGrade']=='HR','CreditGrade']=1 full.loc[full['CreditGrade']=='E','CreditGrade']=2 full.loc[full['CreditGrade']=='D','CreditGrade']=3 full.loc[full['CreditGrade']=='C','CreditGrade']=4 full.loc[full['CreditGrade']=='B','CreditGrade']=5 full.loc[full['CreditGrade']=='A','CreditGrade']=6 full.loc[full['CreditGrade']=='AA','CreditGrade']=7 #prosperRating (Alpha) full.loc[full['ProsperRating (Alpha)']=='HR','ProsperRating (Alpha)']=0 full.loc[full['ProsperRating (Alpha)']=='E','ProsperRating (Alpha)']=1 full.loc[full['ProsperRating (Alpha)']=='D','ProsperRating (Alpha)']=2 full.loc[full['ProsperRating (Alpha)']=='C','ProsperRating (Alpha)']=3 full.loc[full['ProsperRating (Alpha)']=='B','ProsperRating (Alpha)']=4 full.loc[full['ProsperRating (Alpha)']=='A','ProsperRating (Alpha)']=5 full.loc[full['ProsperRating (Alpha)']=='AA','ProsperRating (Alpha)']=6 #IncomeRange full.loc[full['IncomeRange']=='Not displayed','IncomeRange']=0 full.loc[full['IncomeRange']=='Not employed','IncomeRange']=1 full.loc[full['IncomeRange']=='$0','IncomeRange']=2 full.loc[full['IncomeRange']=='$1-24,999','IncomeRange']=3 full.loc[full['IncomeRange']=='$25,000-49,999','IncomeRange']=4 full.loc[full['IncomeRange']=='$50,000-74,999','IncomeRange']=5 full.loc[full['IncomeRange']=='$75,000-99,999','IncomeRange']=6 full.loc[full['IncomeRange']=='$100,000+','IncomeRange']=7 #BankCardUse full.loc[full['BankCardUse']=='NoUse','BankCardUse']=0 full.loc[full['BankCardUse']=='MildUse','BankCardUse']=1 full.loc[full['BankCardUse']=='MediumUse','BankCardUse']=2 full.loc[full['BankCardUse']=='HeavyUse','BankCardUse']=3 full.loc[full['BankCardUse']=='SuperUse','BankCardUse']=4 return fullfull = switch_data(full)建模分析(2009.07.01之前)3.2.1建立模型为了评估分类器的性能,将数据集分为训练集和测试机,为了获取各变量对违约情况影响的重要程度,可以考虑用随机森林算法
from sklearn.cross_validation import train_test_splitfrom sklearn.ensemble import RandomForestClassifierfull_rf = full[full['Status'] !=2]Y=full_rf.loc[full_rf['Category']=='Before 200907','Status']X=full_rf.loc[full_rf['Category']=='Before 200907',['CreditGrade','IncomeRange', 'DebtToIncomeRatio','Delin','BorrowerRate', 'IsBorrowerHomeowner','ListingCategory (numeric)', 'EmploymentStatusDuration','In', 'CreditScore','BankCardUse']]X_train,X_test,Y_train,Y_test=train_test_split(X,Y,train_size=0.7)model=RandomForestClassifier(n_estimators=100)#模型训练model.fit(X_train,Y_train)#模型评分model.score(X_test,Y_test)
2009.07.01之后:模型正确率: 0.77
四、总结本文详述了如何通过数据预览,基本数据分析、探索式数据分析,缺失数据填补等方法,实现对Prosper Loan Data | Kaggle这一分类问题如何进行数据分析的具体探索式实践。并分别对2009.07.01前后的模型进行建模分析对比,模型准确率由68.66%上升到77.22%。 |