我是小z
本次分享一個數據挖掘實戰項目:個人信貸違約預測,此項目對于想要學習信貸風控模型的同學非常有幫助,數據源在文末。
項目背景
當今社會,個人信貸業務發展迅速,但同時也會暴露較高的信用風險。信息不對稱在金融貸款領域突出,表現在過去時期借款一方對自身的財務狀況、還款能力及還款意愿有著較為全面的掌握,而金融機構不能全面獲知借款方的風險水平,或在相關信息的掌握上具有明顯的滯后性。這種信息劣勢,使得金融機構在貸款過程中可能由于風險評估與實際情況的偏離,產生資金損失,直接影響金融機構的利潤水平。
而現今時間金融機構可以結合多方數據,提前對客戶風險水平進行評估,并做出授信決策。
解決方法
運用分類算法預測違約
模型選擇
單模型: 決策樹、貝葉斯、SVM等
集成模型: 隨機森林、梯度提升樹等
評分卡模型: 邏輯回歸
項目可輸出: 評分卡
數據描述 數據總體概述
可用的訓練數據包括用戶的基本屬性user_info.txt、銀行流水記錄bank_detail.txt、用戶瀏覽行為browse_history.txt、信用卡賬單記錄bill_detail.txt、放款時間loan_time.txt,以及這些顧客是否發生逾期行為的記錄overdue.txt。(注意:并非每一位用戶都有非常完整的記錄,如有些用戶并沒有信用卡賬單記錄,有些用戶卻沒有銀行流水記錄。)
相應地,還有用于測試的用戶的基本屬性、銀行流水、信用卡賬單記錄、瀏覽行為、放款時間等數據信息,以及待預測用戶的id列表。
脫敏處理:(a) 隱藏了用戶的id信息;(b) 將用戶屬性信息全部數字化;(c) 將時間戳和所有金額的值都做了函數變換。
(1)用戶的基本屬性user_info.txt。共6個字段,其中字段性別為0表示性別未知。
用戶id,性別,職業,教育程度,婚姻狀態,戶口類型 6346,1,2,4,4,2
(2)銀行流水記錄bank_detail.txt。共5個字段,其中,第2個字段,時間戳為0表示時間未知;第3個字段,交易類型有兩個值,1表示支出、0表示收入;第5個字段,工資收入標記為1時,表示工資收入。
用戶id,時間戳,交易類型,交易金額,工資收入標記 6951,5894316387,0,13.756664,0
(3)用戶瀏覽行為browse_history.txt。共4個字段。其中,第2個字段,時間戳為0表示時間未知。
用戶id,時間戳,瀏覽行為數據,瀏覽子行為編號 34724,5926003545,172,1
(4)信用卡賬單記錄bill_detail.txt。共15個字段,其中,第2個字段,時間戳為0表示時間未知。為方便瀏覽,字段以表格的形式給出。
(6)顧客是否發生逾期行為的記錄overdue.txt。共2個字段。樣本標簽為1,表示逾期30天以上;樣本標簽為0,表示逾期10天以內。
注意:逾期10天~30天之內的用戶,并不在此問題考慮的范圍內。用于測試的用戶,只提供id列表,文件名為testUsers.csv。
用戶id,樣本標簽 1,1 2,0 3,1
各個數據表之間的關系
數據預處理
從表中數據得知并非每一位用戶都有非常完整的記錄,如有些用戶并沒有信用卡賬單記錄,有些用戶卻沒有銀行流水記錄。
發現用戶信息表,是否逾期表,放款時間表這三張表的id數目都是55,596,銀行流水表為9,294,瀏覽信息表為47,330,信用卡賬單表為53,174。通過用戶id數得到并非每個用戶都有銀行流水記錄、信用卡賬單等信息,所以這里我們取6個表共同用戶的記錄篩選后組成完整的表。
我們要預測的測試集都是還沒有放款的用戶特征,所以訓練數據這里我們也選取放款時間之前的特征,將存在時間戳的表與放款時間表進行交叉,只篩選此時間范圍內的用戶id。
篩選出這6張表共有的用戶id,得出5735個用戶的記錄是完整的。
user.T
銀行賬單表
bank_detail_select?=?pd.merge(left=df_bank_detail_train,?
??????????????????????????????right=user,?
??????????????????????????????how='inner',?
??????????????????????????????on='用戶id')
統計用戶進賬單數,求和
統計用戶支出單數,求和
統計用戶工資收入計數,求和
銀行賬單表
bank_train.head()
瀏覽表
先剔除5735以外的數據,再統計每個用戶的瀏覽記錄(count)
browse_train.head()
賬單表
去掉了時間、銀行id、還款狀態這幾個變量,按用戶id分組后對每個字段均值化處理。
逾期表、用戶表
合并五張表
將篩選后的五個表進行合并,得出25個字段
df_train=user_train.merge(bank_train)
df_train=df_train.merge(bill_train)
df_train=df_train.merge(browse_train)
df_train=df_train.merge(overdue_train)
df_train.head()
查看完整表格的基本情況,無缺失值,均是數值類型。
df_train.info()
特征工程 基于業務理解的篩選 銀行流水記錄特征相關性分析
#?相關性結果數據表
corrmat=bank_train[internal_chars].corr()??
#熱力圖
sns.heatmap(corrmat,?square=True,?
????????????linewidths=.5,?annot=True);?
總表相關性分析
#?相關性結果數據表
corrmat=df_train[internal_chars].corr()
#?熱力圖
sns.heatmap(corrmat,?square=False,?
????????????linewidths=.5,?annot=True);??
本期的賬單余額與最低還款額具有高度共線性,決定只選用最低還款額。
生產衍射變量
上期還款差額 =上期賬單金額 - 上期還款金額, 上期還款差額還會直接影響用戶的信用額度以及本期的賬單金額。
調整金額和循環利息是跟“上期的還款差額”有關的:
可以將還款差額進行“特征二值化”來代替這兩個特征。
預借現金額度,是指持卡人使用信用卡通過ATM等自助終端提取現金的最高額度,取現額度包含于信用額度之內,一般是信用額度的50%左右,所以可以不用這個特征,選擇信用額度即可。
df_train['平均支出']=df_train.apply(lambda?x:x.支出金額/x.支出單數,?axis=1)??
df_train['平均工資收入']=df_train.apply(lambda?x:x.工資收入/x.工資筆數,?axis=1)
df_train['上期還款差額']=df_train.apply(lambda?x:x.上期賬單金額-x.上期還款金額,?axis=1)
df_select=df_train.loc[:,['用戶id',?'性別',?'教育程度',?'婚姻狀態',?'平均支出',
??????????????????????????'平均工資收入',?'上期還款差額',?'信用卡額度',?'本期賬單余額',?'本期賬單最低還款額',?
??????????????????????????'消費筆數',??'瀏覽行為數據',?'樣本標簽']].fillna(0)
df_select.head()
基于機器學習的篩選
將上期還款差額二值化
from?sklearn.preprocessing?import?Binarizer
X=df_select['上期還款差額'].values.reshape(-1,1)
transformer?=?Binarizer(threshold=0).fit_transform(X)
df_select['上期還款差額標簽']=transformer
方差過濾法
過濾那些不帶有信息的變量,默認參數為0,即過濾方差為0的那些變量,只保留對模型有貢獻的那些信息。
from?sklearn.feature_selection?import?VarianceThreshold
VTS?=?VarianceThreshold()???#?實例化,參數默認方差為0
x_01=VTS.fit_transform(x)
相關性過濾--互信息法
互信息法是用來捕捉每個特征與標簽之間的任意關系(包括線性和非線性關系)的過濾方法。
和F檢驗相似,它既可以做回歸也可以做分類,并且包含兩個類mutual_info_classif(互信息分類)和mutual_info_regression(互信息回歸)。
這兩個類的用法和參數都和F檢驗一模一樣,不過互信息法比F檢驗更加強大,F檢驗只能夠找出線性關系,而互信息法可以找出任意關系。
from?sklearn.feature_selection?import?mutual_info_classif?as?MIC
result?=?MIC(x,y)
樣本不均衡
通過觀察,正負樣本比例為 836:4899,屬于樣本不均衡范疇,可采用上采樣的SMOTE算法對其進行樣本不均衡處理。
from?imblearn.over_sampling?import?SMOTE
over_samples?=?SMOTE(random_state=111)
over_samples_x,?over_samples_y?=?over_samples.fit_sample(x,y)
模型建立與調參
文章一開始已經提到過了,可選模型較多,這里舉例三種模型邏輯回歸、決策樹、隨機森林模型,其余模型的選用,小伙伴們可以自己動手練習練習。
二分類模型——邏輯回歸模型 互信息與正則化對模型效果的影響
用學習曲線對參數C進行調整,分別在兩個模型中進行調參。
超參數C : 一般不會超過1, 越大懲罰力度越小,本次選取從 0.05 - 2范圍。
from?sklearn.linear_model?import?LogisticRegression?as?LR
from?sklearn.model_selection?import?cross_val_score?as?cvs
lrl1?=?LR(penalty='l1',?solver='liblinear',?
??????????C=i,?max_iter=1000,?random_state=0)
lrl2?=?LR(penalty='l2',?solver='liblinear',?
??????????C=i,?max_iter=1000,?random_state=0)
由圖可知,在經過互信息過濾后,邏輯回歸模型得分明顯提高,且當超參數C=0.6時,模型效果是最好的。
包裝法篩選變量
以邏輯回歸為基分類器,結合包裝法篩選變量,并運用交叉驗證繪制學習曲線,探索最佳變量個數。
同時,運用SMOTE算法進行樣本均衡處理,并比較均衡前后模型效果的變化。
from?sklearn.feature_selection?import?RFE
LR_1?=?LogisticRegression(penalty='l1',?solver='liblinear',?
??????????????????????????C=0.6,?max_iter=1000,?random_state=0)
selector1?=?RFE(LR_1,?n_features_to_select=i,?step=1)
X_wrapper1?=?selector1.fit_transform(x,?y)
once1=cvs(LR_1,?X_wrapper1,?y,?cv=5,?scoring='f1').mean()
由圖可見,樣本均衡前后模型效果有大幅度增長。且兩種正則化方法相差無幾。
樹模型——決策樹
因為樣本均衡化處理前后,對模型效果提升較為明顯,因此在使用決策樹模型建立之前,對樣本進行均衡化處理。
因為深度參數max_depth是對決策樹模型影響最大的參數之一,因此本案例正對決策樹深度繪制學習曲線,探索決策樹最佳參數。
plt.plot(L_CVS,?'r')??#?交叉驗證
plt.plot(L_train,?'g')#?訓練集
plt.plot(L_test,?'b')?#?測試集
由學習曲線可知,在max_depth=5時訓練集和測試集模型效果均達到了最佳狀態,當在max_depth大于5后,模型在訓練集上的分數依然在上升,而測試集上的表現有所下降,這就是模型過擬合現象,因此最終我們選用max_depth=5。
特征重要性
features_imp?=?pd.Series(dtc.feature_importances_,?
??????????index?=?x.columns).sort_values(ascending=False)
features_imp
上期還款差額標簽 0.705916
性別 0.101779
平均支出 0.064218
平均工資收入 0.047644
瀏覽行為數據 0.044333
教育程度 0.015257
婚姻狀態 0.012665
本期賬單最低還款額 0.004455
消費筆數 0.003734
本期賬單余額 0.000000
信用卡額度 0.000000
dtype: float64
決策樹可視化
這里提出一點,如果需要深入理解決策樹決策過程,可以借助決策樹可視化來輔助理解。
import?graphviz
from?sklearn?import?tree
#首先配置
dot_data?=?tree.export_graphviz(dtc?
??????#?要對已經建成的dct這個實例化好的模型進行畫圖
??????,feature_names=?x.columns?
??????#?更改列名為中文
??????#?,class_names=[]?
??????#?更改標簽名字
??????,filled=True?
??????#?給每一個節點分配顏色,顏色約深表示葉子的純度越高
??????,rounded=True
??????#?節點性狀為圓角
??????)
graph?=?graphviz.Source(dot_data)
graph
樹模型——隨機森林
from?sklearn.ensemble?import?RandomForestClassifier?as?RFC
from?sklearn.model_selection?import?GridSearchCV
rfc?=?RFC(n_estimators=i+1,
??????????n_jobs=-1,
??????????random_state=90)
score?=?cvs(rfc,over_samples_x_train,?
????????????over_samples_y_train,
????????????cv=5,?scoring='f1').mean()
模型調參
有?些參數是沒有參照的,一開始很難確定?個范圍,這種情況下采用先通過學習曲線確定參數大致范圍,再通過網格搜索確定最佳參數。
比如確定n_estimators范圍時,通過學習曲線觀察n_estimators在什么取值開始變得平穩,是否?直推動模型整體準確率的上升等信息。
對于其他參數也是按照同樣的思路,如影響單棵決策樹模型的參數max_depth來說,?般根據數據的??來進??個試探,比如乳腺癌數據很?,所以可以采?1~10,或者1~20這樣的試探。
但對于像digit recognition那樣的?型數據來說,我們應該嘗試30~50層深度(或許還不?夠),此時更應該畫出學習曲線,來觀察深度對模型的影響。
確定范圍后,就可以通過網格搜索的方式確定最佳參數。其他參數就不一一舉例了,大家可以動手嘗試一下。
#?調整max_depth
param_grid?=?{'max_depth':np.arange(1,?20,?1)}
rfc?=?RFC(n_estimators=150,random_state=90,?n_jobs=-1)
GS?=?GridSearchCV(rfc,param_grid,cv=5,?scoring='f1')
GS.fit(over_samples_x,?over_samples_y)
GS.best_params_
GS.best_score_
模型評價
本次案例模型評估使用classification_report
sklearn中的classification_report函數用于顯示主要分類指標的文本報告.在報告中顯示每個類的精確度,召回率,F1值等信息。
主要參數:
y_true:1維數組,或標簽指示器數組/稀疏矩陣,目標值。
y_pred:1維數組,或標簽指示器數組/稀疏矩陣,分類器返回的估計值。
labels:array,shape = [n_labels],報表中包含的標簽索引的可選列表。
target_names:字符串列表,與標簽匹配的可選顯示名稱(相同順序)。
sample_weight:類似于shape = [n_samples]的數組,可選項,樣本權重。
digits:int,輸出浮點值的位數。
決策樹驗證集評價結果
最后這里舉了一個決策樹模型效果評價的例子,其余分類型模型評價同樣可以使用。當然,模型評價方法不止這一種,大家也可以嘗試著從其他角度來做模型評價。
precision recall f1-score support
0 0.70 0.74 0.72 1454
1 0.72 0.68 0.70 1454
accuracy 0.71 2908
macro avg 0.71 0.71 0.71 2908
weighted avg 0.71 0.71 0.71 2908
本文旨在梳理數據挖掘的一般過程,沒有涉及到很復雜的算法,每個環節,如數據預處理、特征工程、模型建立于評價,均是常用的方法。本文數據也都給大家準備好了。
數據源代碼下載地址:
提取碼:niub