項(xiàng)目介紹:
p2p 借貸業(yè)務(wù)具有門檻低,渠道成本低的特性,風(fēng)險(xiǎn)防控對(duì)于出借企業(yè)來(lái)說(shuō)非常重要。本項(xiàng)目需要
從大量借貸者的數(shù)據(jù)集中分析出容易違約和不容易違約的人群畫像特征,以給業(yè)務(wù)做貸前決策使
用。同時(shí)使用機(jī)器學(xué)習(xí)算法,實(shí)現(xiàn)自動(dòng)識(shí)別風(fēng)險(xiǎn)人群(精準(zhǔn)率為 89.86%),加快人工審查效率。
項(xiàng)目具體內(nèi)容:
1、使用 python pandas 工具進(jìn)行數(shù)據(jù)清洗、缺失值、異常值處理以及特征指標(biāo)篩選。
2、使用 python matplotlib 可視化工具進(jìn)行探索式數(shù)據(jù)分析,展示用戶關(guān)鍵特征如月收入、信用卡
透支情況對(duì)于違約率的影響情況。
3、使用機(jī)器學(xué)習(xí)隨機(jī)森林進(jìn)行建模分析,使用學(xué)習(xí)曲線、網(wǎng)格搜索、交叉驗(yàn)證,最終得到了一個(gè)評(píng)
分為 84.9%、精準(zhǔn)率為 89.86%、召回率為 80.70%、auc 面積為 0.9337 數(shù)據(jù)預(yù)測(cè)模型。
一、數(shù)據(jù)預(yù)處理(上)
二、數(shù)據(jù)探索
三、數(shù)據(jù)預(yù)處理(下)
三、數(shù)據(jù)建模
? ? 本次數(shù)據(jù)訓(xùn)練使用的模型是隨機(jī)森林分類算法,通過(guò)對(duì)預(yù)處理過(guò)的數(shù)據(jù)集進(jìn)行訓(xùn)練,使用學(xué)習(xí)曲線、網(wǎng)格搜索、交叉驗(yàn)證。最終得到了一個(gè)評(píng)分為84.9%、精準(zhǔn)率為89.86%、召回率為80.70%、auc面積為0.9337數(shù)據(jù)預(yù)測(cè)模型。?
數(shù)據(jù)預(yù)處理的基本流程與思路:
1、首先要明確有多少特征,哪些是連續(xù)的,哪些是類別的。
2、檢查有沒有缺失值,對(duì)確實(shí)的特征選擇恰當(dāng)方式進(jìn)行彌補(bǔ),使數(shù)據(jù)完整。
3、對(duì)連續(xù)的數(shù)值型特征進(jìn)行標(biāo)準(zhǔn)化,使得均值為0,方差為1。
4、對(duì)類別型的特征進(jìn)行one-hot編碼。
5、將需要轉(zhuǎn)換成類別型數(shù)據(jù)的連續(xù)型數(shù)據(jù)進(jìn)行二值化。
6、為防止過(guò)擬合或者其他原因,選擇是否要將數(shù)據(jù)進(jìn)行正則化。
7、在對(duì)數(shù)據(jù)進(jìn)行初探之后發(fā)現(xiàn)效果不佳,可以嘗試使用多項(xiàng)式方法,尋找非線性的關(guān)系。
8、根據(jù)實(shí)際問(wèn)題分析是否需要對(duì)特征進(jìn)行相應(yīng)的函數(shù)轉(zhuǎn)換。
一、數(shù)據(jù)預(yù)處理(上)
導(dǎo)入數(shù)據(jù)集,并查看數(shù)據(jù)基本情況??梢钥吹絧rosper原始數(shù)據(jù)量比較龐大,一個(gè)有113937個(gè)樣本,80個(gè)特征列,1個(gè)標(biāo)簽列。
# 導(dǎo)入prosper借貸數(shù)據(jù)集
data=pd.read_csv("prosperLoanData.csv")
# 查看數(shù)據(jù)信息,有113937個(gè)樣本,80個(gè)特征,一個(gè)標(biāo)簽。數(shù)據(jù)量較大。
# dtypes: bool(3), float64(50), int64(11), object(17)
data.info()
1.1、特征較多,先共刪減一部分無(wú)用的特征。
# 刪除冗余變量
data.drop(["ListingKey","ListingNumber","LoanKey","LoanNumber"], axis=1,inplace=True)
# 刪除無(wú)關(guān)變量
data.drop(["FirstRecordedCreditLine","ListingCreationDate","ClosedDate","DateCreditPulled","LoanOriginationQuarter","MemberKey"], axis=1,inplace=True)
# 刪除貸后變量
data.drop(["LoanCurrentDaysDelinquent","LoanFirstDefaultedCycleNumber","LoanMonthsSinceOrigination","LP_CustomerPayments","LP_CustomerPrincipalPayments","LP_InterestandFees","LP_ServiceFees","LP_CollectionFees","LP_GrossPrincipalLoss","LP_NetPrincipalLoss","LP_NonPrincipalRecoverypayments"],axis=1,inplace=True)
1.2?查看數(shù)據(jù)缺失情況,可以看到有40個(gè)特征是存在數(shù)據(jù)缺失的,缺失率從0.000219-0.882909不等。下面處理缺失數(shù)據(jù)。
# 處理數(shù)值型變量的缺失
missing= pd.concat([data.isnull().any(),data.count()],axis =1)
column= ['是否缺失','數(shù)量']
missing= pd.DataFrame(list(missing.values),index = list(missing.index),columns = column)
total= missing['數(shù)量'].max()
missing['缺失數(shù)量']= total- missing['數(shù)量']
missing['總數(shù)量']= [total]*missing.shape[0]
missing['缺失率']= missing['缺失數(shù)量']/total
miss= missing[missing['是否缺失']== True]
print("\n 數(shù)據(jù)缺失情況:\n",miss.shape)
print(miss)
1.2.1?刪除缺失值比較多的特征
下面兩個(gè)特征缺失率太高,且與我們要分析的相關(guān)性不大,直接刪除掉。
# CreditGrade,信用等級(jí),反映的是2009年7月1日前客戶的信用級(jí),信用等級(jí)越高,其償債能力越強(qiáng)。缺失率0.745
# GroupKey,借款人是其成員的小組的關(guān)鍵。 如果借款人沒有團(tuán)體關(guān)系,價(jià)值將為空。缺失率0.882
data.drop(["CreditGrade","GroupKey"],axis=1,inplace=True)
1.2.2 獲取數(shù)據(jù)類型是分類變量的所有特征,并使用unknown進(jìn)行填充
categorical= data.select_dtypes(include=["object"]).columns.values
print("類型為object的特征:\n",categorical)
data[categorical]= data[categorical].fillna("Unknown")
1.2.3 特殊變量使用計(jì)算公式進(jìn)行填充
# EstimatedEffectiveYield 估計(jì)的有效收益。缺失率為25%
# 有效收益等于借款人利率(i)減去服務(wù)費(fèi)率,(ii)減去收取的未收取利息,(iii)加上估計(jì)收取的滯納金。 適用于2009年7月以后發(fā)放的貸款。
# EstimatedEffectiveYield = BorrowerRate - 利率的其他費(fèi)用損失
# 預(yù)估的費(fèi)用損失
estimated_loss_from_fees= data["BorrowerRate"]- data["EstimatedEffectiveYield"]
data["EstimatedEffectiveYield"].fillna(data["BorrowerRate"]- estimated_loss_from_fees.median(),inplace=True)
# EstimatedReturn 在創(chuàng)建時(shí)分配給上市公司的預(yù)計(jì)收益。估計(jì)收益是估計(jì)的有效收益與估計(jì)損失率之間的差額。適用于2009年7月以后發(fā)放的貸款。缺失率為25%
# EstimatedReturn = EstimatedEffectiveYield - EstimatedLoss
data["EstimatedReturn"].fillna(data["EstimatedReturn"].median(), inplace=True)
data["EstimatedLoss"].fillna(data["EstimatedLoss"].median(), inplace=True)
# DebtToIncomeRatio 負(fù)債收入比。缺失率為7.5%
#DebtToIncomeRatio =?MonthlyLoanPayment/StatedMonthlyIncome
#用未核實(shí)的收入來(lái)計(jì)算 DebtToIncomeRatio , 把0月收入的賬戶記為1
data["DebtToIncomeRatio"].fillna(data["MonthlyLoanPayment"]/ (data["StatedMonthlyIncome"]+ 1),inplace = True)
# 不可估計(jì)的用中位數(shù)填充
# ProsperRating (numeric),創(chuàng)建列表時(shí)分配的Prosper評(píng)級(jí):0 - N / A,1 - HR,2 - E,3 - D,4 - C,5 - B,6 - A,7 - AA。 適用于2009年7月以后發(fā)放的貸款。缺失率25%
data["ProsperRating (numeric)"].fillna(data["ProsperRating (numeric)"].median(),inplace=True)
# ProsperScore,使用歷史Prosper數(shù)據(jù)構(gòu)建的自定義風(fēng)險(xiǎn)評(píng)分。 得分從1-10開始,10分是最好的,或者是最低的風(fēng)險(xiǎn)分?jǐn)?shù)。 適用于2009年7月以后發(fā)放的貸款。缺失率25%
data["ProsperScore"].fillna(data["ProsperScore"].median(),inplace=True)
# 客戶歷史貸款數(shù)據(jù)的缺失值補(bǔ)0
# 用0填補(bǔ)缺失的Prosper歷史數(shù)據(jù)
prosper_vars= ["TotalProsperLoans",# 缺失率80.6%
? ? ? ? ? ? ? ? "TotalProsperPaymentsBilled",# 缺失率80.6%
? ? ? ? ? ? ? ? "OnTimeProsperPayments",# 缺失率80.6%
? ? ? ? ? ? ? ? "ProsperPaymentsLessThanOneMonthLate",# 缺失率80.6%
? ? ? ? ? ? ? ? "ProsperPaymentsOneMonthPlusLate",# 缺失率80.6%
? ? ? ? ? ? ? ? "ProsperPrincipalBorrowed",# 缺失率80.6%
? ? ? ? ? ? ? ? "ProsperPrincipalOutstanding",
"ScorexChangeAtTimeOfListing"]# 缺失率80.6%
data[prosper_vars]= data[prosper_vars].fillna(0)
1.2.4 去掉意義重復(fù)列
# BorrowerAPR,BorrowerRate直接相關(guān),只對(duì)BorrowerAPR進(jìn)行分析;
# ProsperRating (numeric), ProsperRating (Alpha)只是不同表達(dá)形式,只使用ProsperRating (numeric);
# CreditScoreRangeUpper,CreditScoreRangeLower直接相關(guān),使用平均信用分。
data['CreditScoreRange']=((data['CreditScoreRangeUpper']+data['CreditScoreRangeLower'])/2).round(0)
data= data.drop(['BorrowerRate','ProsperRating (Alpha)','CreditScoreRangeLower','CreditScoreRangeUpper'],axis=1)
1.2.5 刪除缺失率比較少的特征的缺失數(shù)據(jù)行
data.dropna(subset=["BorrowerAPR",#0.0002%
? ? ? ? ? ? ? ? ? ? "EmploymentStatusDuration",#0.066%
? ? ? ? ? ? ? ? ? ? "CurrentCreditLines",#0.066%
? ? ? ? ? ? ? ? ? ? "TotalCreditLinespast7years",#0.006%
? ? ? ? ? ? ? ? ? ? "TotalInquiries" #0.010%
? ? ? ? ? ? ? ? ? ? ]
,inplace=True)
處理完缺失數(shù)據(jù)后,樣本量為106290,特征量為55
print("缺失值處理后",data.shape)
1.3 數(shù)據(jù)過(guò)濾
1.3.1 從2009年7月開始,Prosper調(diào)整了對(duì)客戶的評(píng)估方式,此次我們只對(duì)2009-07-01后的貸款進(jìn)行分析。
過(guò)濾完數(shù)據(jù)后,樣本量變?yōu)?2931,特征量為54
data= data[data['LoanOriginationDate']>'2009-7-1']
data.drop(["LoanOriginationDate"],axis=1,inplace=True)
二、數(shù)據(jù)探索
2.1單變量分析
0為未違約人數(shù),1位違約人數(shù),可以看到2009.07以后,違約率為22.90%
print("未違約率為:{};違約率為{}".format(1-data["LoanStatus"].mean(),data["LoanStatus"].mean()))
fig= plt.figure()
ax1= fig.add_subplot(111)
sns.countplot(data["LoanStatus"])
plt.show()

