數(shù)據(jù)來自Kaggle的Give Me Some Credit,有15萬條的樣本數(shù)據(jù),網(wǎng)上的分析說明有很多,本人結(jié)合其他大佬的方法,對(duì)數(shù)據(jù)進(jìn)行細(xì)致的分析,主要分析在EDA環(huán)節(jié),之后嘗試使用toad這個(gè)評(píng)分卡的庫,以及使用quct結(jié)合卡方檢驗(yàn)分箱的方法,使用AUC和KS,結(jié)合交叉驗(yàn)證對(duì)比分析哪個(gè)效果更好。
目錄
由于整篇文章的篇幅過長(zhǎng),因此分為上下兩部分。
- 上篇
- 理解數(shù)據(jù)
- 探索性數(shù)據(jù)分析
- 數(shù)據(jù)預(yù)處理
- 特征工程
- 下篇
- 使用toad進(jìn)行woe分箱,并進(jìn)行模型評(píng)估
- 手寫卡方分箱,并進(jìn)行模型評(píng)估
- 評(píng)分卡建立
1.1背景介紹
銀行領(lǐng)域評(píng)分卡一般分為四種,A、B、C、F卡:
A卡表示為貸前評(píng)分卡。
B卡表示為貸中評(píng)分卡。
C卡表示為貸后評(píng)分卡。
F卡表示為反欺詐評(píng)分卡。
1.2基本的項(xiàng)目流程
典型的信用評(píng)分模型主要的開發(fā)流程如下所示:
(1)數(shù)據(jù)獲取,包括獲取存量客戶及潛在客戶的數(shù)據(jù)。存量客戶是指已經(jīng)在證劵公司開展相關(guān)融資業(yè)務(wù)的客戶,包括個(gè)人客戶和機(jī)構(gòu)客戶;潛在客戶是指
(2)數(shù)據(jù)預(yù)處理,主要工作包括數(shù)據(jù)清洗,缺失值處理,異常值處理,主要是為了將獲取的原始數(shù)據(jù)轉(zhuǎn)化為可用作模型開發(fā)的數(shù)據(jù)。
(3)EDA探索性數(shù)據(jù)分析,該步驟主要是獲取樣本總體的大概情況,描述樣本總體情況的指標(biāo)主要有直方圖和箱線圖等等。
(4)變量選擇,主要是通過統(tǒng)計(jì)學(xué)的方法,篩選出對(duì)違約狀態(tài)影響最顯著的指標(biāo)。常見的特征篩選方法,一般分為三種:過濾法、嵌入法、包裝法。過濾法一般采用sklearn當(dāng)中的方差過濾和卡方過濾。嵌入法是一種讓算法自己決定使用哪些特征的方法。包裝法和嵌入法很像,但包裝法需要使用一個(gè)目標(biāo)函數(shù)作為黑盒來幫助選擇特征。一般來說對(duì)于評(píng)分卡模型,還會(huì)使用woe值和IV值篩選特征。
(5)模型開發(fā),該步驟主要包括變量分段、變量的WOE(證據(jù)權(quán)重)變換和邏輯回歸估算三部分。
(6)模型評(píng)估,一般評(píng)分卡中常用的評(píng)估方法,有Accuracy計(jì)算準(zhǔn)確性、畫出ROC曲線、計(jì)算AUC數(shù)值、還有KS值、最后做一個(gè)交叉驗(yàn)證看模型的穩(wěn)定性。
(7)最后一步就是形成評(píng)分卡
2.1數(shù)據(jù)獲取
## 導(dǎo)入庫
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.linear_model import LogisticRegression as LR ##調(diào)用sklearn邏輯回歸
from imblearn.over_sampling import SMOTE ## 處理數(shù)據(jù)不平衡問題
import seaborn as sns
# 畫圖顯示中文
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus'] = False
data = pd.read_csv(r"rankingcard.csv",index_col = 0) ##首先導(dǎo)入訓(xùn)練集數(shù)據(jù)
test = pd.read_csv(r"cs-test.csv",index_col = 0) ##導(dǎo)入測(cè)試集數(shù)據(jù)
2.2探索數(shù)據(jù)
#觀察數(shù)據(jù)類型
data.head()
## 查看訓(xùn)練集數(shù)據(jù)
test.head()
??
# 觀察數(shù)據(jù)維度
print(data.shape)
print(test.shape)
(150000, 11)
(101503, 11)
data.info() ##查看里面的基本情況,字符類型以及缺失值情況
下面可以看到數(shù)據(jù)的大致情況。數(shù)據(jù)屬于個(gè)人消費(fèi)類貸款,只考慮信用評(píng)分最終實(shí)施能夠使用到的數(shù)據(jù)應(yīng)從如下一些方面獲取數(shù)據(jù):
基本屬性:包括借款人當(dāng)時(shí)的年齡。
償債能力:包括了借款人的月收入、負(fù)債比率。
信用往來:兩年內(nèi)35-59天逾期次數(shù)、兩年內(nèi)60-89天逾期次數(shù)、兩年內(nèi)90天或以上的逾期次數(shù)
財(cái)產(chǎn)狀況:包括了開放式信貸和貸款數(shù)量、不動(dòng)產(chǎn)貸款或額度數(shù)量
貸款屬性:暫無
其他因素:包括了借款人的家屬數(shù)量(不包括本人在內(nèi))
時(shí)間窗口:自變量的觀察窗口為過去兩年,因變量表現(xiàn)窗口為未來兩年。
標(biāo)簽如下所示:
SeriousDlqin2yrs:指在過去兩年中至少有一次逾期90天或更長(zhǎng)時(shí)間的信用違約情況。是本數(shù)據(jù)集的目標(biāo)變量。
RevolvingUtilizationOfUnsecuredLines:指信用卡和個(gè)人信貸余額與可用信貸額度之比。
age:指借款人的年齡。
NumberOfTime30-59DaysPastDueNotWorse:指在過去兩年中出現(xiàn)了30-59天的逾期但沒有更嚴(yán)重的逾期情況的次數(shù)。
DebtRatio:指負(fù)債比率,即每月債務(wù)支付、贍養(yǎng)費(fèi)用和生活費(fèi)用除以每月總收入。
MonthlyIncome:指借款人的月收入。
NumberOfOpenCreditLinesAndLoans:指借款人未償還的信用額度。
NumberOfTimes90DaysLate:指在過去兩年中出現(xiàn)了90天或更長(zhǎng)時(shí)間的逾期情況的次數(shù)。
NumberRealEstateLoansOrLines:指不包括家庭住房在內(nèi)的房地產(chǎn)貸款和額外的抵押貸款次數(shù)。
NumberOfTime60-89DaysPastDueNotWorse:指在過去兩年中出現(xiàn)了60-89天的逾期但沒有更嚴(yán)重的逾期情況的次數(shù)。
NumberOfDependents:指借款人在家庭中需要撫養(yǎng)的家屬人數(shù)。
##去除重復(fù)值,注意去除的是重復(fù)的行,因?yàn)閷?duì)于150000行的數(shù)據(jù),
##存在兩組完全一樣的數(shù)據(jù)幾乎不太可能,有可能是錄入錯(cuò)誤
data.drop_duplicates(inplace = True) ##刪除重復(fù)值,并且替換
data.info()
?
##刪除后一定要記得恢復(fù)索引!
data.index = range(data.shape[0])
2.3 EDA 探索性數(shù)據(jù)分析
2.3.1 缺失值分析
##探索一下模型的缺失值
data.isnull().sum() ##用isnull語句+sum語句,返回布爾值相加,得到每列缺失值的數(shù)目
data.isnull().sum()/len(data) ##判斷每一列缺失值所占的比值
2.3.2 數(shù)據(jù)平衡性
## 畫餅圖
figure,ax = plt.subplots(figsize = (12,4))
data.SeriousDlqin2yrs.value_counts().plot.pie(autopct = '%1.1f%%')
正樣本(好客戶)占比93.3%,負(fù)樣本(壞客戶)占比6.7%。
說明客戶一般為好客戶。我們需要捕捉的是壞客戶,但由于比例太過懸殊,此時(shí)樣本不平衡,需要后續(xù)進(jìn)行處理。
2.3.3 異常值分析
通過對(duì)數(shù)據(jù)進(jìn)行分析,發(fā)現(xiàn)有很多和業(yè)務(wù)理解不相同的數(shù)據(jù)。
同時(shí)根據(jù)前面訓(xùn)練集和測(cè)試集的對(duì)比,可以發(fā)現(xiàn)在測(cè)試集當(dāng)中同樣存在這樣的異常值,所以對(duì)這樣的所謂異常值不能簡(jiǎn)單的剔除。
如果是實(shí)際工作當(dāng)中出現(xiàn)這樣的問題,需要和業(yè)務(wù)人員進(jìn)行確認(rèn),如果在比賽中遇到,那就要做好分箱,結(jié)合業(yè)務(wù)和woe進(jìn)行分析。
信用卡和個(gè)人信貸余額與可用信貸額度之比-RevolvingUtilizationOfUnsecuredLines
fig = plt.figure(figsize = (14,4))
ax1 = fig.add_subplot(1,2,1)
sns.distplot(data['RevolvingUtilizationOfUnsecuredLines'],kde = True) ##畫出直方圖
ax1 = fig.add_subplot(1,2,2)
sns.boxplot(y=data['RevolvingUtilizationOfUnsecuredLines']) ## 畫出箱線圖
plt.show()
?我的理解是,正常情況下信用卡和個(gè)人信貸余額與可用信貸額度之比的取值范圍應(yīng)該是[0,1]。
而這些異常數(shù)據(jù)有可能是沒有除以總額度造成的,或者是其他情況,需要借助具體的業(yè)務(wù)進(jìn)行分析。
一般認(rèn)為貸款額度與總額度比例小于1是合理的情況。因此先分析比例小于時(shí),貸款額度與總額度比例和好壞客戶之間的關(guān)系。
這里需要自己定義個(gè)函數(shù)get_compare_plot,可以畫出不同自定義分箱的bardete圖像,如果對(duì)定義函數(shù)有疑問可以大家一起探討。
cut_num = [0,0.3,0.5,0.7,1,10,100,1000,10000,60000]
get_compare_plot(data,feature_plot = 'RevolvingUtilizationOfUnsecuredLines',cut_num=cut_num,is_qcut=False)
這里可以看到,當(dāng)Revol(貸款額度與總額度比例) 小于1時(shí),隨著該比例的增加,客戶違約率也在增加,符合業(yè)務(wù)邏輯。
正常來說,應(yīng)該是隨著比例的增加,客戶違約率也會(huì)增加,但是在大于10后,該規(guī)律發(fā)生了改變,
并且可以通過客戶數(shù)可以發(fā)現(xiàn)數(shù)據(jù)大于10的客戶數(shù)突然要小了很多,因此對(duì)其進(jìn)行進(jìn)一步分析。
如果要提高模型預(yù)測(cè)的準(zhǔn)確性,可以這里對(duì)測(cè)試集中Revol特征的客戶數(shù)進(jìn)行對(duì)比,因?yàn)槠脑蜻@里不作過多的展示。
對(duì)[1,10]之間進(jìn)行分析,找到下滑最好的一個(gè)分割點(diǎn)。
cut_num=[]
for i in np.arange(-1,10,1):
cut_num.append(i)
get_compare_plot(data,feature_plot="RevolvingUtilizationOfUnsecuredLines",cut_num=cut_num,is_qcut=False)
對(duì)1-10分析后,可以看到,從1-2開始違約率是在逐漸下降的,這不符合正常的規(guī)律性,應(yīng)該是Revol越大,違約率越大。
而且發(fā)現(xiàn)在1-2時(shí),樣本個(gè)數(shù)比之后都大很多,之后違約率有了特別大的提升,大概率是因?yàn)闃颖緮?shù)變少,具有隨機(jī)性。
所以對(duì)[1,2]之間的數(shù)據(jù)進(jìn)行細(xì)分。
cut_num=[]
for i in np.arange(0.8,2,0.2):
cut_num.append(i)
get_compare_plot(data,feature_plot="RevolvingUtilizationOfUnsecuredLines",cut_num=cut_num,is_qcut=False)
之間對(duì)0-2之間做過分析,因此從0.8開始。可以發(fā)現(xiàn)數(shù)據(jù)走勢(shì)差不多。
通過和之前的分析對(duì)比來看,Revol在0~2內(nèi),違約率增加。超過2之后,客戶數(shù)量迅速下降和違約率也有降低的趨勢(shì)。因此,可以認(rèn)為Revol=2,
是我們要找的閾值。大于2的為異常值,小于2的為正常值。
print("貸款以及信用卡可用額度與總額度比例大于2的比重為:",100*(data['RevolvingUtilizationOfUnsecuredLines']>2).sum()/len(data),"%")
貸款以及信用卡可用額度與總額度比例大于2的比重為: 0.24834160023026822 %。
最終自己針對(duì)Revol的一個(gè)分箱結(jié)果如下,為之后的toad分箱和手動(dòng)分箱都提供一個(gè)參考。
cut_num=[-1,0,1,2,100000]
get_compare_plot(data,feature_plot="RevolvingUtilizationOfUnsecuredLines",cut_num=cut_num,is_qcut=False)
以上是對(duì)Revol這個(gè)特征的一個(gè)比較全面的分析,通過不斷分組探索數(shù)據(jù)的閾值,找出比較適合的切分點(diǎn)。
這里最后的數(shù)據(jù)處理,仍然存在問題,即可能會(huì)引入數(shù)據(jù)噪聲,因?yàn)椴磺宄傤~度具體值為多少。
以下的特征依舊會(huì)這么處理,分析數(shù)據(jù)的合理性,找出閾值,尋找異常值進(jìn)行記錄,后續(xù)處理的時(shí)候可進(jìn)行刪除等操作。
年齡-age分析
fig = plt.figure(figsize = (14,4))
ax1 = fig.add_subplot(1,2,1)
sns.distplot(data['age'],kde=True)
ax1 = fig.add_subplot(1,2,2)
sns.boxplot(y=data['age'])
plt.show()
?這里年齡的分布比較接近正態(tài)分布,通過對(duì)比訓(xùn)練集和測(cè)試集可以發(fā)現(xiàn)訓(xùn)練集中年齡有等于0的情況,而測(cè)試集里是從21開始。據(jù)我了解,銀行能貸款的最低年齡為18歲,而年齡為0這個(gè)情況幾乎不符合實(shí)際情況,所以后續(xù)處理的時(shí)候進(jìn)行刪除。
cut_num=[-1,20,30,40,50,60,70,80,90,100,110]
get_compare_plot(data,feature_plot="age",cut_num=cut_num,is_qcut=False)
把年齡從-1-110每10歲分一組。發(fā)現(xiàn)隨著年齡的增加,客戶違約率在逐漸降低。
1.(年齡越大,越不容易違約)但在100-110這個(gè)階段,違約率上升,因?yàn)闃颖緮?shù)突然減少,可以看出違約人數(shù)也就1個(gè)人。
2.將年齡大于100的和90一起變成20人一箱。
3.因?yàn)闇y(cè)試集中也沒有0歲的,所以將0歲的異常值刪除(在后續(xù)刪除)。
年齡最終分箱情況
cut_num=[-1,20,30,40,50,60,70,80,110]
get_compare_plot(data,feature_plot="age",cut_num=cut_num,is_qcut=False)
?過去兩年內(nèi)出現(xiàn)35-59天|60-89天|90天以上|逾期但是沒有發(fā)展得更壞的次數(shù)
?這里找出在限定范圍內(nèi)(兩年內(nèi)2*365),每種情況出現(xiàn)的最多次數(shù)。
- 30~59天24次。
- 60~89天最多的違規(guī)次數(shù)為12次。
- 90天以上最多的違規(guī)次數(shù)為8次。
?針對(duì)30-59天進(jìn)行分箱分析
cut_num=[-1,1,3,5,24,100] ##因?yàn)?-24之間的人數(shù)很少,所以直接分成一箱
get_compare_plot(data,feature_plot="NumberOfTime30-59DaysPastDueNotWorse",cut_num=cut_num,is_qcut=False)
?可以看出,大于24次的人數(shù)只有225,針對(duì)這些人數(shù)可以進(jìn)行刪除,對(duì)150000的樣本不會(huì)有太大影響。逾期的次數(shù)越多,客戶違約率就越高,符合正常邏輯。
?針對(duì)60-89天進(jìn)行分箱分析
cut_num=[-1,1,12,100] ##因?yàn)?-12人數(shù)較少,所以分成一箱
get_compare_plot(data,feature_plot="NumberOfTime60-89DaysPastDueNotWorse",cut_num=cut_num,is_qcut=False)
?
?感覺像是同一批人。逾期的次數(shù)越多,客戶違約率就越高,符合正常邏輯。
針對(duì)大于90天數(shù)據(jù)進(jìn)行分析
cut_num=[-1,1,8,100]
get_compare_plot(data,feature_plot="NumberOfTimes90DaysLate",cut_num=cut_num,is_qcut=False)
?
?逾期的次數(shù)越多,客戶違約率就越高,都符合正常邏輯。
負(fù)債率-DebtRatio
fig= plt.figure(figsize=(14,4))
ax1=fig.add_subplot(1,2,1)
sns.distplot(data['DebtRatio'],kde=True)
ax1=fig.add_subplot(1,2,2)
sns.boxplot(y=data['DebtRatio'])
plt.show()
?負(fù)債率主要集中在“0附近”,正常來說,負(fù)債率應(yīng)該是小于1的。但卻有很多的值大于1,甚至上萬,即存在異常值。
cut_num=[-1,0,0.3,0.5,0.7,1,10,100,1000,1000000]
get_compare_plot(data,feature_plot="DebtRatio",cut_num=cut_num,is_qcut=False)
負(fù)債率在0-1之間,隨著負(fù)債率的增加,違約率也在增加。其中1達(dá)到最大0.11
當(dāng)負(fù)債率為0時(shí),有著較高的違約率,這點(diǎn)需要從業(yè)務(wù)上去理解??赡苁且?yàn)槿魺o負(fù)債(每月償還債務(wù),贍養(yǎng)費(fèi),生活費(fèi)用除以月總收入),比較不靠譜。
當(dāng)負(fù)債率達(dá)到10時(shí),隨著負(fù)債率的增加,違約率無顯著的變化規(guī)律。這里對(duì)大于10繼續(xù)進(jìn)行分析。
cut_num=[10,100,1000,100000]
get_compare_plot(data,feature_plot="DebtRatio",cut_num=cut_num,is_qcut=False)
?可以發(fā)現(xiàn),在10以后違約率很低,只有0.05左右。
cut_num=[]
for i in np.arange(0,11,1):
cut_num.append(i)
get_compare_plot(data,feature_plot="DebtRatio",cut_num=cut_num,is_qcut=False)
?針對(duì)0.10中進(jìn)行分箱,可以發(fā)現(xiàn)相比0,1箱其他客戶數(shù)都很小了,而且從2開始違約率和客戶數(shù)都變小。所以閾值暫認(rèn)為是2。
最終針對(duì)負(fù)債率的分析結(jié)果如下:
cut_num=[-1,0,0.3,0.5,0.7,1,2,1000000]
get_compare_plot(data,feature_plot="DebtRatio",cut_num=cut_num,is_qcut=False)
從這里可以看出,最后一箱隨著負(fù)債率的提升,而負(fù)債率卻下降,所以這里我猜測(cè)有可能是因?yàn)槿?shù)的時(shí)候,某些數(shù)據(jù)沒有做除法。
月薪-?MonthlyIncome
a=data['MonthlyIncome'].isnull().sum()/len(data)*100
print('月薪缺失值比例為%.2f%%'%(a))
?月薪缺失值比例為19.56%
對(duì)于缺失大于15%的數(shù)據(jù)連續(xù)性數(shù)據(jù)可以嘗試使用隨機(jī)森林進(jìn)行填充。
cut_num=[0,1000,5000,10000,15000,20000,100000,1000000,10000000]
get_compare_plot(data,feature_plot="MonthlyIncome",cut_num=cut_num,is_qcut=False)
對(duì)于月薪來說,一般會(huì)認(rèn)為月薪越多,其違約率越小。但是因?yàn)樵滦降臄?shù)據(jù)跨度太大,所以之后結(jié)合toad再進(jìn)行仔細(xì)分析。
開放式貸款和信貸數(shù)量-NumberOfOpenCreditLinesAndLoans
fig= plt.figure(figsize=(14,4))
ax1=fig.add_subplot(1,2,1)
sns.distplot(data['NumberOfOpenCreditLinesAndLoans'],kde=True)
ax1=fig.add_subplot(1,2,2)
sns.boxplot(y=data['NumberOfOpenCreditLinesAndLoans'])
plt.show()
通過直方圖可以發(fā)現(xiàn)數(shù)據(jù)基本符合正態(tài)分布,并且數(shù)據(jù)存在一些異常值。
最終的分箱結(jié)果:
cut_num=[-1,0,1,3,5,7,10,20,30,40]
get_compare_plot(data,feature_plot="NumberOfOpenCreditLinesAndLoans",cut_num=cut_num,is_qcut=False)
隨著信貸數(shù)量增加,客戶違約率在不斷降低,最后基本保持在0.06左右。即信貸數(shù)量越多,說明該客戶越值得信賴。
這里可以認(rèn)定大于30的為異常值,因?yàn)?0-40的樣本量突然下降。
但也可以通過箱線圖看出,30-40的值為連續(xù)的,沒有斷點(diǎn)。這里先不按照異常值進(jìn)行處理。
抵押貸款和房地產(chǎn)貸款數(shù)量-NumberRealEstateLoansOrLines
fig= plt.figure(figsize=(14,4))
ax1=fig.add_subplot(1,2,1)
sns.distplot(data['NumberRealEstateLoansOrLines'],kde=True)
ax1=fig.add_subplot(1,2,2)
sns.boxplot(y=data['NumberRealEstateLoansOrLines'])
plt.show()
通過直方圖能看到數(shù)據(jù)是極度右偏的分布,另外箱線圖上也能明顯地看到離群點(diǎn)。
## 將大于20的分成一箱
cut_num=[-1,0,1,3,5,7,10,15,20,50]
get_compare_plot(data,feature_plot="NumberRealEstateLoansOrLines",cut_num=cut_num,is_qcut=False)
?當(dāng)?shù)盅嘿J款和房地產(chǎn)貸款數(shù)量為0時(shí),客戶有一定的違約率,跟之前的負(fù)債率一樣。
當(dāng)?shù)盅嘿J款和房地產(chǎn)貸款數(shù)量大于0之后,隨著數(shù)量的增加,客戶違約率也在不斷增加,說明整體的趨勢(shì)應(yīng)該是隨數(shù)量增加而增大的。
但是大于10之后,隨數(shù)量增加,客戶數(shù)越小,所以決定將大于7的分成一箱,并且單調(diào)性和前面保持一樣。
## 將大于7的分成一箱
cut_num=[-1,0,1,3,5,7,50]
get_compare_plot(data,feature_plot="NumberRealEstateLoansOrLines",cut_num=cut_num,is_qcut=False)
?家屬人數(shù)(配偶,子女等)-NumberOfDependents
a=data['NumberOfDependents'].isnull().sum()/len(data)*100
print('家屬人數(shù)缺失值比例為%.2f%%'%(a))
家屬人數(shù)缺失值比例為2.56%。家屬人數(shù)存在缺失值,這里可看到缺失值的比例為2.62%。數(shù)值不大,可以使用眾數(shù)填充。
fig= plt.figure(figsize=(14,4))
ax1=fig.add_subplot(1,2,1)
sns.distplot(data['NumberOfDependents'],kde=True)
ax1=fig.add_subplot(1,2,2)
sns.boxplot(y=data['NumberOfDependents'])
plt.show()
?最終分箱結(jié)果:
## 將大于5的可分為一箱處理
cut_num=[-1,0,1,3,5,21]
get_compare_plot(data,feature_plot="NumberOfDependents",cut_num=cut_num,is_qcut=False)
隨著家屬人數(shù)增加,客戶違約率增加。因?yàn)榧覍偃藬?shù)增加,家庭開銷增加,需要的開銷也就增加。當(dāng)單身時(shí)(家屬人數(shù)為0)客戶違約率最小為0.058。 大于5的可以分成一箱。
?總結(jié):因?yàn)槭潜荣悢?shù)據(jù),所以結(jié)合業(yè)務(wù)情況在找數(shù)據(jù)中異常值的時(shí)候,沒有做太多的異常值刪除等操作,原因是在測(cè)試集當(dāng)中也出現(xiàn)了同樣的問題,為保證在測(cè)試集中良好的表現(xiàn),所以只針對(duì)測(cè)試集中不存在的數(shù)據(jù),比如年齡為0等這樣的情況進(jìn)行異常值刪除。在實(shí)際業(yè)務(wù)情況下,我認(rèn)為應(yīng)該對(duì)這些問題積極和業(yè)務(wù)人員進(jìn)行溝通。
2.4 數(shù)據(jù)預(yù)處理
這里對(duì)一些之前整理過的異常值處理,填補(bǔ)缺失值和數(shù)據(jù)不平衡處理的方法。
2.4.1 缺失值處理
##使用家屬人數(shù)的均值對(duì)家屬人數(shù)中的缺失值進(jìn)行填補(bǔ),inplace=true表示覆蓋原數(shù)據(jù)
data["NumberOfDependents"].fillna(data["NumberOfDependents"].mean(),inplace = True)
data.info() ##查看NumberOfDependent這一列填補(bǔ)上
def fill_missing_rf(X,y,to_fill):
##使用隨機(jī)森林填補(bǔ)一個(gè)特征的缺失值的函數(shù)
##參數(shù):
##X:要填補(bǔ)的特征矩陣
##y:完整的,沒有缺失值的標(biāo)簽
##to_fill:字符串,要填補(bǔ)的那一列的名稱
#構(gòu)建我們的新特征矩陣和新標(biāo)簽
df = X.copy()
fill = df.loc[:,to_fill]
df = pd.concat([df.loc[:,df.columns!=to_fill],pd.DataFrame(y)],axis = 1)
#找出我們的訓(xùn)練集和測(cè)試集
Ytrain = fill[fill.notnull()]
Ytest = fill[fill.isnull()]
Xtrain = df.iloc[Ytrain.index,:]
Xtest = df.iloc[Ytest.index,:]
#用隨機(jī)森林回歸來填補(bǔ)缺失值
from sklearn.ensemble import RandomForestRegressor as rfr
rfr = rfr(n_estimators=100).fit(Xtrain,Ytrain)
Ypredict = rfr.predict(Xtest)
return Ypredict
##創(chuàng)建函數(shù)所需要的參數(shù),并將參數(shù)導(dǎo)入到函數(shù)之中,產(chǎn)出結(jié)果:
X = data.iloc[:,1:] ##將特征賦予到x中
y = data["SeriousDlqin2yrs"] ##標(biāo)簽賦予到y(tǒng)中,也可以用 y =data.iloc[:,0]
X.shape
y_pred = fill_missing_rf(X,y,"MonthlyIncome") ##將參數(shù)賦予到隨機(jī)森林中
##確認(rèn)我們的結(jié)果合理之后,就可以將數(shù)據(jù)進(jìn)行覆蓋
data.loc[data.loc[:,"MonthlyIncome"].isnull(),"MonthlyIncome"] = y_pred
data.info() ##檢查全部都填滿
?2.4.2 刪除之前分析年齡為0的異常值
##觀察異常值,年齡最小的值居然只有0,這不符合現(xiàn)實(shí)銀行的業(yè)務(wù)需求,即使是兒童賬戶也要至少8歲,我們可以查看一下年齡為0的人有多少
(data["age"]==0).sum()
只有1個(gè)人
##發(fā)現(xiàn)只有一個(gè)人年齡為0,可以判斷這是錄入失誤造成的,可以當(dāng)成是缺失值來處理,直接刪除掉這個(gè)樣本
data = data[data["age"]!=0]
另外,有三個(gè)指標(biāo)看起來很奇怪:"NumberOfTime3059DaysPastDueNotWorse"、"NumberOfTime60-89DaysPastDueNotWorse"、"NumberOfTimes90DaysLate"這三個(gè)指標(biāo)分別是“過去兩年內(nèi)出現(xiàn)35-59天逾期但是沒有發(fā)展的更壞的次數(shù)”,“過去兩年內(nèi)出現(xiàn)60-89天逾期但是沒有發(fā)展的更壞的次數(shù)”,“過去兩年內(nèi)出現(xiàn)90天逾期的次數(shù)”。這三個(gè)指標(biāo),在99%的分布的時(shí)候依然是2,最大值卻是
98,看起來非常奇怪。一個(gè)人在過去兩年內(nèi)逾期35~59天98次,一年6個(gè)60天,兩年內(nèi)逾期98次這是怎么算出來的?我們可以去咨詢業(yè)務(wù)人員,請(qǐng)教他們這個(gè)逾期次數(shù)是如何計(jì)算的。如果這個(gè)指標(biāo)是正常的,那這些兩年內(nèi)逾期了98次的客戶,應(yīng)該都是壞客戶。在我們無法詢問他們情況下,我們查看一下有多少個(gè)樣本存在這種異常:
data.loc[:,"NumberOfTimes90DaysLate"].value_counts()
data.loc[:,"NumberOfTime30-59DaysPastDueNotWorse"].value_counts()
?
data.loc[:,"NumberOfTime60-89DaysPastDueNotWorse"].value_counts()
data = data[data.loc[:,"NumberOfTimes90DaysLate"] < 90]
data.index = range(data.shape[0]) ##恢復(fù)索引
data.info()
2.5 特征衍生
構(gòu)建兩個(gè)新的特征:總違約率和每個(gè)月的支出
## 代表了客戶在過去2年內(nèi)逾期30-59天、60-89天和90天以上的總次數(shù)。
data['AllNumlate']=data['NumberOfTime30-59DaysPastDueNotWorse']+data['NumberOfTime60-89DaysPastDueNotWorse']+data['NumberOfTimes90DaysLate']
## 代表了客戶每月債務(wù)還款額的大小。
data['Monthlypayment']=data['DebtRatio']*data['MonthlyIncome']
2.5.1 解決樣本不平衡問題
#探索標(biāo)簽的分布
X = data.iloc[:,1:]
y = data.iloc[:,0]
y.value_counts()
0 139292 1 9873
import imblearn
from imblearn.over_sampling import SMOTE
##imblearn是專門處理不平衡數(shù)據(jù)集的庫,在處理樣本不平衡問題中性能高過sklearn很多
#imblearn里面也是一個(gè)個(gè)的類,也需要進(jìn)行實(shí)例化,fit擬合,和sklearn用法類似
X.copy().fillna(-1).reset_index(drop=True)
y = y.reset_index(drop=True)
sm = SMOTE(random_state=42) ##實(shí)例化
X,y = sm.fit_sample(X,y) ##返回已經(jīng)上采樣完畢過后的特征矩陣和標(biāo)簽
n_sample_ = X.shape[0]
處理數(shù)據(jù)中正負(fù)樣本比例不均衡,為了盡可能捕捉壞樣本。這里采用SMOTE算法對(duì)數(shù)據(jù)進(jìn)行上采樣。
print(X.shape)
print(Y.shape)
pd.Series(y).value_counts()
1 139292 0 139292 Name: SeriousDlqin2yrs, dtype: int64
本篇總結(jié):
通過對(duì)數(shù)據(jù)進(jìn)行探索性分析,更加了解數(shù)據(jù),從中觀察出數(shù)據(jù)的一些規(guī)律和問題,這樣在后續(xù)的預(yù)處理過程中,也能有些思路。
以上是對(duì)數(shù)據(jù)分析和處理的過程,但其中還有很多的細(xì)節(jié)處理不到位,或者對(duì)業(yè)務(wù)理解上有偏差,如果大家有更好的見解可以多多指正,謝謝!
接下來是對(duì)數(shù)據(jù)進(jìn)行分箱。使用toad這個(gè)專門的評(píng)分卡庫自動(dòng)分箱并構(gòu)建邏輯回歸模型來進(jìn)行預(yù)測(cè),并利用ROC-AUC和KS進(jìn)行評(píng)估。再和使用手動(dòng)分箱的方式進(jìn)行對(duì)比,最后建立評(píng)分卡。文章來源:http://www.zghlxwxcb.cn/news/detail-636076.html
數(shù)據(jù)挖掘項(xiàng)目:金融銀行風(fēng)控信用評(píng)分卡模型(下篇)_Soda kun的博客-CSDN博客文章來源地址http://www.zghlxwxcb.cn/news/detail-636076.html
到了這里,關(guān)于數(shù)據(jù)挖掘項(xiàng)目:金融銀行風(fēng)控信用評(píng)分卡模型(上篇)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!