1??項目需求背景
為了擴大貸款業(yè)務(wù)的客戶人數(shù),該銀行去年針對現(xiàn)有的存款用戶但未辦理貸款業(yè)務(wù)的客戶展開了一項推廣活動驻子,促使其辦理個人貸款業(yè)務(wù),取得了較好的轉(zhuǎn)化效果。今年希望通過識別出更有貸款潛力的客戶哄酝,提高活動轉(zhuǎn)化率,降低營銷費用
2??數(shù)據(jù)收集
去年營銷活動的用戶信息祷膳,共包含5000條記錄陶衅,14個字段,對應字段含義如下:
ID - 客戶
Age - 客戶年齡
Experience - 客戶工作經(jīng)驗
Income - 客戶年收入(單位:千美元)
ZIPCode - 家庭地址郵政編碼
Family - 客戶的家庭規(guī)模
CCAvg - 每月信用卡消費額(單位:千美元)
Education - 教育水平 (1: 本科; 2: 研究生; 3: 高級)
Mortgage - 房屋抵押價值(如有)(單位:千美元)
Personal Loan - 此客戶是否接受上一次活動中提供的個人貸款直晨?(1:是 0:否)
Securities Account - 是否有證券賬戶万哪?(1:是 0:否)
CD Account - 是否有存款證明(CD)帳戶嗎(1:是 0:否)
Online - 是否開通網(wǎng)上銀行侠驯?(1:是 0:否)
CreditCard - 是否有信用卡?(1:是 0:否)
#導入相關(guān)庫
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns#設(shè)置全部行輸出
from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = "all"#讀取數(shù)據(jù)
data=pd.read_csv('Personal_Loan.csv')data.head()
3??數(shù)據(jù)探索和清洗
3.1??查看數(shù)據(jù)的形狀奕巍、類型吟策,處理缺失值、重復值的止、異常值
#數(shù)據(jù)整體情況
data.info()
-- 無缺失值檩坚,需要把Mortgage和Income更改為float類型,ZIP Code改為字符型
#變量類型轉(zhuǎn)換
data.Mortgage=data.Mortgage.astype('float')
data.Income=data.Income.astype('float')
data['ZIP Code']=data['ZIP Code'].astype('str')
data.info()
#查看重復值的個數(shù)
data.duplicated().sum()
-- 無重復值
#查看異常值
data.columns
#選擇散點圖方式
fig = plt.figure()
plt.scatter(data.values[:,0],data.values[:,2])
-- 查看各列的散點圖诅福,Experience列出現(xiàn)負數(shù)值匾委,為異常數(shù)據(jù)
#把Experience負值改為0
data.loc[data.Experience<0,'Experience']=0
3.2??描述性統(tǒng)計
data.describe()
4??數(shù)據(jù)預處理
4.1??去年營銷活動的效果如何
# 去年營銷活動效果
data.groupby('Personal Loan').size()
-- 5000名客戶中,有480個客戶開通了個人貸款業(yè)務(wù)氓润,轉(zhuǎn)化率9.6%赂乐,說明此次推廣活動的效果還是不錯的。數(shù)據(jù)源的可信度也比較高
4.2??特征篩選
4.2.1??相關(guān)系數(shù)
#把ID設(shè)為索引咖气,ID不屬于變量
data.set_index(['ID'],inplace=True)
#因變量Personal Loan跟其他變量的相關(guān)系數(shù)
cor = data.corr()['Personal Loan']
cor
cor[abs(cor)>0.05
#fig代表繪圖窗口(Figure)挨措;axis代表這個繪圖窗口上的坐標系(axis)
fig,axis=plt.subplots(figsize=(10,10))
#繪制熱力圖,顏色越深崩溪,相關(guān)性越強
ax=sns.heatmap(data.corr(),annot=True,linecolor='black',cmap="BrBG_r",fmt='.2f')
#fmt設(shè)置小數(shù)位
#bottom代表y軸下限浅役,top表示y軸上限(matplotlib版本畫熱力圖上下邊框只顯示一半)
bottom, top = ax.get_ylim()
ax.set_ylim(bottom + 0.5, top - 0.5);
由相關(guān)系數(shù)和熱力圖:
1.與Personal Loan強相關(guān)的變量:Income收入、CCAvg信用卡還款額和CD Account是否有是存款證明帳戶
2.與Personal Loan弱相關(guān)的變量:Education受教育程度伶唯,Mortgage房屋抵押價值和Family家庭人數(shù)
3.其中Age年齡觉既、Experience工作經(jīng)驗和ZIP Code家庭地址郵政編碼雖然關(guān)系不大,但它們屬于連續(xù)型變量乳幸,需要進一步分析瞪讼。可以分箱后再做觀察粹断,看看是否有某一段存在特殊值尝艘,也可以考慮放在模型中
定性變量:CD Account是否有是存款證明帳戶、Education受教育程度姿染、Family家庭人數(shù)
定量變量:Income收入背亥、CCAvg信用卡還款額、Mortgage房屋抵押價值
4.2.2??定性變量
# rc參數(shù)
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus'] = False
#CD Account
#開通CD Account的用戶貸款比例
data.groupby('CD Account')['Personal Loan'].agg(['mean','count'])
#可視化
f,ax1= plt.subplots()
sns.countplot(x='CD Account',hue='Personal Loan',data=data,ax=ax1)
ax1.set_title('用戶貸款比例')#標題
-- 開通了CD Account的客戶悬赏,貸款的比例遠高于是沒有開通的客戶,說明開通CD Account的客戶成為貸款業(yè)務(wù)的潛在客戶可能性更大狡汉;且大量客戶沒有開通CD Account,找到方法讓客戶開通CD Account也是一個提高貸款率的可能選項
#Education
data.groupby('Education')['Personal Loan'].agg(['mean','count'])
-- 受教育水平越高闽颇,貸款的比例越高盾戴,尤其在本科以上學歷差距明顯,說明受教育水平高的用戶成為貸款業(yè)務(wù)的潛在客戶可能性更大
#Family
data.groupby('Family')['Personal Loan'].agg(['mean','count'])
-- 單身人士與沒有孩子的家庭的貸款率都比較低兵多,有孩子的家庭用戶相對而言更有意愿轉(zhuǎn)化為貸款用戶尖啡,特別是獨生子女家庭
4.2.3??定量分析-分箱
#Income收入
data['Income_bins']=pd.qcut(data.Income,20)
data.groupby('Income_bins')['Personal Loan'].agg(['mean','count'])
data.groupby('Income_bins')['Personal Loan'].mean().plot()
-- 高收入人群明顯申請貸款的橄仆,收入小于64時,貸款率幾乎為零衅斩,收入超過98時盆顾,貸款率急劇上升,超過170時畏梆,貸款意愿達到50%
#CCAvg信用卡還款額
data['CCAvg_bins']=pd.qcut(data.CCAvg,20)
data.groupby('CCAvg_bins')['Personal Loan'].agg(['mean','count'])
data.groupby('CCAvg_bins')['Personal Loan'].mean().plot()
-- CCAvge在2.8時您宪,貸款率會增大將近4倍;在4.3-6.0區(qū)間會貸款率會達到45%奠涌;大于6時宪巨,貸款率會稍有回落,但貸款意愿依舊比較強
#Mortgage房屋抵押價值
data['Mortgage_bins']=pd.cut(data.Mortgage,10)? #等深分箱會有重復邊界值,為0的數(shù)據(jù)占比太多
data.groupby('Mortgage_bins')['Personal Loan'].agg(['mean','count'])
plt.subplots(figsize=(15,5))
data.groupby('Mortgage_bins')['Personal Loan'].mean().plot()
-- 當Mortgage大于190.5時溜畅,貸款申請的意愿有明顯的提升捏卓,總體來看,抵押值越高慈格,貸款轉(zhuǎn)化率越高怠晴。但房屋抵押價值高的客戶很少
4.2.4??對相關(guān)系數(shù)低的連續(xù)型變量分箱觀察
#Age年齡
data['Age_bins']=pd.qcut(data.Age,6)
data.groupby('Age_bins')['Personal Loan'].agg(['mean','count'])
data.groupby('Age_bins')['Personal Loan'].mean().plot()
-- Age在32-39區(qū)間時貸款率較高,但總體年齡跟貸款率的相關(guān)性不高
#Experience工作經(jīng)驗
data['Experience_bins']=pd.qcut(data.Experience,6)
data.groupby('Experience_bins')['Personal Loan'].agg(['mean','count'])
data.groupby('Experience_bins')['Personal Loan'].mean().plot()
-- Experience在7-14區(qū)間時貸款率較高峦椰,但總體工作經(jīng)驗跟貸款率的相關(guān)性不高
#ZIP Code家庭地址郵政編碼
#郵政編碼的第一個數(shù)字代表美國各州龄寞,第二個和第三個數(shù)字一起代表一個地區(qū)(或一個大城市),所以按照第2汰规、3個數(shù)字分區(qū)
data['ZIP Code_bins']=data['ZIP Code'].str.extract('9(\d\d)',expand=False)
plt.subplots(figsize=(15,5))
data.groupby('ZIP Code_bins')['Personal Loan'].agg(['mean','count'])
data.groupby('ZIP Code_bins')['Personal Loan'].mean().plot()
-- ZIP Code各地區(qū)與貸款率相關(guān)性不高
5??模型搭建
用連續(xù)型變量和分箱兩種方式測試模型的效果
5.1??用原始數(shù)據(jù)的變量
data.head(2)
最終選取加入模型的6個變量:Income收入汤功、Family家庭人數(shù)、CCAvg信用卡還款額溜哮、Education受教育程度滔金、Mortgage房屋抵押價值和CD Account是否有是存款證明帳戶(已嘗試把Experience、Age茂嗓、ZIP Code加入模型餐茵,沒有改善模型)
data.iloc[:,[2,4,5,6,7,10]].head()
# model_selection模型選擇功能
#train_test_split 訓練測試分區(qū)
#cross_val_score 交叉驗證得分
from sklearn.model_selection import train_test_split,cross_val_score
#劃分訓練集和測試集
xtrain,xtest,ytrain,ytest=train_test_split(data.iloc[:,[2,4,5,6,7,10]],data.iloc[:,8]
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ,test_size=0.3)
#test_size=0.2,指定訓練測試集隨機抽樣20%的數(shù)據(jù)
#random_state=0 隨機種子數(shù)的確定
xtrain.shape
#導入包和類
from sklearn.linear_model import LogisticRegression
#實例化
log=LogisticRegression(solver="lbfgs",C=0.04,max_iter=400)
#擬合數(shù)據(jù)
log.fit(xtrain,ytrain)
log.score(xtrain,ytrain)#訓練集R方
log.score(xtest,ytest)#測試集R方
y_log=log.predict(xtest)#predict_proba 預測評分,y的估計值述吸。根據(jù)預測的概率忿族,大于0.5的返回1
-- 正確率都是94%,考慮到數(shù)據(jù)集0蝌矛、1分布極不均衡道批,還要看下f1指標
5.2??使用連續(xù)型變量分箱后的數(shù)據(jù)
df=data.copy()
df=df.loc[:,['Income_bins','Family','CCAvg_bins','Education','Mortgage_bins','CD Account','Personal Loan']]
df.head()
#數(shù)字編碼
from sklearn.preprocessing import LabelEncoder
encoder= LabelEncoder().fit(df["Income_bins"])
df["Income_bins"] = encoder.transform(df["Income_bins"])
encoder= LabelEncoder().fit(df["CCAvg_bins"])
df["CCAvg_bins"] = encoder.transform(df["CCAvg_bins"])
encoder= LabelEncoder().fit(df["Mortgage_bins"])
df["Mortgage_bins"] = encoder.transform(df["Mortgage_bins"])
df.info() #需要的變量是數(shù)值型了
# model_selection模型選擇功能
#train_test_split 訓練測試分區(qū)
#cross_val_score 交叉驗證得分
from sklearn.model_selection import train_test_split,cross_val_score
#劃分訓練集和測試集
xtrain_new,xtest_new,ytrain_new,ytest_new=train_test_split(df.iloc[:,:6],df.iloc[:,-1]
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ,test_size=0.3,random_state=2)
#test_size=0.2,指定訓練測試集隨機抽樣20%的數(shù)據(jù)
#random_state=0 隨機種子數(shù)的確定
xtrain_new.shape
log_new=LogisticRegression(solver="lbfgs",C=0.3,max_iter=100)
#擬合數(shù)據(jù)
log_new.fit(xtrain_new,ytrain_new)
log_new.score(xtrain_new,ytrain_new)
log_new.score(xtest_new,ytest_new)
y_log_new=log_new.predict(xtest_new)
-- 正確率也是94%入撒,跟方法一差不多
6??模型評估
6.1??混淆矩陣預測
對模型進行評價
#方法一:
from sklearn.metrics import confusion_matrix #混淆矩陣包
from sklearn.metrics import classification_report #分類報告包
cm=confusion_matrix(ytest,y_log)#行放y隆豹,列放y的預測值,形成2*2的交叉表
print(classification_report(ytest,y_log,target_names=['非貸款','貸款']))
sns.heatmap(cm,fmt="d",cmap="icefire",annot=True)#annot將數(shù)值顯示在單元格里
-- 方法一:預測正確率95%,召回率53%茅逮,精準率88%璃赡,f1是66%判哥,該數(shù)據(jù)中1和0的比例差距較大,所以不能看正確率碉考,主要看f1塌计,模型總體得分較低
#方法二:
from sklearn.metrics import confusion_matrix #混淆矩陣包
from sklearn.metrics import classification_report #分類報告包
cm_new=confusion_matrix(ytest_new,y_log_new)#行放y,列放y的預測值,形成2*2的交叉表
print(classification_report(ytest_new,y_log_new,target_names=['非貸款','貸款']))
sns.heatmap(cm_new,fmt="d",cmap="icefire",annot=True)#annot將數(shù)值顯示在單元格里
-- 方法二:預測正確率95%豆励,召回率57%夺荒,精準率82%,f1是68%良蒸,比方法一得分高一點技扼,但差距不大
6.2??交叉驗證
評估模型的穩(wěn)定性
#方法一:
from sklearn.model_selection import cross_val_score,LeaveOneOut,KFold,GroupKFold
x,y=data.iloc[:,[1,2,4,5,6,7,10]],data.iloc[:,8]
scores=cross_val_score(log,x,y,cv=3,scoring="f1")
print('交叉驗證:%s'%scores)
print('平均交叉驗證得分:%s'% np.mean(scores))
-- 方法一:交叉驗證得分之差超過2%,模型過擬合
#方法二:
x_new,y_new=df.iloc[:,:6],df.iloc[:,-1]
scores_new=cross_val_score(log_new,x_new,y_new,cv=3,scoring="f1")
print('交叉驗證:%s'%scores_new)
print('平均交叉驗證得分:%s'% np.mean(scores_new))
-- 方法二:得分之差減小嫩痰,分組后的數(shù)據(jù)讓模型更穩(wěn)定了
6.3??解釋模型
輸出回歸系數(shù)和OR值
log.coef_
(np.exp(log.coef_)-1)*100
#順序:Income Family CCAvg Education Mortgage CD Account
#輸出回歸系數(shù)
log_new.coef_
(np.exp(log_new.coef_)-1)*100#方法二OR值
#順序:Income_bins Family CCAvg_bins Education Mortgage_bins CD Account
-- 方法一和方法二的OR值差別很大
6.4??用SGD模型 結(jié)合網(wǎng)格搜索進行調(diào)參
#建模
from sklearn.linear_model import SGDClassifier
sgd_clf=SGDClassifier(loss="log")
sgd_clf.fit(xtrain,ytrain)#擬合訓練集數(shù)據(jù)
sgd_clf.score(xtest,ytest)#非監(jiān)督模型是transform
from sklearn.model_selection import GridSearchCV
#參數(shù)設(shè)置
parameters=[{'penalty':['l2','l1'],'alpha':[0.04,0.05,0.06]},
? ? ? ? ? ? {'l1_ratio':[0.1,0.5,0.9,1]}
? ? ? ? ? ]
#線性回歸中叫algha系數(shù)剿吻,logistic和svm叫C。懲罰系數(shù)的倒數(shù)串纺,值越小,正則化越大(懲罰越大)丽旅,修正過擬合,共線性
grid_search=GridSearchCV(sgd_clf,parameters,cv=3,scoring='accuracy')#scoring='accuracy'
grid_search.fit(xtrain,ytrain)
print("測試得分:%s" %grid_search.score(xtest,ytest))
print("全部及最優(yōu)系數(shù):%s" %grid_search.best_estimator_)
-- 方法一最優(yōu)正則化系數(shù)是0.04纺棺,迭代正則化系數(shù)C
#建模
sgd_clf=SGDClassifier(loss="log")
sgd_clf.fit(xtrain_new,ytrain_new)#擬合訓練集數(shù)據(jù)
sgd_clf.score(xtest_new,ytest_new)#非監(jiān)督模型是transform
#參數(shù)設(shè)置
parameters=[{'penalty':['l2','l1'],'alpha':[0.04,0.05,0.06]},
? ? ? ? ? ? {'l1_ratio':[0.1,0.5,0.9,1]}
? ? ? ? ? ]
#線性回歸中叫algha系數(shù)榄笙,logistic和svm叫C。懲罰系數(shù)的倒數(shù)祷蝌,值越小,正則化越大(懲罰越大)茅撞,修正過擬合,共線性
grid_search=GridSearchCV(sgd_clf,parameters,cv=3,scoring='accuracy')#scoring='accuracy'
grid_search.fit(xtrain_new,ytrain_new)
print("測試得分:%s" %grid_search.score(xtest_new,ytest_new))
print("全部及最優(yōu)系數(shù):%s" %grid_search.best_estimator_)
-- 方法二最優(yōu)正則化系數(shù)是0.0001巨朦,迭代正則化系數(shù)C(但是這個系數(shù)迭代過去效果并不好米丘,疑問?)
7??結(jié)論
7.1??相關(guān)性部分
更容易轉(zhuǎn)化為貸款客戶的用戶有如下特征:
· 開通了銀行賬戶的用戶相對于沒有開通銀行賬戶貸款意愿更強
·?教育水平越高的客戶越容易接受貸款
·?家庭人口較多的家庭貸款意愿較強糊啡,尤其是獨生子女的家庭
·?年齡區(qū)間在30-40歲的客戶相對貸款意愿更強
·?相對收入越高拄查,貸款的意愿越強烈, 當年收入超過82時棚蓄,貸款意愿會有5倍以上的上升堕扶,超過98時,貸款意愿達到17%以上梭依,超過170時稍算,貸款意愿達到一半
·?當房屋抵押值大于190.5千美元時,貸款申請的意愿有明顯的提升,但房屋抵押價值高的客戶很少
·?每月消費額在2.8千美元以上的客戶睛挚,貸款申請的意愿有明顯的提升
7.2??模型部分
模型總體得分較低邪蛔,OR值過高,還需要找原因優(yōu)化扎狱,以下只是基于目前不成熟分析的結(jié)論
分組后的數(shù)據(jù)穩(wěn)定性更好侧到,目前得到的預測正確率95%勃教,召回率57%,精準率82%匠抗,f1是68%
在其他條件不變的情況下:
·?Income_bins增加一個單位故源,貸款率提高143%;
·?Family增加一個單位汞贸,貸款率提高130%绳军;
·?CCAvg_bins增加一個單位,貸款率提高6%矢腻;
·?Education增加一個單位门驾,貸款率提高460%;
·?Mortgage_bins增加一個單位多柑,貸款率提高4%奶是;
·?CD Account增加一個單位,貸款率提高614%