2.1.1不同地區(qū)貸款數(shù)量分布
從圖中可以看到加利福尼亞州貸款數(shù)量遠(yuǎn)比其他州的數(shù)量高。由于prosper總部就位于加利福尼亞州,這與實(shí)際情況一致。其他排名靠前的分別是得克薩斯、紐約、佛羅里達(dá)、伊利諾伊,貸款數(shù)據(jù)均超過(guò)了5000條。根據(jù)2015年美國(guó)各州的GDP排名,這5個(gè)州剛好排名前五,而且順序也是一致的。說(shuō)明Prosper平臺(tái)的用戶主要分布在美國(guó)經(jīng)濟(jì)發(fā)達(dá)的地區(qū)。
State=data.BorrowerState
State_counts=State.value_counts()
print("地區(qū)分布數(shù)據(jù)",State_counts)
plt.figure(figsize=(15,10))
sns.barplot(x=State_counts.values,y=State_counts.index)
plt.title('BorrowerState',fontsize=20)
plt.xlabel('Order Numbers of each State',fontsize=20)
plt.ylabel('State in Abbreviation',fontsize=20)
plt.show()

2.1.2?貸款人收入情況分布
年薪在25000美金以上在美國(guó)屬于技術(shù)性白領(lǐng)或者有一定學(xué)歷的職員,50000美金已經(jīng)是近金領(lǐng)階層,比如:大學(xué)教授,醫(yī)生等。從圖中可以看出Prosper平臺(tái)用戶的收入水平都相對(duì)較高,有利于用戶還款,利于平臺(tái)和投資者的風(fēng)險(xiǎn)控制。
IncomeRange=data.IncomeRange
plt.figure(figsize=(15,10))
sns.countplot(IncomeRange,order=['Not employed','Not displayed','$0','$1-24,999','$25,000-49,999','$50,000-74,999','$75,000-99,999','$100,000+'])

