贷款客户违约预测模型

背景:根据已有贷款客户的还款情况数据,以预测客户是否违约,提前预警。
数据:某融资担保公司所拥有的数据,包括基本身份信息,每月还款与支出情况,行业、缴款方式、缴款记录、时间、频率等信息。
目标:建立多个机器学习模型(SVM,逻辑回归,随机森林等)。选择出稳定得分率较高的模型,以预测违约情况。

贷款客户违约预测模型_第1张图片
违约分析


【一】 建模思路

确定本次项目的流程。
贷款客户违约预测模型_第2张图片
思路流程

本次已有贷款客户数据,需要选择出相关性最强的维度,对客户是否违约进行二分类。建立模型后,预测客户是否违约,以提前预警。


【二】 数据清洗

从数据库中提取出相应的数据,观察数据。

贷款客户违约预测模型_第3张图片
客户数据(脱敏)

观察数据集后发现部分数据是半结构化数据,需要进行特征抽象。部分数据可能存在缺失,我们判定贷款申请人是否违约是一个 二元分类 问题。可以通过一个分类算法来处理。

1>查看数据集合维度
data.dtypes.value_counts()

(110292, 42)

2>查看每列属性缺失值的比例

因为数据集缺失值较多的特征对模型预测意义不大,故应先处理。

check_null = data.isnull().sum().sort_values(ascending=False)/float(len(data)) 
print(check_null[check_null > 0.2]) # 查看缺失比例大于20%的属性。

处理后可发现,本次数据集数据量完整不需要删除缺失较多的数据。
如果缺失值对属性来说是有意义的,还得细分缺失值对应的属性是数值型变量或是分类类型变量。

3>同值化处理

如果某个变量大部分的观测都是相同的特征,那么这个特征或者输入变量就无法用来区分预测值。

data = data.loc[:,data.apply(pd.Series.nunique) != 1]
data.shape

(110292, 32)

4>数据过滤

结合业务知识,将一般无关或对构建预测模型没有意义的属性整合入drop_list,后删除drop_list以提高数据置信度。

data.drop(drop_list, axis=1, inplace=True)

(110292, 22)

5>将数据做预处理

将所有字符串形式的属性转换为数字形式,将部分连续变量转换为离散变量,再对部分数据做归一化。

