案例数据介绍

本案例中的企业从事个人汽车金融服务,向购车的个人提供信用贷款。该公司的风控部门根据贷款申请者的基本属性、信贷历史、历史信用情况、贷款标的物的情况等信息构建贷款违约顶测模型,其中是否违约bad_ind是因变量。数据来自《Python数据科学:技术详解与商业实践》第八章。

import numpy as np
from sklearn.linear_model import LogisticRegression,LogisticRegressionCV
from sklearn.model_selection import train_test_split
import pandas as pd
from sklearn.metrics import classification_report,confusion_matrix
import matplotlib.pyplot as plt
accepts = pd.read_csv(r'C:\Users\accepts2.csv').dropna()
#%%
##数据说明:本数据是一份汽车贷款违约数据
##名称---中文含义
##application_id---申请者ID
##account_number---帐户号
##bad_ind---是否违约
##vehicle_year---汽车购买时间
##vehicle_make---汽车制造商
##bankruptcy_ind---曾经破产标识
##tot_derog---五年内信用不良事件数量(比如手机欠费消号)
##tot_tr---全部帐户数量
##age_oldest_tr---最久账号存续时间(月)
##tot_open_tr---在使用帐户数量
##tot_rev_tr---在使用可循环贷款帐户数量(比如信用卡)
##tot_rev_debt---在使用可循环贷款帐户余额(比如信用卡欠款)
##tot_rev_line---可循环贷款帐户限额(信用卡授权额度)
##rev_util---可循环贷款帐户使用比例(余额/限额)
##fico_score---FICO打分,越高信用越好
##purch_price---汽车购买金额(元)
##msrp---建议售价
##down_pyt---分期付款的首次交款
##loan_term---贷款期限(月)
##loan_amt---贷款金额
##ltv---贷款金额/建议售价*100
##tot_income---月均收入(元)
##veh_mileage---行使里程(Mile)
##used_ind---是否二手车
Out[2]: application_id  account_number  bad_ind  ...  veh_mileage used_ind weight
0            2314049           11613        1  ...      24000.0        1   1.00
1              63539           13449        0  ...         22.0        0   4.75
3            8725187           15359        1  ...      10000.0        1   1.00
4            4275127           15812        0  ...         14.0        0   4.75
5            8712513           16979        0  ...          1.0        0   4.75...             ...      ...  ...          ...      ...    ...
5840         2291068        10005156        0  ...      45000.0        1   4.75
5841         7647192        10005616        0  ...         21.0        0   4.75
5842         5993246        10006591        0  ...      25000.0        1   4.75
5843         4766566        10010208        0  ...          0.0        0   4.75
5844         1928782        10010219        0  ...         12.0        0   4.75[4105 rows x 25 columns]

下面对数据进行预处理,并生成一些衍生比值指标:

##衍生变量计算函数:
def divMy(x,y):if x==np.nan or y==np.nan:return np.nanelif y==0:return -1else:return x/y
##历史负债收入比:tot_rev_line/tot_income
accepts["dti_hist"]=accepts[["tot_rev_line","tot_income"]].apply(lambda x:divMy(x[0],x[1]),axis = 1)
##本次新增负债收入比:loan_amt/tot_income
accepts["dti_mew"]=accepts[["loan_amt","tot_income"]].apply(lambda x:divMy(x[0],x[1]),axis = 1)
##本次贷款首付比例:down_pyt/loan_amt
accepts["fta"]=accepts[["down_pyt","loan_amt"]].apply(lambda x:divMy(x[0],x[1]),axis = 1)
##新增债务比:loan_amt/tot_rev_debt
accepts["nth"]=accepts[["loan_amt","tot_rev_debt"]].apply(lambda x:divMy(x[0],x[1]),axis = 1)
##新增债务额度比:loan_amt/tot_rev_line
accepts["nta"]=accepts[["loan_amt","tot_rev_line"]].apply(lambda x:divMy(x[0],x[1]),axis = 1)
##bankruptcy_ind的'Y'和'N'转换为1和0
accepts["bankruptcy_ind"]=accepts["bankruptcy_ind"].apply(lambda x:1 if x=='Y' else (0 if x=='N' else np.nan))

