Loan Prediction Problem

问题综述
About Company
Dream Housing Finance company deals in all home loans. They have presence across all urban, semi urban and rural areas. Customer first apply for home loan after that company validates the customer eligibility for loan.

Problem
Company wants to automate the loan eligibility process (real time) based on customer detail provided while filling online application form. These details are Gender, Marital Status, Education, Number of Dependents, Income, Loan Amount, Credit History and others. To automate this process, they have given a problem to identify the customers segments, those are eligible for loan amount so that they can specifically target these customers. Here they have provided a partial data set.
用已知数据预测某人是否可以得到贷款,这是一个分类问题,我们可以用logistic regression,决策数和随机森林等模型建模。
数据连接:https://github.com/Paliking/ML_examples/tree/master/LoanPrediction

理解数据

VARIABLE DESCRIPTIONS:
Variable                    Description
Loan_ID                     ID
Gender                      性别
Married                     是否结婚(Y/N)
Dependents                  家属人数
Education                   是否是大学毕业生
Self_Employed               自雇人士(Y/N)
ApplicantIncome             申报收入
CoapplicantIncome           家庭收入
LoanAmount                  贷款金额
Loan_Amount_Term            贷款天数
Credit_History              信用记录
Property_Area               房产位置
Loan_Status                 是否批准贷款(Y/N)

观察数据特征

对数据的观察是为了更好的了解数据,判断出有用的变量,也为数据预处理提供依据。

数值观察

先读取数据集

# -*- coding: utf-8 -*-
%matplotlib inline 
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus']=False#防止作图中文乱码
import pandas as pd
import numpy as np
import matplotlib as plt
df = pd.read_csv(r'C:\Users\Administrator\Desktop\train_u6lujuX_CVtuZ9i.csv',index_col=0)

总览数据集

df.shape
image.png

观察前20条数据

df.head(20)
前20条数据

可以使用info跟能看到全局

df.info()
image.png

用describe描述统计数据

df.describe()
image.png

看看空值


image.png
total =df.isnull().sum().sort_values(ascending=False)
percent_1 =df.isnull().sum()/df.isnull().count()*100
percent_2 = (round(percent_1, 1)).sort_values(ascending=False)
missing_data = pd.concat([total, percent_2], axis=1, keys=['Total', '%'])
missing_data.head(8)
空值占比

对于非数值变量我们可以用value_counts来计数


image.png

image.png

约有69%的人得到了贷款

从统计结果我们可以看到:
1,7个变量存在空值。
2,84%的人有信用记录,约有69%的人得到了贷款。
3,从分位数看申请人收入情况,大致情况没有异常;从最大值来看申报收入和家庭收入都有离群值

申请者各属性分布

申报收入箱线图

df.boxplot(column='ApplicantIncome')
申报收入箱线图

极端值过多了,这种现象的原因有很多,在我们的数据集中我们可以用是否受大学教育来解释


image.png

我们再来看看贷款金额(LoanAmount)

image.png
import matplotlib.pyplot as plt
fig = plt.figure(figsize=(15,10))
fig.set(alpha=0.2)   

plt.subplot2grid((2,3),(0,0))            
df.Loan_Status.value_counts().plot(kind='bar')
plt.title(u"贷款批准人数") # 标题
plt.ylabel(u"人数")  

plt.subplot2grid((2,3),(0,1),colspan=2)
df['LoanAmount'].hist(bins=50)
plt.ylabel(u"人数")
plt.title(u"贷款金额")

plt.subplot2grid((2,3),(1,0))
df.Education.value_counts().plot(kind='bar')
plt.title(u"是否接受大学教育") # 标题
plt.ylabel(u"人数") 

plt.subplot2grid((2,3),(1,1),colspan=2)
plt.scatter(df.ApplicantIncome, df.CoapplicantIncome,alpha=0.4,marker='o',)
plt.xlim(0,10000)
plt.ylim(0,10000)
plt.ylabel(u"年龄")                         # 设定纵坐标名称
plt.grid(b=True, which='major', axis='y') 
plt.title(u"申报收入和家庭收入")

plt.show()
几个属性

