Lending Club—构建贷款违约预测模型

2024-01-16 04:50

本文主要是介绍Lending Club—构建贷款违约预测模型,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

python信用评分卡(附代码,博主录制)

https://study.163.com/course/introduction.htm?courseId=1005214003&utm_campaign=commission&utm_source=cp-400000000398149&utm_medium=share

 

https://blog.csdn.net/arsenal0435/article/details/80446829(原文链接)

1.本项目需解决的问题
    本项目通过利用P2P平台Lending Club的贷款数据,进行机器学习,构建贷款违约预测模型,对新增贷款申请人进行预测是否会违约,从而决定是否放款。

 

2.建模思路
    以下为本次项目的工作流程。

 

 

3.场景解析
    贷款申请人向Lending Club平台申请贷款时,Lending Club平台通过线上或线下让客户填写贷款申请表,收集客户的基本信息,这里包括申请人的年龄、性别、婚姻状况、学历、贷款金额、申请人财产情况等信息,通常来说还会借助第三方平台如征信机构或FICO等机构的信息。通过这些信息属性来做线性回归 ,生成预测模型,Lending Club平台可以通过预测判断贷款申请是否会违约,从而决定是否向申请人发放贷款。

1)首先,我们的场景是通过用户的历史行为(如历史数据的多维特征和贷款状态是否违约)来训练模型,通过这个模型对新增的贷款人“是否具有偿还能力,是否具有偿债意愿”进行分析,预测贷款申请人是否会发生违约贷款。这是一个监督学习的场景,因为已知了特征以及贷款状态是否违约(目标列),我们判定贷款申请人是否违约是一个二元分类问题,可以通过一个分类算法来处理,这里选用逻辑斯蒂回归(Logistic Regression)。

2)观察数据集发现部分数据是半结构化数据,需要进行特征抽象。

    现对该业务场景进行总结如下:

    根据历史记录数据学习并对贷款是否违约进行预测,监督学习场景,选择逻辑斯蒂回归(Logistic Regression)算法。
数据为半结构化数据,需要进行特征抽象。

4.数据预处理(Pre-Processing Data)
     本次项目数据集来源于Lending Club Statistics,具体为2018年第一季Lending Club平台发生借贷的业务数据。
 数据预览

 

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

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


    从上面信息可以发现,本次数据集缺失值较多的属性对我们模型预测意义不大,例如id和member_id以及url等。因此,我们直接删除这些没有意义且缺失值较多的属性。此外,如果缺失值对属性来说是有意义的,还得细分缺失值对应的属性是数值型变量或是分类类型变量。

thresh_count = len(data)*0.4 # 设定阀值
data = data.dropna(thresh=thresh_count, axis=1) #若某一列数据缺失的数量超过阀值就会被删除
再将处理后的数据转化为csv

data.to_csv('loans_2018q1_ml.csv', index = False)
loans = pd.read_csv('loans_2018q1_ml.csv')
loans.dtypes.value_counts() # 分类统计数据类型


loans.shape
(107866, 103)

同值化处理   
    如果一个变量大部分的观测都是相同的特征,那么这个特征或者输入变量就是无法用来区分目标时间。

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


缺失值处理——分类变量   
objectColumns = loans.select_dtypes(include=["object"]).columns
loans[objectColumns].isnull().sum().sort_values(ascending=False)

loans[objectColumns]


loans['int_rate'] = loans['int_rate'].str.rstrip('%').astype('float')
loans['revol_util'] = loans['revol_util'].str.rstrip('%').astype('float')
objectColumns = loans.select_dtypes(include=["object"]).columns
    我们可以调用missingno库来快速评估数据缺失的情况。

msno.matrix(loans[objectColumns]) # 缺失值可视化


    从图中可以直观看出变量“last_pymnt_d”、“emp_title”、“emp_length”缺失值较多。

    这里我们先用‘unknown’来填充。

objectColumns = loans.select_dtypes(include=["object"]).columns
loans[objectColumns] = loans[objectColumns].fillna("Unknown")
缺失值处理——数值变量
numColumns = loans.select_dtypes(include=[np.number]).columns