Logistic回归

Logistic回归通过logit转换将取值为正负无穷的线性方程的值域转化为(0,1) ,正好与概率的取值范围一致,如下所示:

其中 Pi / (1-Pi) 可解释为在样本中违约的概率是不违约的概率的多少倍。在scikit-learn中,与逻辑回归有关的主要是LogisticRegression、LogisticRegressionCV等。主要区别是LogisticRegressionCV使用了交叉验证来选择正则化系数C,而LogisticRegression需要自己每次指定一个正则化系数(其中C参数为正则化系数λ的倒数,默认为1)。

一、LogisticRegression()

sklearn.linear_model.LogisticRegression(penalty=‘l2’, dual=False, tol=0.0001, C=1.0,fit_intercept=True, intercept_scaling=1, class_weight=None, random_state=None,solver=‘liblinear’, max_iter=100, multi_class=‘ovr’, verbose=0,warm_start=False, n_jobs=1),其中最常使用的参数有正则化选择参数:penalty,优化算法选择参数:solver,分类方式选择参数:multi_class,类型权重参数:class_weight以及样本权重参数:sample_weight等,具体可参阅sun_shengyun:sklearn逻辑回归类库使用小结。

正则化选择参数penalty

  • LogisticRegression默认带了正则化项L2。penalty参数可选择的值为"l1"和"l2"。
  • 上篇博客也说到,在调参时如果主要目的只是为了解决过拟合,一般penalty选择L2正则化就够了。如果选择L2发现还是过拟合,即预测效果差时,就可以考虑L1正则化。另外,如果模型的特征非常多,我们希望一些不重要的特征系数归零,从而让模型系数稀疏化的话,也可以使用L1正则化。
  • penalty参数的选择会影响我们损失函数优化算法参数solver的选择。如果是L2正则化,那么4种可选的算法{‘newton-cg’, ‘lbfgs’, ‘liblinear’, ‘sag’}都可选。但如果是L1正则化,就只能选择‘liblinear’了。这是因为L1正则化的损失函数不是连续可导的,而{‘newton-cg’, ‘lbfgs’,‘sag’}这三种优化算法时都需要损失函数的一阶或者二阶连续导数。

优化算法选择参数solver

  • solver参数决定了我们对逻辑回归损失函数的优化方法,有4种算法可以选择,分别是:liblinear、 lbfgs、newton-cg、sag。
  • L1、liblinear:适用于小数据集;如果选择L2正则化发现还是过拟合,就可以考虑L1正则化;如果模型的特征非常多,希望一些不重要的特征系数归零,也可以使用L1正则化。
  • L2、liblinear:libniear只支持多元逻辑回归的OvR,不支持MvM,但MVM相对精确。
  • L2、lbfgs/newton-cg/sag:较大数据集,支持one-vs-rest(OvR)和many-vs-many(MvM)两种分类方式选择参数下的多元逻辑回归。
  • L2、sag:如果样本量非常大,比如大于10万,sag是第一选择;但不能用于L1正则化。

分类方式选择参数multi_class

  • multi_class参数决定了分类方式的选择,有 ovr和multinomial两个值可以选择,默认是 ovr。
  • ovr即前面提到的one-vs-rest(OvR),而multinomial即前面提到的many-vs-many(MvM)。如果是二元逻辑回归(即只有两种可能结果,如违约和不违约),ovr和multinomial并没有任何区别,区别主要在多元逻辑回归上。

类型权重参数class_weight

  • 考虑误分类代价敏感、分类类型不平衡的问题,class_weight可选 : ‘balanced’, default: None
  • class_weight参数用于标示分类模型中各种类型的权重,可以不输入,即不考虑权重,或者说所有类型的权重一样。如果选择输入的话,可以选择balanced让类库自己计算类型权重,或者我们自己输入各个类型的权重,比如对于0,1的二元模型,我们可以定义class_weight={0:0.9,1:0.1},这样类型0的权重为90%,而类型1的权重为10%。
  • 如果class_weight选择balanced,那么类库会根据训练样本量来计算权重。某种类型样本量越多,则权重越低,样本量越少,则权重越高。