2.1.3貸款人職業(yè)分布
從圖中可以看出,除了不愿意透露具體職業(yè)的人,大部分用戶是教授、程序員、企業(yè)高管等具有一定社會(huì)地位的人,這部分人受過(guò)高等教育,信用有一定保障。另外,這與之前看到的收入情況相符。
Occupation=data.Occupation
Occupation_count=Occupation.value_counts()
plt.figure(figsize=(18,10))
sns.barplot(x=Occupation_count.values,y=Occupation_count.index)

2.1.4貸款人債務(wù)收入比分布
大部分用戶的債務(wù)收入比在0.2左右,超過(guò)0.5的占很少部分。說(shuō)明Prosper平臺(tái)用戶的還款能力還是比較樂觀的
DebtToIncomeRatio_1=data.loc[data.DebtToIncomeRatio<1,'DebtToIncomeRatio']
plt.figure(figsize=(15,10))
sns.distplot(DebtToIncomeRatio_1,kde=False)

2.1.5?貸款者信用卡使用情況
BankcardUtilization代表的是信用卡使用金額和信用卡額度的比值,可以體現(xiàn)用戶的資金需求。Prosper用戶多是0.5~1之間,說(shuō)明用戶每個(gè)月還有信用卡要還,降低了其還款能力。

2.2?相關(guān)的關(guān)鍵因素對(duì)貸款違約率的影響
2.2.1借貸人收入IncomeRange對(duì)違約率的影響
從圖中可以看出:
1.一般來(lái)說(shuō)收入越高違約率越低
2.貸款的人員主要集中在中等收入群體
# 使用groupby來(lái)統(tǒng)計(jì)數(shù)量
print("IncomeRange:\n",data['IncomeRange'].value_counts())
data_IncomeRange=data.groupby(['IncomeRange','LoanStatus'])['LoanStatus'].count().unstack()
# 重命名索引
data_IncomeRange=data_IncomeRange.reindex(['Not displayed','Not employed','$0','$1-24,999','$25,000-49,999','$50,000-74,999','$75,000-99,999','$100,000+'])
# 計(jì)算違約率
data_IncomeRange['DefaultedRate']=data_IncomeRange['Defaulted']/(data_IncomeRange['Defaulted']+data_IncomeRange['Completed'])
print(data_IncomeRange.head())
# 開始繪圖
f,ax1=plt.subplots(figsize=(16,9))
data_IncomeRange[['Completed','Defaulted']].plot(kind='bar',ax=ax1,rot=0,fontsize=14)
ax2=ax1.twinx()
data_IncomeRange['DefaultedRate'].plot(ax=ax2,style='g.-',fontsize=14)
plt.title('DefaultedRate by IncomeRange',fontsize=20)
ax1.set_xlabel('IncomeRange',fontsize=16)
ax1.set_ylabel('Count',fontsize=16)
ax2.legend(loc='center right',fontsize=14)
ax1.legend(fontsize=14)
plt.savefig("explore/IncomeRange-LoanStatus.png")