pd.set_option('display.max_columns', len(numColumns))
loans[numColumns].tail()

loans.drop([107864, 107865], inplace =True)
    这里使用可sklearn的Preprocessing模块,参数strategy选用most_frequent,采用众数插补的方法填充缺失值。
imr = Imputer(missing_values='NaN', strategy='most_frequent', axis=0) # axis=0 针对列来处理
imr = imr.fit(loans[numColumns])
loans[numColumns] = imr.transform(loans[numColumns])
    这样缺失值就已经处理完。

 

数据过滤
print(objectColumns)


    将以上重复或对构建预测模型没有意义的属性进行删除。

drop_list = ['sub_grade', 'emp_title', 'issue_d', 'title', 'zip_code', 'addr_state', 'earliest_cr_line',
'initial_list_status', 'last_pymnt_d', 'next_pymnt_d', 'last_credit_pull_d', 'disbursement_method']

loans.drop(drop_list, axis=1, inplace=True)
loans.select_dtypes(include = ['object']).shape
(107866, 8)


5.特征工程(Feature Engineering)
特征衍生
    Lending Club平台中,"installment"代表贷款每月分期的金额,我们将'annual_inc'除以12个月获得贷款申请人的月收入金额,然后再把"installment"(月负债)与('annual_inc'/12)(月收入)相除生成新的特征'installment_feat',新特征'installment_feat'代表客户每月还款支出占月收入的比,'installment_feat'的值越大,意味着贷款人的偿债压力越大,违约的可能性越大。
loans['installment_feat'] = loans['installment'] / ((loans['annual_inc']+1) / 12)
特征抽象(Feature Abstraction)
def coding(col, codeDict):

colCoded = pd.Series(col, copy=True)
for key, value in codeDict.items():
colCoded.replace(key, value, inplace=True)

return colCoded

#把贷款状态LoanStatus编码为违约=1, 正常=0:

loans["loan_status"] = coding(loans["loan_status"], {'Current':0,'Issued':0,'Fully Paid':0,'In Grace Period':1,'Late (31-120 days)':1,'Late (16-30 days)':1,'Charged Off':1})

print( '\nAfter Coding:')

pd.value_counts(loans["loan_status"])


        贷款状态可视化

 

loans.select_dtypes(include=["object"]).head()


    首先,我们对变量“emp_length”、"grade"进行特征抽象化。

# 有序特征的映射
mapping_dict = {
"emp_length": {
"10+ years": 10,
"9 years": 9,
"8 years": 8,
"7 years": 7,
"6 years": 6,
"5 years": 5,
"4 years": 4,
"3 years": 3,
"2 years": 2,
"1 year": 1,
"< 1 year": 0,
"Unknown": 0
},
"grade":{
"A": 1,
"B": 2,
"C": 3,
"D": 4,
"E": 5,
"F": 6,
"G": 7
}
}

loans = loans.replace(mapping_dict)
loans[['emp_length','grade']].head()


    再对剩余特征进行One-hot编码。

n_columns = ["home_ownership", "verification_status", "application_type","purpose", "term"]
dummy_df = pd.get_dummies(loans[n_columns]) # 用get_dummies进行one hot编码
loans = pd.concat([loans, dummy_df], axis=1) #当axis = 1的时候,concat就是行对齐,然后将不同列名称的两张表合并
    再清除掉原来的属性。

loans = loans.drop(n_columns, axis=1)
loans.info()

    这样,就已经将所有类型为object的变量作了转化。

col = loans.select_dtypes(include=['int64','float64']).columns
col = col.drop('loan_status') #剔除目标变量

loans_ml_df = loans # 复制数据至变量loans_ml_df
特征缩放(Feature Scaling)
    我们采用的是标准化的方法,调用scikit-learn模块preprocessing的子模块StandardScaler。
sc =StandardScaler() # 初始化缩放器
loans_ml_df[col] =sc.fit_transform(loans_ml_df[col]) #对数据进行标准化
特征选择(Feature Selecting)
    目的:首先,优先选择与目标相关性较高的特征;其次,去除不相关特征可以降低学习的难度。