def Sigmoid (X):
    return (1.0 / (1 + np.exp(-float(X)));

def Replace (X,columns):
    a = X.groupby([columns],as_index=False)[columns].agg({'cnt':'count'})
    for i in a[columns]:
        X[columns] = X[columns].replace(i,a[(a[columns]== i )].index.tolist()[0])
    return (X)

def Quota (X):
    X['信用额度']=X['信用额度']*(10**-4)
    return (X)

def Age (X):
    a = X.groupby(['年龄'],as_index=False)['年龄'].agg({'cnt':'count'})
    for i in a['年龄']:
        if i < 30:
            X['年龄'].replace(i,0)
        if 30 <= i <40:
            X['年龄'].replace(i,1)
        if 40 <= i :
            X['年龄'].replace(i,2)
    return (X)

清洗完后数据:

贷款客户违约预测模型_第4张图片
各个维度方差验证

【二】 特征工程

1>特征衍生

为了提高对贷款客户的预测,根据业务经验生成新的特征。
例如:将每月分期应还金额减去上一月应还金额,再除以当月实际归还的天数,生成新特征,代表客户每月还款支出的变化,值越大意味着贷款人的偿债压力越来越大,违约的可能性越大。

2>特征缩放

采用的是标准化方法,调用scikit-learn模块preprocessing的子模块StandardScaler。
preprocessing.StandardScaler类可以用来计算数据矩阵的均值和标准差,而且这个类用起来更方便

from sklearn import preprocessing
sc =StandardScaler()  # 初始化缩放器
data_ml_df[col] =sc.fit_transform(data_ml_df[col])  #对数据进行标准化
3>特征选择

选出与目标变量相关性较高的特征。递归特征消除 (RFE)筛选15个与目标变量相关性最强的特征,去除不相关特征以降低学习的难度而达到首次降维.

def RFE (X,Y,n):
    from sklearn.linear_model import LogisticRegression
    from sklearn.feature_selection import RFE
    model = LogisticRegression()
    # 建立递归特征消除筛选器
    rfe = RFE(model, n_features_to_select=n)     #通过递归选择特征,选择n个特征
    rfe = rfe.fit(X,Y)
    return (rfe.n_features_ , rfe.estimator_ , rfe.support_ , rfe.ranking_)   #ranking 为 1代表被选中,其他则未被代表未被选中

运用PCA进行主成分分析。PCA可能会提高模型准确率,但是可解释性会下降,根据具体情况选择使用。

def PCA(data):
    from sklearn.decomposition import PCA
    pca=PCA(n_components=None, copy=True, whiten=False)
    pca.fit(data)
    return(pca.components_ ,pca.explained_variance_ratio_)

#pca.components_返回模型的各个特征向量
#pca.explained_variance_ratio_返回各个成为各自的方差百分比(贡献率)
4>相关性分析

选择出是否违约相关性最强的24个维度进行分析。

import matplotlib.pyplot as plt  
import seaborn as sns 
import numpy as np
import pandas as pd

plt.rcParams['font.sans-serif']=['SimHei']                
plt.rcParams['axes.unicode_minus']=False
corrmat = data.corr()  
k = 24
plt.figure(figsize=(12,9))
cols = corrmat.nlargest(k, '是否违约')['是否违约'].index                       
cm = np.corrcoef(data[cols].values.T)
sns.set(font_scale=1.25,font='SimHei')                                   
hm = sns.heatmap(cm, cbar=True, annot=True, square=True, fmt='.2f',cmap='BuGn_r',annot_kws={'size': 10}, yticklabels=cols.values, xticklabels=cols.values)
plt.show()
贷款客户违约预测模型_第5张图片
相关性较强的维度

【三】 模型训练

1>数据选择

在观察预测值Y之后发现,违约与按时还款差值过大,这时带入模型考虑是否准备不同的数据集合以提高准确性。
准备data1 违约量按照百分比存在,data2违约量等同于按时还款量。

def Breach(IO):          #违约的数据
    a = X.groupby(['是否违约'],as_index=False)['是否违约'].agg({'cnt':'count'})
    X=pd.read_excel(IO)
    X['是否违约'] = X['是否违约'].replace(0,np.NaN)
    X_breach= X.dropna(axis=0,how='any')
    return (X_breach)

def Abiding(IO):         #按时还款的数据
    X=pd.read_excel(IO)   
    X['是否违约'] = X['是否违约'].replace(1,np.NaN)
    X_abiding = X.dropna(axis=0,how='any')
    return (X_abiding)
2>构建分类器训练

采用交叉验证法划分数据集,将数据划分为3部分:训练集、验证集和测试集。

from sklearn import cross_validation 

def Data1(IO):           #原始数据
    X=pd.read_excel(IO)
    Y1 = X['是否违约']
    X1 = X.drop(['是否违约'],axis = 1)
    X1_train, X1_test, y1_train, y1_test = \
        cross_validation.train_test_split( X1, Y1, test_size=0.3, random_state=0)
    return (X1_train, X1_test, y1_train, y1_test)

def Data2(X_breach,X_abiding):          #同样数量  
    X_abiding = X_abiding.sample(n=len(X_breach))
    S = pd.concat([X_breach,X_abiding],axis = 0)
    S = S.sample(frac=1).reset_index(drop=True)
    Y2 = S['是否违约']
    X2 = S.drop(['是否违约'],axis = 1)
    X2_train, X2_test, y2_train, y2_test = \
        cross_validation.train_test_split( X2, Y2, test_size=0.3, random_state=0)
    return (X2_train, X2_test, y2_train, y2_test)  

本次交叉验证的比例为7:3

3>建立模型

二分类问题,首先选择逻辑回归,随机森林与支持向量机进行验证。
后根据具体情况可以考虑Adaboost,朴素贝叶斯等。

from sklearn.metrics import accuracy_score
       
def RF(X_train, X_test, y_train, y_test):    #随机森林 
    from  sklearn.ensemble  import  RandomForestClassifier
    model= RandomForestClassifier(n_estimators=100)
    model.fit(X_train, y_train)
    predicted= model.predict(X_test)
    score = accuracy_score(y_test, predicted)
    return (score)

def Svm(X_train, X_test, y_train, y_test):   #支持向量机
    from sklearn import svm
    model = svm.SVC(kernel='rbf')
    model.fit(X_train, y_train)    
    predicted= model.predict(X_test)
    score = accuracy_score(y_test, predicted)
    return (score)    

def LR(X_train, X_test, y_train, y_test):   #逻辑回归
    from sklearn.linear_model import LogisticRegression
    lor = LogisticRegression(penalty='l1',C=100,multi_class='ovr') 
    lor.fit(X_train, y_train)
    predicted= lor.predict(X_test)
    score = accuracy_score(y_test, predicted)
    return (score)    

def SGD(X_train, X_test, y_train, y_test):      #随机梯度下降
    from sklearn.linear_model import SGDClassifier
    sgdv = SGDClassifier(penalty='l1')
    sgdv.fit(X_train,y_train)
    predicted = sgdv.predict(X_test)
    score = accuracy_score(y_test, predicted)
    return (score) 

尝试不同算法后得分如下

data1 : 百分比       data2 : 同等数量 
#随机森林得分: data1 : 0.8192222222222222 data2 : 0.6958814665996986 
#支持向量机 rbf 得分: data1 : 0.7856666666666666 data2 : 0.5228528377699648
#逻辑回归得分: data1 : 0.7845555555555556 data2 : 0.5979407332998493 
#随机梯度下降得分: data1 : 0.7457777777777778 data2 : 0.5507282772476143 

比较后模型后,优化参数,提高准确性。


【四】 分析结果

训练模型得分不太满意,只有随机森林得分较高。特征工程程度加深的化,可能有助于提高模型得分。
可尝试模型融合,不同模型投票后,集成学习有助于值的预测。
百分比数据量的结果明显优于等比例数据量。

你可能感兴趣的