2.2.2?債務(wù)收入比DebtToIncomeRatio對(duì)違約率的影響
從上圖可以看出:
1.債務(wù)收入比小于0.6時(shí),違約數(shù)明顯小于未違約數(shù),
2.當(dāng)債務(wù)收入比大于0.6時(shí),兩者的差距不是很明顯甚至違約數(shù)大于未違約數(shù),說(shuō)明了債務(wù)收入比越大的人越容易違約
f,ax=plt.subplots(figsize=(16,9))
data.loc[data['LoanStatus']=='Completed','DebtToIncomeRatio'].plot(kind='hist',bins=1000,ax=ax,label='Completed')
data.loc[data['LoanStatus']=='Defaulted','DebtToIncomeRatio'].plot(kind='hist',bins=1000,ax=ax,label='Defaulted')
plt.xlim(0,1)
plt.legend(loc='best',fontsize=14)
ax.set_xlabel('DebtToIncomeRatio',fontsize=16)
ax.set_ylabel('Count',fontsize=16)
ax.set_title('DefaultedRate by DebtToIncomeRatio',fontsize=20)
plt.savefig('explore/DebtToIncomeRatio-LoanStatus.png')

2.2.3 借款人BankcardUtilization對(duì)違約率的影響
1.總的來(lái)說(shuō),隨著信用卡的透支比例越來(lái)越高,違約率也越來(lái)越高
2.SuperUse的違約率到了37.5%,這部分人群需要嚴(yán)格了監(jiān)控,No Use人群也有31%的違約率,當(dāng)初將信用卡透支比例為0和NA的數(shù)據(jù)都?xì)w類為No Use,顯然沒有這么簡(jiǎn)單,應(yīng)該是大部分人群的NA值是為了隱藏自己的高透支比例而填寫的
data_BankcardUse=data.groupby(['BankcardUse','LoanStatus'])['LoanStatus'].count().unstack()# 列轉(zhuǎn)行
#按索引重新排列
data_BankcardUse=data_BankcardUse.reindex(['No Use','Mild Use','Medium Use','Heavy Use','Super Use'])
#計(jì)算對(duì)應(yīng)的違約率
data_BankcardUse['DefaultedRate']=data_BankcardUse['Defaulted']/(data_BankcardUse['Defaulted']+data_BankcardUse['Completed'])
#開始繪圖
f,ax1=plt.subplots(figsize=(16,9))
data_BankcardUse[['Completed','Defaulted']].plot(kind='bar',ax=ax1,rot=0,fontsize=14)
ax1.set_xlabel('BankCardUse',fontsize=16)
ax1.set_ylabel('Count',fontsize=16)
ax2=ax1.twinx()
data_BankcardUse['DefaultedRate'].plot(style='g.-',ax=ax2,fontsize=14)
ax1.legend(fontsize=14)
ax2.legend(loc='center right',fontsize=14)
plt.title('DefaultedRate by BankCardUse',fontsize=20)
plt.savefig('explore/BankCardUse-LoanStatus.png')