#构建X特征变量和Y目标变量
x_feature = list(loans_ml_df.columns)
x_feature.remove('loan_status')
x_val = loans_ml_df[x_feature]
y_val = loans_ml_df['loan_status']
len(x_feature) # 查看初始特征集合的数量
103
    首先,选出与目标变量相关性较高的特征。这里采用的是Wrapper方法,通过暴力的递归特征消除 (Recursive Feature Elimination)方法筛选30个与目标变量相关性最强的特征,逐步剔除特征从而达到首次降维,自变量从103个降到30个。
# 建立逻辑回归分类器
model = LogisticRegression()
# 建立递归特征消除筛选器
rfe = RFE(model, 30) #通过递归选择特征,选择30个特征
rfe = rfe.fit(x_val, y_val)
# 打印筛选结果
print(rfe.n_features_)
print(rfe.estimator_ )
print(rfe.support_)
print(rfe.ranking_) #ranking 为 1代表被选中,其他则未被代表未被选中

col_filter = x_val.columns[rfe.support_] #通过布尔值筛选首次降维后的变量
col_filter

Filter

    在第一次降维的基础上,通过皮尔森相关性图谱找出冗余特征并将其剔除;同时,可以通过相关性图谱进一步引导我们选择特征的方向。

colormap = plt.cm.viridis
plt.figure(figsize=(12,12))
plt.title('Pearson Correlation of Features', y=1.05, size=15)
sns.heatmap(loans_ml_df[col_filter].corr(),linewidths=0.1,vmax=1.0, square=True, cmap=colormap, linecolor='white', annot=True)

drop_col = ['funded_amnt', 'funded_amnt_inv', 'out_prncp', 'out_prncp_inv', 'total_pymnt_inv', 'total_rec_prncp',
'num_actv_rev_tl', 'num_rev_tl_bal_gt_0', 'home_ownership_RENT', 'application_type_Joint App',
'term_ 60 months', 'purpose_debt_consolidation', 'verification_status_Source Verified', 'home_ownership_OWN',
'verification_status_Verified',]
col_new = col_filter.drop(drop_col) #剔除冗余特征

len(col_new) # 特征子集包含的变量从30个降维至15个。
15

Embedded
    下面需要对特征的权重有一个正确的评判和排序,可以通过特征重要性排序来挖掘哪些变量是比较重要的,降低学习难度,最终达到优化模型计算的目的。这里,我们采用的是随机森林算法判定特征的重要性,工程实现方式采用scikit-learn的featureimportances 的方法。
names = loans_ml_df[col_new].columns
clf=RandomForestClassifier(n_estimators=10,random_state=123) #构建分类随机森林分类器
clf.fit(x_val[col_new], y_val) #对自变量和因变量进行拟合
for feature in zip(names, clf.feature_importances_):
print(feature)

plt.style.use('ggplot')

## feature importances 可视化##
importances = clf.feature_importances_
feat_names = names
indices = np.argsort(importances)[::-1]
fig = plt.figure(figsize=(20,6))
plt.title("Feature importances by RandomTreeClassifier")
plt.bar(range(len(indices)), importances[indices], color='lightblue', align="center")
plt.step(range(len(indices)), np.cumsum(importances[indices]), where='mid', label='Cumulative')
plt.xticks(range(len(indices)), feat_names[indices], rotation='vertical',fontsize=14)
plt.xlim([-1, len(indices)])
plt.show()

# 下图是根据特征在特征子集中的相对重要性绘制的排序图,这些特征经过特征缩放后,其特征重要性的和为1.0。
# 由下图我们可以得出的结论:基于决策树的计算,特征子集上最具判别效果的特征是“total_pymnt”。

6.模型训练
处理样本不均衡
    前面已提到,目标变量“loans_status”正常和违约两种类别的数量差别较大,会对模型学习造成困扰。我们采用过采样的方法来处理样本不均衡问题,具体操作使用的是SMOTE(Synthetic Minority Oversampling Technique),SMOET的基本原理是:采样最邻近算法,计算出每个少数类样本的K个近邻,从K个近邻中随机挑选N个样本进行随机线性插值,构造新的少数样本,同时将新样本与原数据合成,产生新的训练集。