样本权重参数sample_weight

  • 当样本是高度失衡的,导致样本不是总体样本的无偏估计,从而可能导致我们的模型预测能力下降。调节样本权重的方法有两种,第一种是在class_weight使用balanced。第二种是在调用fit函数时,通过sample_weight来自己调节每个样本权重
  • 如果上面两种方法都用到了,那么样本的真正权重是class_weight*sample_weight。

这里我们选择C=0.01(即λ=100),penalty = ‘l2’,solver=‘lbfgs’。下面根据数据集中25个特征(排除application_id、account_number、vehicle_make)以及bad_ind进行多变量逻辑回归:

data=accepts.iloc[:,4:]#25个特征数据
target=accepts.bad_ind
train_X,test_X,train_y,test_y = train_test_split(data,target,test_size = 0.3,random_state = 0)
logit=LogisticRegression(C = 0.01,penalty = 'l2',solver='lbfgs',max_iter = 100000).fit(train_X,train_y)
coef = pd.Series(logit.coef_[0,:],index = train_X.columns)
###绘制特征系数大小排名图
from pylab import mpl
mpl.rcParams['font.sans-serif'] = ['SimHei']
mpl.rcParams['axes.unicode_minus']=False
plt.figure(figsize=(8,6))
coef.sort_values().plot(kind = "barh",width = 0.35)
plt.title("模型中各特征的系数")
plt.grid()
plt.show()


可以看到25个特征中有不少特征系数几乎为0,因此可以剔除这些特征再进行逻辑回归,此处不再赘述。下面是LogisticRegression自带的一些方法,可以查看对测试集的预测效果:

prob0_test = logit.predict_proba(test_X)[:,0]#预测属于0的概率
prob1_test = logit.predict_proba(test_X)[:,1]#预测属于1的概率
pred_test = logit.predict(test_X)#预测标签
test_table = pd.DataFrame({'预测标签':pred_test,'预测为0的概率':prob0_test,'预测为1的概率':prob1_test})
test_table.head(16)
Out[106]: 预测标签   预测为0的概率   预测为1的概率
0      0  0.877870  0.122130
1      0  0.592357  0.407643
2      0  0.967154  0.032846
3      0  0.874919  0.125081
4      0  0.552422  0.447578
5      0  0.611668  0.388332
6      0  0.904147  0.095853
7      0  0.834194  0.165806
8      0  0.664811  0.335189
9      0  0.890139  0.109861
10     0  0.653965  0.346035
11     0  0.670883  0.329117
12     0  0.707951  0.292049
13     0  0.858788  0.141212
14     0  0.990260  0.009740
15     1  0.439046  0.560954
print(logit.score(train_X,train_y),logit.score(test_X,test_y))#返回平均准确率
0.8172641837800209 0.8051948051948052

可以看到第一列为预测结果,二、三列为预测为0(不违约)和1(违约)的概率。在第15条数据中,由于预测为0的概率小于预测为1的概率,因此分类标签为1。训练集和测试集的准确率均在80%以上且相差不大,拟合效果较好。

二、LogisticRegressionCV()

交叉验证法(cross validation)先将数据集划分为 k 个大小相似的互斥子集,每次用 k-1 个子集的并集作为训练集,余下的那个子集作为测试集,这样就可获得 k 组训练/测试集,从而可进行 k 次训练和测试,最终返回的是这 k 个测试结果的均值。交叉验证法评估结果的稳定性和保真性在很大程度上取决于 k 的取值,为强调这一点,通常把交叉验证法称为 k 折交叉验证 (k-fold cross validation),k 最常用的取值是 5、10、20等。下图给出了10折交叉验证的示意:

LogisticRegressionCV(*, self, Cs=10, fit_intercept=True, cv=None, dual=False, penalty=‘l2’, scoring=None, solver=‘lbfgs’, tol=1e-4, max_iter=100, class_weight=None, n_jobs=None, verbose=0, refit=True, intercept_scaling=1., multi_class=‘auto’, random_state=None, l1_ratios=None),其中:

  • Cs表示产生C的个数,例如Cs=10,会产生相应的10个C:10(-4), 10(-3.11),10(-2.22), … , 10(-3.11), 104,LogisticRegressionCV会自动进行交叉验证,从上面10个C里面挑出最佳的C;
  • 交叉验证参数cv,默认fold数量为3,使用3折交叉验证;
  • 并行数n_jobs,默认值1,-1表示与CPU个数一致。
  • 其它参数含义可参考官方文档。
logitCV=LogisticRegressionCV(Cs = 10,penalty = 'l2',solver='lbfgs',max_iter = 100000).fit(train_X,train_y)
print(logitCV.score(train_X,train_y),logitCV.score(test_X,test_y))#返回给出的数据和标签的平均准确率
0.8169161155586495 0.8051948051948052
logitCV.C_#搜索出的最佳得分下的C值
Out[114]: array([1291.54966501])

查准率、查全率及F1值

sklearn中的classification_report函数用于显示主要分类指标的文本报告,在报告中显示每个类的查准率、查全率及F1值等信息。其中左边的一列为分类的标签名、准确度、宏平均和加权平均等,support列为每个标签的出现次数/总和,precision、recall、f1-score三列分别为各个类别的查准率、查全率及F1值

print(confusion_matrix(test_y,pred_test,labels=[0,1]))#LogisticRegression方法下的混淆矩阵
print(classification_report(test_y,pred_test))#LogisticRegression方法下的分类结果报告
[[970  18][222  22]]precision    recall  f1-score   support0       0.81      0.98      0.89       9881       0.55      0.09      0.15       244accuracy                           0.81      1232macro avg       0.68      0.54      0.52      1232
weighted avg       0.76      0.81      0.74      1232

对于二分类问题,可将样例根据其真实类别与学习器预测类别的组合划分为真正例(true positive)、假正例(false positive)、真反例(true negative)、 假反例(false negative)四种情形,令TP、FP、TN、FN分别表示其对应的样例数,则显然有TP+FP+TN+FN=样例总数。分类结果的混淆矩阵如下:

查准率和查全率是一对矛盾的度量。一般来说,查准率高时,查全率往往偏低;而查全率高时,查准率往往偏低。F1是基于查准率与查全率的调和平均定义的:

对混淆矩阵结果的判断可参考Vincent__Lai:如何通过Recall和Precise快速判断自己模型的问题。在一些应用中,对查准率和查全率的重视程度有所不同。例如在商品推荐系统中,为了尽可能少打扰用户,更希望推荐内容确是用户感兴趣的,此时查准率更重要;而在逃犯信息检索系统中,更希望尽可能少漏掉逃犯,此时查全率更重要。而本案例的贷款发生违约的后果严重,因此查全率更加重要,后续工作应该是着力于提高标签1预测的查全率,比如修改分类的默认阈值0.5、提高标签为1样本的权重等。下面通过修改class_weight='balanced’来提高查全率:

logit3 = LogisticRegression(C = 0.01,penalty = 'l2',solver='lbfgs',class_weight\
= 'balanced',max_iter = 100000).fit(train_X,train_y)
pred_test3 = logit3.predict(test_X)
print(classification_report(test_y, pred_test3))precision    recall  f1-score   support0       0.91      0.65      0.76       9881       0.35      0.75      0.47       244accuracy                           0.67      1232macro avg       0.63      0.70      0.62      1232
weighted avg       0.80      0.67      0.70      1232

可以看到标签1的查全率大大提高了。

ROC和AUC

ROC全称是"受试者工作特征" (Receiver Operating Characteristic) 曲线。ROC 曲线的纵轴是"真正例率" (True Positive Rate,简称 TPR),横轴是"假正例率" (False Positive Rate,简称 FPR),基于前文混淆矩阵中的符号,两者分别定义为:

显示 ROC 曲线的图称为 ROC 图,下图给出了一个示意图,显然对角线对应于"随机猜测"模型,而点 (0,1) 则对应于将所有正例排在所有反例之前的"理想模型"。