我们看散点图(申报收入和家庭收入在一万内收入的人),有一个现象:申报收入为0的人是有家庭收入,在加入收入这个特征时我们可以把它们加起来看成是收入(Income)
贷款金额也是存在离群值的

各属性与贷款批准与否的关系

我们用pandas.crosstab形成交叉表


image.png

绘制堆叠图


信用历史和贷款批准与否

信用是一个有力的特征,信用好的更容易得到贷款。

性别和贷款批准与否

结婚与否和是否贷款
大学与贷款批准与否

接受大学教育与否也是一个特征

a=df.groupby(['Credit_History','Gender','Loan_Status'])
dfa=pd.DataFrame(a.count()['Loan_ID'])
dfa
申请金额和贷款批准与否

申请金额小更容易通过。


是否受雇佣与贷款批准与否
grid = sns.FacetGrid(df, col='Loan_Status', row='Dependents', size=2.2, aspect=2)
grid.map(plt.hist, 'LoanAmount', alpha=.5, bins=50)
grid.add_legend()
家庭人数与借款额和贷款是否批准

我们看不出家庭人数和借款额与Loan_Status的关系


我们可以从以上的图里发现一些关系和现实合理的假设:
1,有信用记录的人更容易得到贷款
2,受大学教育与否对是否贷款有些影响
3,结婚人士更容易得到贷款
4,申请金额小更容易通过
这四个特征将先用于初步训练模型


数据处理

数据处理通常是对空缺值,离群值和非数值变量进行处理。在处理时我们要衡量变量的缺失程度和特征的重要性,对一些具有意义的离群值要消除它的过度影响。

我们先对空缺值进行处理
该怎么处理空值呢?有以下几点:
1,大量样本缺失时,我们可能选择删除该变量,这类样本再加入模型可能影响模型结果。
2,适度样本缺失时,我们分两种情况:
a,连续型:做一个步长(step)。b,非连续型:把空值作为一类加入到变量中
3,缺失值不是很多,我们可以放入模型试试,也可以根据现有数据补全。

我们把训练集和测试集合并取出要预测的变量Loan_Status

train_df = pd.read_csv(r'C:\Users\Administrator\Desktop\train_u6lujuX_CVtuZ9i.csv',index_col=0)
test_df=pd.read_csv(r'C:\Users\Administrator\Desktop\test_Y3wMUE5_7gLdaTN.csv',index_col=0)#读取两个数据集合

把Loan_Status编码化(0,1),取出Loan_Status等于y待用

col_Loan_Status=pd.Categorical(train_df['Loan_Status'])
y=pd.DataFrame({'Loan_Status':col_Loan_Status.codes})
train_df=train_df.drop(['Loan_Status'],axis=1)
df=pd.concat((train_df,test_df),axis=0)

把两个收入相加生成新的列,看看他的分布

df['Income'] = df['ApplicantIncome'] + df['CoapplicantIncome']
df['Income'].hist(bins=50)
image.png

这是一个有偏分布,在做计算判断可能也会偏,我们可以让它平稳一点。

df['Income_log'] = np.log1p(df['Income'])
df.drop(['Income','ApplicantIncome','CoapplicantIncome'],axis=1,inplace=True)
df['Income_log'].hist(bins=25)
image.png

这样分布更符合正态分布

同样的我们也把LoanAmount进行对数处理,处理前先把空值填充,方法是从均值加减标准差随机取数

mean = df["LoanAmount"].mean()
std = df["LoanAmount"].std()
is_null = df["LoanAmount"].isnull().sum()
# compute random numbers between the mean, std and is_null
rand_LoanAmount = np.random.randint(mean - std, mean + std, size = is_null)
# fill NaN values in Age column with random values generated
LoanAmount_slice = df["LoanAmount"].copy()
LoanAmount_slice[np.isnan(LoanAmount_slice)] = rand_LoanAmount
df["LoanAmount"] = LoanAmount_slice
df["LoanAmount"] = df["LoanAmount"].astype(int)

对数处理

df['LoanAmount_log']=np.log1p(df['LoanAmount'])
df.drop(['LoanAmount'],axis=1,inplace=True)