# 构建自变量和因变量
X = loans_ml_df[col_new]
y = loans_ml_df["loan_status"]

n_sample = y.shape[0]
n_pos_sample = y[y == 0].shape[0]
n_neg_sample = y[y == 1].shape[0]
print('样本个数:{}; 正样本占{:.2%}; 负样本占{:.2%}'.format(n_sample,
n_pos_sample / n_sample,
n_neg_sample / n_sample))
print('特征维数:', X.shape[1])

# 处理不平衡数据
sm = SMOTE(random_state=42) # 处理过采样的方法
X, y = sm.fit_sample(X, y)
print('通过SMOTE方法平衡正负样本后')
n_sample = y.shape[0]
n_pos_sample = y[y == 0].shape[0]
n_neg_sample = y[y == 1].shape[0]
print('样本个数:{}; 正样本占{:.2%}; 负样本占{:.2%}'.format(n_sample,
n_pos_sample / n_sample,
n_neg_sample / n_sample))

构建分类器训练
    本次项目我们采用交叉验证法划分数据集,将数据划分为3部分:训练集(training set)、验证集(validation set)和测试集(test set)。让模型在训练集进行学习,在验证集上进行参数调优,最后使用测试集数据评估模型的性能。

    模型调优我们采用网格搜索调优参数(grid search),通过构建参数候选集合,然后网格搜索会穷举各种参数组合,根据设定评定的评分机制找到最好的那一组设置。

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.3, random_state = 0) # random_state = 0 每次切分的数据都一样
# 构建参数组合
param_grid = {'C': [0.01,0.1, 1, 10, 100, 1000,],
'penalty': [ 'l1', 'l2']}
# C:Inverse of regularization strength; must be a positive float. Like in support vector machines, smaller values specify stronger regularization.

grid_search = GridSearchCV(LogisticRegression(), param_grid, cv=10) # 确定模型LogisticRegression,和参数组合param_grid ,cv指定10折
grid_search.fit(X_train, y_train) # 使用训练集学习算法


print("Best parameters: {}".format(grid_search.best_params_))
print("Best cross-validation score: {:.5f}".format(grid_search.best_score_))


print("Best estimator:\n{}".format(grid_search.best_estimator_)) # grid_search.best_estimator_ 返回模型以及他的所有参数(包含最优参数)


现在使用经过训练和调优后的模型在测试集上测试。

y_pred = grid_search.predict(X_test)
print("Test set accuracy score: {:.5f}".format(accuracy_score(y_test, y_pred,)))
Test set accuracy score: 0.66064

print(classification_report(y_test, y_pred))


roc_auc = roc_auc_score(y_test, y_pred)
print("Area under the ROC curve : %f" % roc_auc)
Area under the ROC curve : 0.660654

 


总结
    最后结果不太理想,实际工作中还要做特征分箱处理,计算IV值和WOE编码也是需要的。模型评估方面也有不足,这为以后的工作提供了些经验。

 

https://study.163.com/course/courseMain.htm?courseId=1005988013&share=2&shareId=400000000398149(博主录制)

转载于:https://www.cnblogs.com/webRobot/p/10647730.html

这篇关于Lending Club—构建贷款违约预测模型的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/611390

相关文章

Golang的CSP模型简介(最新推荐)

《Golang的CSP模型简介(最新推荐)》Golang采用了CSP(CommunicatingSequentialProcesses,通信顺序进程)并发模型,通过goroutine和channe... 目录前言一、介绍1. 什么是 CSP 模型2. Goroutine3. Channel4. Channe

Python中构建终端应用界面利器Blessed模块的使用

《Python中构建终端应用界面利器Blessed模块的使用》Blessed库作为一个轻量级且功能强大的解决方案,开始在开发者中赢得口碑,今天,我们就一起来探索一下它是如何让终端UI开发变得轻松而高... 目录一、安装与配置:简单、快速、无障碍二、基本功能:从彩色文本到动态交互1. 显示基本内容2. 创建链

Golang使用etcd构建分布式锁的示例分享