2.2.4 消費(fèi)信用分CreditScoreRange對(duì)違約率的影響
從上圖可以看出:
1.隨著信用分?jǐn)?shù)CreditScore的上升,它的違約率在下降
2.大部分貸款者的信用分為650-800,違約率在0.06-0.02
data_CreditScore=data.groupby(['CreditScoreRange','LoanStatus'])['LoanStatus'].count().unstack()
data_CreditScore['DefaultedRate']=data_CreditScore['Defaulted']/(data_CreditScore['Defaulted']+data_CreditScore['Completed'])
#開始繪圖
f,ax1=plt.subplots(figsize=(16,9))
data_CreditScore[['Completed','Defaulted']].plot(kind='line',ax=ax1,rot=0,fontsize=14)
ax1.set_xlabel('CreditScore',fontsize=16)
ax1.set_ylabel('Count',fontsize=16)
ax2=ax1.twinx()
data_CreditScore['DefaultedRate'].plot(style='g.-',ax=ax2,fontsize=14)
ax1.legend(fontsize=14)
ax2.legend(loc='center right',fontsize=14)
plt.title('DefaultedRate by CreditScoreRange',fontsize=20)
plt.savefig('explore/CreditScore-LoanStatus.png')

2.2.5 過(guò)去7年借款人違約次數(shù)DelinquenciesLast7Years對(duì)違約率的影響
過(guò)去七年違約次數(shù)(DelinquenciesLast7Years)能夠衡量一個(gè)人在過(guò)去七年中征信情況,違約一次或以上的人在借款時(shí)違約概率更大。
?從上圖可以看出:
1.總體來(lái)說(shuō)過(guò)去7年違約次數(shù)越多,違約率越高
2.過(guò)去7年未違約的人數(shù)相對(duì)來(lái)說(shuō)比其他違約的人數(shù)高很多,具體看下面的分析
data_DelinquenciesLast7Years=data.groupby(['DelinquenciesLast7Years','LoanStatus'])['LoanStatus'].count().unstack()
data_DelinquenciesLast7Years['DefaultedRate']=data_DelinquenciesLast7Years['Defaulted']/(data_DelinquenciesLast7Years['Defaulted']+data_DelinquenciesLast7Years['Completed'])
f,ax1=plt.subplots(figsize=(16,9))
data_DelinquenciesLast7Years[['Completed','Defaulted']].plot(kind='line',ax=ax1,rot=0,fontsize=14)
ax1.set_xlabel('DelinquenciesLast7Years')
ax1.set_ylabel('Count',fontsize=16)
ax1.set_xticks(range(0,100,2))
ax1.set_xticklabels(range(0,100,2))
ax2=ax1.twinx()
data_DelinquenciesLast7Years['DefaultedRate'].plot(style='g.-',ax=ax2,fontsize=14)
ax1.legend(fontsize=14)
ax2.legend(loc='center right',fontsize=14)
plt.title('DefaultedRate by DelinquenciesLast7Years',fontsize=20)
plt.savefig('explore/DelinquenciesLast7Years-LoanStatu.png')