绘图过程很简单:给定m+个正例和m-个反例,根据学习器预测结果对样例进行排序,然后把分类阈值设为最大,即把所有样例均预测为反例,此时真正例率和假正例率均为0,在坐标 (0,0) 处标记一个点。然后,将分类阈值依次设为每个样例的预测值,即依次将每个样例划分为正例。设前一个标记点坐标为 (x,y), 当前若为真正例,则对应标记点的坐标为 (x,y+1/m+);当前若为假正例,则对应标记点的坐标为 (x+1/m-,y),然后用线段连接相邻点即得。

进行学习器的比较时,若一个学习器的 ROC 曲线被另一个学习器的曲线完全"包住",则可断言后者的性能优于前者;若两个学习器的 ROC 曲线发生交叉,则难以断言两者孰优孰劣。此时如果一定要进行比较,则较为合理的判据是比较 ROC 曲线下的面积,即AUC (Area Under ROC Curve),如上图所示。

sklearn.metrics.roc_curve函数可绘制ROC曲线。fpr, tpr, thresholds = roc_curve(y_true, y_score, pos_label = None, sample_weight = None, drop_intermediate = True):

  • y_true是真实的样本标签,默认为{0,1}或者{-1,1}。如果要设置为其它值,则 pos_label 参数要设置为特定值。
  • y_score是预测为正label的概率;
  • pos_label即标签中认定为正的label;
  • sample_weight即采样权重,可选择取其中的一部分进行计算;
  • drop_intermediate(default=True)即可选择去掉一些对于ROC性能不利的阈值,使得到的曲线有更好的表现性能。
  • 返回值fpr, tpr, thresholds即前文提到的假正例率、真正例率和阈值。

下面以LogisticRegression得出的结果为例,画出ROC曲线,计算AUC值。此处正label为0,因此pos_label=0,y_score为预测标签为0的概率prob0_test:

from sklearn.metrics import roc_curve,auc
false_positive_rate,true_positive_rate,thresholds=roc_curve(test_y,prob0_test,pos_label=0)
roc_auc=auc(false_positive_rate, true_positive_rate)
plt.title('ROC')
plt.plot(false_positive_rate, true_positive_rate,'b',label='AUC = %0.2f'% roc_auc)
plt.legend(loc='best')
plt.plot([0,1],[0,1],'r--')#随机猜测45°线
plt.ylabel('TPR')
plt.xlabel('FPR')
plt.show()

参考文献

https://blog.csdn.net/sun_shengyun/article/details/53811483
https://blog.csdn.net/w1301100424/article/details/84546194
http://www.sofasofa.io/forum_main_post.php?postid=1000383
周志华《机器学习》,清华大学出版社
常国珍等《Python数据科学:技术详解与商业实践》,机械工业出版社