《Golang使用etcd构建分布式锁的示例分享》在本教程中,我们将学习如何使用Go和etcd构建分布式锁系统,分布式锁系统对于管理对分布式系统中共享资源的并发访问至关重要,它有助于维护一致性,防止竞... 目录引言环境准备新建Go项目实现加锁和解锁功能测试分布式锁重构实现失败重试总结引言我们将使用Go作

Python基于火山引擎豆包大模型搭建QQ机器人详细教程(2024年最新)

《Python基于火山引擎豆包大模型搭建QQ机器人详细教程(2024年最新)》:本文主要介绍Python基于火山引擎豆包大模型搭建QQ机器人详细的相关资料,包括开通模型、配置APIKEY鉴权和SD... 目录豆包大模型概述开通模型付费安装 SDK 环境配置 API KEY 鉴权Ark 模型接口Prompt

大模型研发全揭秘:客服工单数据标注的完整攻略

在人工智能(AI)领域,数据标注是模型训练过程中至关重要的一步。无论你是新手还是有经验的从业者,掌握数据标注的技术细节和常见问题的解决方案都能为你的AI项目增添不少价值。在电信运营商的客服系统中,工单数据是客户问题和解决方案的重要记录。通过对这些工单数据进行有效标注,不仅能够帮助提升客服自动化系统的智能化水平,还能优化客户服务流程,提高客户满意度。本文将详细介绍如何在电信运营商客服工单的背景下进行

Andrej Karpathy最新采访:认知核心模型10亿参数就够了,AI会打破教育不公的僵局

夕小瑶科技说 原创  作者 | 海野 AI圈子的红人,AI大神Andrej Karpathy,曾是OpenAI联合创始人之一,特斯拉AI总监。上一次的动态是官宣创办一家名为 Eureka Labs 的人工智能+教育公司 ,宣布将长期致力于AI原生教育。 近日,Andrej Karpathy接受了No Priors(投资博客)的采访,与硅谷知名投资人 Sara Guo 和 Elad G

嵌入式QT开发:构建高效智能的嵌入式系统

摘要: 本文深入探讨了嵌入式 QT 相关的各个方面。从 QT 框架的基础架构和核心概念出发,详细阐述了其在嵌入式环境中的优势与特点。文中分析了嵌入式 QT 的开发环境搭建过程,包括交叉编译工具链的配置等关键步骤。进一步探讨了嵌入式 QT 的界面设计与开发,涵盖了从基本控件的使用到复杂界面布局的构建。同时也深入研究了信号与槽机制在嵌入式系统中的应用,以及嵌入式 QT 与硬件设备的交互,包括输入输出设

Retrieval-based-Voice-Conversion-WebUI模型构建指南

一、模型介绍 Retrieval-based-Voice-Conversion-WebUI(简称 RVC)模型是一个基于 VITS(Variational Inference with adversarial learning for end-to-end Text-to-Speech)的简单易用的语音转换框架。 具有以下特点 简单易用:RVC 模型通过简单易用的网页界面,使得用户无需深入了

透彻!驯服大型语言模型(LLMs)的五种方法,及具体方法选择思路

引言 随着时间的发展,大型语言模型不再停留在演示阶段而是逐步面向生产系统的应用,随着人们期望的不断增加,目标也发生了巨大的变化。在短短的几个月的时间里,人们对大模型的认识已经从对其zero-shot能力感到惊讶,转变为考虑改进模型质量、提高模型可用性。 「大语言模型(LLMs)其实就是利用高容量的模型架构(例如Transformer)对海量的、多种多样的数据分布进行建模得到,它包含了大量的先验

图神经网络模型介绍(1)

我们将图神经网络分为基于谱域的模型和基于空域的模型,并按照发展顺序详解每个类别中的重要模型。 1.1基于谱域的图神经网络         谱域上的图卷积在图学习迈向深度学习的发展历程中起到了关键的作用。本节主要介绍三个具有代表性的谱域图神经网络:谱图卷积网络、切比雪夫网络和图卷积网络。 (1)谱图卷积网络 卷积定理:函数卷积的傅里叶变换是函数傅里叶变换的乘积,即F{f*g}