三、數(shù)據(jù)預(yù)處理(下)
3.1 數(shù)據(jù)轉(zhuǎn)化
3.1.1類變量進(jìn)行啞變量化
樣本量變?yōu)?2931,特征量為127
def harmonize_data(df):
? ? # bool值變成0,1
? ? df["IsBorrowerHomeowner"]=df["IsBorrowerHomeowner"].astype(int)
? ? df["IncomeVerifiable"]= df["IncomeVerifiable"].astype(int)
? ? df["CurrentlyInGroup"]= df["CurrentlyInGroup"].astype(int)
? ? # BorrowerState(貸款人所在州)
????le= LabelEncoder().fit(df['BorrowerState'].astype(str))
????df.loc[:,'BorrowerState']= le.transform(df['BorrowerState'].astype(str))
????# Occupation(貸款人職業(yè))
????occupation= pd.get_dummies(df["Occupation"])
????df= df.join(occupation,rsuffix="_Occupation")
????df.drop("Occupation",axis=1,inplace=True)
????## EmploymentStatus
? ? employment= pd.get_dummies(df["EmploymentStatus"])
????df= df.join(employment,rsuffix="_employmentstatus")
????df.drop("EmploymentStatus",axis=1,inplace=True)
????#IncomeRange(貸款人年收入范圍)
? ? df.loc[df['IncomeRange']== 'Not displayed','IncomeRange']= 0
? ? df.loc[df['IncomeRange']== 'Not employed','IncomeRange']= 1
? ? df.loc[df['IncomeRange']== '$0','IncomeRange']= 2
? ? df.loc[df['IncomeRange']== '$1-24,999','IncomeRange']= 3
? ? df.loc[df['IncomeRange']== '$25,000-49,999','IncomeRange']= 4
? ? df.loc[df['IncomeRange']== '$50,000-74,999','IncomeRange']= 5
? ? df.loc[df['IncomeRange']== '$75,000-99,999','IncomeRange']= 6
? ? df.loc[df['IncomeRange']== '$100,000+','IncomeRange']= 7
? ? return df
data= harmonize_data(data)
3.1.2?標(biāo)簽變量進(jìn)行二分類
已完成貸款的樣本量變?yōu)?6365,特征量為127
# 根據(jù)投資人有無(wú)損失,貸款是否完成將已關(guān)閉的交易分為四組
# Cancelled:貸款取消
# Defaulted:包含Defaulted、Chargedoff
# Current:貸款還款中
# Completed:包含Completed、FinalPaymentInProgress、Past Due
def switch_data1(x):
? ? if x=='Current':
? ? ? ? y='Current'
? ? elif x=='Chargedoff' or x=='Defaulted':
? ? ? ? y='Defaulted'
? ? elif x=='Cancelled':
? ? ? ? y='Cancelled'
? ? else:
? ? ? ? y='Completed'
? ? return y
# 轉(zhuǎn)換數(shù)據(jù)
data['LoanStatus']=data['LoanStatus'].apply(switch_data1)
# 由于Cancelled數(shù)據(jù)只有五條,現(xiàn)將其去除
data=data[data['LoanStatus']!='Cancelled']
#將數(shù)據(jù)集分成已完成(Loandata_finished)和未完成(Loandata_unfinished)兩部分
data_unfinished = data[data['LoanStatus']=='Current']
data = data[data['LoanStatus']!='Current']
data["LoanStatus"] = (data["LoanStatus"] == "Completed").astype(int)
未違約率為:0.7709084012895885;違約率為0.22909159871041151
print("未違約率為:{};違約率為{}".format(data["LoanStatus"].mean(),1-data["LoanStatus"].mean()))
fig = plt.figure()
ax1 = fig.add_subplot(221)
sns.countplot(data["LoanStatus"])
plt.show()