(六十二)基于logistic回归的信用评级和分类模型评估相关推荐

  1. 【Clemetine】基于二项Logistic回归的电信客户流失预测

    一.实验目的及要求 1.掌握Logistic回归分析的基本步骤.原理.软件实现.结果分析: 2.理解多重共线性的概念.原理及岭轨迹的软件实现: 3.了解高维数据分析的应用领域及分析方法. 二.实验仪器 ...

  2. 机器学习笔记1:基于Logistic回归进行数据预测

    机器学习笔记1:基于Logistic回归进行数据预测 一.背景 近期项目的一个核心部分就是实现对数据的预测,因为没有实际的数据样本,所以我准备近期学习Machine Learning的几种方式,从简单 ...

  3. 用python计算贷款_Python基于Logistic回归建模计算某银行在降低贷款拖欠率的数据示例...

    本文实例讲述了Python基于Logistic回归建模计算某银行在降低贷款拖欠率的数据.分享给大家供大家参考,具体如下: 一.Logistic回归模型: 二.Logistic回归建模步骤 1.根据分析 ...

  4. SAP UI5 应用开发教程之六十二 - 基于 OData V4 的 SAP UI5 表格控件使用方法介绍试读版

    一套适合 SAP UI5 初学者循序渐进的学习教程 教程目录 SAP UI5 本地开发环境的搭建 SAP UI5 应用开发教程之一:Hello World SAP UI5 应用开发教程之二:SAP U ...

  5. 数据科学和人工智能技术笔记 十二、逻辑回归

    十二.逻辑回归 作者:Chris Albon 译者:飞龙 协议:CC BY-NC-SA 4.0 C 超参数快速调优 有时,学习算法的特征使我们能够比蛮力或随机模型搜索方法更快地搜索最佳超参数. sci ...

  6. 数学建模-分类模型(基于logistic回归)

    基于logistic回归的分类模型: 对于二分类模型,采用基础逻辑回归(logistic regression) 对于多分类模型,采用多分类逻辑回归 模型要求(针对01 logistic) 假设1:因 ...

  7. 面渣逆袭:三万字,七十图,详解计算机网络六十二问(收藏版)

    大家好,我是老三,开工大吉,虎年第一篇,面渣逆袭系列继续! 这次给大家带来了计算机网络六十二问,三万字,七十图详解,大概是全网最全的网络面试题. 建议大家收藏了慢慢看,新的一年一定能够跳槽加薪,虎年& ...

  8. 面渣逆袭:计算机网络六十二问,三万字图文详解!速收藏!

    这次给大家带来了计算机网络六十二问,三万字,七十图详解,大概是全网最全的网络面试题. 基础 1.说下计算机网络体系结构 计算机网络体系结构,一般有三种:OSI 七层模型.TCP/IP 四层模型.五层结 ...

  9. 基于Logistic回归的麻雀搜索算法

    文章目录 一.理论基础 1.麻雀搜索算法 2.改进麻雀搜索算法 (1)逐维小孔成像反向学习优化发现者位置 (2)基于Logistic模型的自适应因子 (3)算法伪代码 二.仿真实验与分析 三.参考文献 ...

最新文章

  1. 设计模式 之美 -- 建造者模式
  2. Understanding Global Unicast IPv6 Addressing
  3. AC日记——中位数 洛谷 P1168
  4. JavaScript快速入门(六)——DOM
  5. linux编译安装ansible 2.9.22
  6. MYSQL查表的字段名称,字段类型,字段长度,字段注释的SQL语句
  7. hadoop2.2单节点集群的搭建
  8. python pandas使用pipe管道增强代码可读性
  9. 如何在SQL Server中使用级联删除?
  10. 电话系统服务器,局域网电话系统的两种解决方案——是否需要I
  11. HDU1799 循环多少次?【打表】
  12. linux用管理员给用户权限,Linux普通用户获得管理员权限
  13. 禁不住诱惑?不可描述的应用之下暗藏巨大风险
  14. VMware Workstation安装windows xp系统并创建虚拟软盘
  15. 【转载】WAMP5:PHP环境整合安装(图解)及密码设置图解
  16. R语言需要C语言基础吗,R语言入门(1)-初识R语言
  17. android垃圾清理动画,[Android开发实战]金山清理大师(猎豹清理大师)一键加速快捷方式动画实现...
  18. python 编程题 有n个整数、使其前面各数_有n个整数,使其前面各数顺序向后移m个位置,最后m个数变成最前面m个数。...
  19. 蓝桥杯 青少年创意编程大赛 scratch 组(一)
  20. 如何在CAD中加载卫星地图并作街道与建筑绘制

热门文章

  1. untiy的http请求
  2. 51单片机_15-1 LED亮度调节
  3. 台式计算机如何安装摄像头,台式机如何使用摄像头
  4. 吴海燕C语言真题,基于APP的智能婴儿床系统的设计与实现开题报告
  5. 企业微信组织架构同步教程
  6. Matter协议特性解析(一) 支持非Matter协议,私有协议,Matter Bridge技术分析
  7. 获取公众号的关注链接
  8. ROS机器人开机自启动设置
  9. python批量请求url_python批量请求注册接口爬虫相关问题记录
  10. win10 运行debussy不能打开波形窗口问题