看看还剩什么要处理


空缺值

Married缺失值只有三个,我们使用pandas中fillna填充,先编码化


M={'Yes':1,'No':0}
df['Married']=df['Married'].map(M)
df['Married']=df['Married'].fillna(method='pad')
df['Married']=df['Married'].astype(int)

同样的方法对Gender,Self_Employed,Dependents,LoanAmount,Education


image.png
S={'Yes':1,'No':0}
df['Self_Employed']=df['Self_Employed'].map(S)
df['Self_Employed']=df['Self_Employed'].fillna(method='pad').astype(int)

df['Loan_Amount_Term']=df['Loan_Amount_Term'].fillna(method='pad').astype(int)

G={'Male':1,'Female':0}
df['Gender']=df['Gender'].map(G)
df['Gender']=df['Gender'].fillna(method='pad').astype(int)

df['Dependents'].replace(['0','1','2','3+'],[0,1,2,3],inplace=True)
df['Dependents']=df['Dependents'].fillna(method='pad').astype(int)

E={'Graduate':1,'Not Graduate':0}
df['Education']=df['Education'].map(E)
df['Education']=df['Education'].fillna(method='pad').astype(int)

看看我们的数据。


image.png

image.png

好多了,还剩下Property_Area和Credit_History的缺失值
对Property_Area的处理,由于数字是有大小的,如果对Property_Area数字编码的话可能数字的大小对模型产生影响,因此我们对它使用pandas自带的get_dummiesOne-Hot处理。实际上以上某些变量也可以用这个方法处理。

dummy_Property_Area=pd.get_dummies(df['Property_Area'])
df=pd.concat([df,dummy_Property_Area],axis=1)
df.drop(['Property_Area'],axis=1,inplace=True)

jiexialai对Credit_History进行处理
在这里我们可以对信用记录是否是缺失分为两类看看他们与是否批准贷款的分布

fig = plt.figure()
fig.set(alpha=0.2) 
noCH=df.Loan_Status[pd.isnull(df.Credit_History)].value_counts()
CH = df.Loan_Status[pd.notnull(df.Credit_History)].value_counts()
df1=pd.DataFrame({'不缺失':CH,'缺失':noCH}).transpose()
df1.plot(kind='bar',stacked=True,color=['blue','red'])
plt.title("按信用记录是否缺失看是否贷款")
plt.xlabel("信用记录是否缺失")
plt.ylabel("人数")
image.png
image.png

信用记录是缺失值的似乎更难得到贷款。
我把空值作为一类即,再对它One-Hot处理。

dummy_Credit_History=pd.get_dummies(df['Credit_History'])
df=pd.concat([df,dummy_Credit_History],axis=1)
df.drop(['Credit_History'],axis=1,inplace=True)

都处理完了。我们看看


image.png

特征建立

日平均还款的对数:用于衡量平均每日还款

df['Day_Payment']=cc['LoanAmount']/cc['Loan_Amount_Term']
df['Day_Payment'].fillna(df['Day_Payment'].mean(),inplace=True)

家庭收入比总收入和申报收入比总收入:用来衡量收入来源

aa = pd.read_csv(r'C:\Users\Administrator\Desktop\train_u6lujuX_CVtuZ9i.csv',index_col=0)
bb = pd.read_csv(r'C:\Users\Administrator\Desktop\test_Y3wMUE5_7gLdaTN.csv',index_col=0)#读取两个数据集合
cc=pd.concat((aa,bb),axis=0)
cc['ApplicantIncome']=np.log1p(cc['ApplicantIncome'])
cc['CoapplicantIncome']=np.log1p(cc['CoapplicantIncome'])
cc['Income']=cc['ApplicantIncome']+cc['CoapplicantIncome']
df['CoIncome_index']=cc['CoapplicantIncome']/cc['Income']
df['AppIncome_index']=cc['ApplicantIncome']/cc['Income']

建立机器学习模型

先把两个集合分开

D_train_df =df.loc[train_df.index]
D_test_df =df.loc[test_df.index]
D_train_df.shape,D_test_df.shape
image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容