3.2 至此,數(shù)據(jù)預(yù)處理的工作就告一段落,保存預(yù)處理好的數(shù)據(jù)。
data.to_csv("prosperLoanData-clean-finished.csv",index=False)
data_unfinished.to_csv("prosperLoanData-clean-unfinished.csv",index=False)
四、建模建模
?導(dǎo)入經(jīng)過(guò)預(yù)處理的prosper借貸數(shù)據(jù)集
data=pd.read_csv("prosperLoanData-clean-finished.csv")
Y= data['LoanStatus']
X= data.drop(["LoanStatus"],axis=1)?
4.1?手工挑選特征查看一下建模效果
準(zhǔn)確率為0.7695
X = data[['ProsperRating (numeric)','IncomeRange','DebtToIncomeRatio', 'BankcardUtilization','StatedMonthlyIncome', 'IsBorrowerHomeowner','ListingCategory (numeric)', 'EmploymentStatusDuration', 'InquiriesLast6Months', 'CreditScoreRange','BorrowerState', 'CurrentDelinquencies', 'LoanOriginalAmount']]
print (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
#建立模型
rfc = RandomForestClassifier(random_state=42,n_estimators=100)
score = cross_val_score(rfc, X, Y, cv=10).mean()
print("初步看一下準(zhǔn)確率",score)
print (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
4.2?使用模型自己選取特征
準(zhǔn)確率為0.7780
Y= data['LoanStatus']
X= data.drop(["LoanStatus"],axis=1)
4.3?使用學(xué)習(xí)曲線選取最優(yōu)n_estimators
在0-200/20內(nèi)學(xué)習(xí),得到最優(yōu)n_estimators=161,score = 0.8508
在151-171/20內(nèi)學(xué)習(xí),得到最優(yōu)n_estimators=163,score = 0.8511
#print ("n_estimators學(xué)習(xí)曲線開始:",time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
score1= []
# for i in range(1,201,20): # 161附近,0.7777左右
for i in range(151,171,2):
? ? rfc= RandomForestClassifier(n_estimators=i,random_state=42)
? ? scores= cross_val_score(rfc,X,Y,cv=10)
????score1.append(scores.mean())
print ("n_estimators學(xué)習(xí)曲線結(jié)束:",time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
print(score1)
# 0.7782668779703795,171
print("最高的準(zhǔn)確率",max(score1),score1.index(max(score1)))
plt.figure(figsize=[15,10])
plt.plot(range(151,171,2),score1)
# plt.plot(range(1,201,20),score1)
plt.show()

4.4?使用網(wǎng)格搜索調(diào)其他參數(shù)
在0-60/5內(nèi)學(xué)習(xí),得到最優(yōu)max_depth=41
在0-60/5內(nèi)學(xué)習(xí),得到最優(yōu)max_features=16
這里由于比較耗時(shí),沒有進(jìn)一步細(xì)化選擇更高的參數(shù)
print ("網(wǎng)格搜索學(xué)習(xí)曲線開始:",time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
param_grid= {'max_depth':np.arange(1,60,5)}# {'max_depth': 41} 0.7769 ,9分鐘
param_grid= {'max_features':np.arange(1,60,5)}# {'max_features': 16} 0.7778 ,27分鐘
rfc= RandomForestClassifier(n_estimators=84)
GS= GridSearchCV(rfc,param_grid,cv=10)
GS.fit(X,Y)
print ("網(wǎng)格搜索學(xué)習(xí)曲線結(jié)束:",time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
print(GS.best_params_)
print(GS.best_score_)
4.4 最終模型效果
最終準(zhǔn)確率 0.8490528905289052
混淆矩陣:
[[5552? 554]
[1175 4914]]
精準(zhǔn)率: [0.82533076 0.89868325]
召回率: [0.90926957 0.80702907]
roc和auc面積為0.9337

4.5 查看各特征的重要性
FeatureImp= pd.Series(rfc.feature_importances_,index=list(X_train.columns)).sort_values(ascending=False)
#特征重要性作圖
plt.figure(figsize=(18,20))
print("特征重要程度")
print(FeatureImp[:20])
FeatureImp[:20].sort_values(ascending=True).plot(kind='barh')
plt.xlabel('Feature Importance')
plt.title('Feature Importance')
plt.show()


4.6?數(shù)據(jù)預(yù)測(cè)
預(yù)測(cè)的違約率0.0427
X_unfinished= data_unfinished.drop(["LoanStatus"],axis=1)
unfinished_predict= rfc.predict(X_unfinished)
X_unfinished['LoanStatusPredict']= pd.DataFrame(unfinished_predict)
print(unfinished_predict)
defaulted_ratio_predict= 1-X_unfinished['LoanStatusPredict'].mean()
print("預(yù)測(cè)的違約率",defaulted_ratio_predict)
#保存預(yù)測(cè)數(shù)據(jù)
X_unfinished.to_csv('LoanData_unfinished_predict.csv')