逻辑回归三部曲 |
您所在的位置:网站首页 › 回归三部曲是哪三部 › 逻辑回归三部曲 |
逻辑回归已经在各大银行和公司都实际运用于业务,已经有很多前辈写过逻辑回归。本文将从我实际应用的角度阐述逻辑回归的由来,致力于让逻辑回归变得清晰、易懂。逻辑回归又叫对数几率回归,是一种广义线性回归分析模型。虽然名字里有回归,但其实是分类模型,常用于二分类。 这篇文章是逻辑回归三部曲中的第三部,介绍sklearn库中逻辑回归参数的含义和使用方法,并给出项目实战的Python代码。如果想要了解逻辑回归的来源和原理,参见公众号中的文章:逻辑回归由来和逻辑回归原理 文章目录 一、在Python中如何实现逻辑回归建模1.1 调用sklearn库1.2 逻辑回归常用参数详解 二、逻辑回归模型项目实战2.1 导入基本库并设置文件存放路径2.2 导入待建模的数据2.3 分析数据基本情况2.3.1 用head函数看下数据表头和前几行数据2.3.2 用value_counts函数观测因变量y的数据分布2.3.3 用describe函数查看数据分布 2.4 用IV挑选变量2.4.1 用等频分割的方法计算单个变量的IV值2.4.2 用等频分割的方法批量计算IV值 2.5 建立模型2.5.1 用挑选好的变量建立原始模型2.5.2 把挑选好的变量转成woe再建立模型 2.6 把模型转成评分卡的形式 一、在Python中如何实现逻辑回归建模 1.1 调用sklearn库 from sklearn.linear_model import LogisticRegression as lr 1.2 逻辑回归常用参数详解 逻辑回归函数中有很多参数,可以根据自己的数据进行相应调整。如果觉得纯看参数解释会有点枯燥,可以先看本文第二部分项目实战,有需要的时候再回过头来看这部分。 LogisticRegression( solver='lbfgs', penalty='l2', class_weight=None, tol=0.0001, random_state=None, C=1.0, fit_intercept=True, intercept_scaling=1, dual=False, max_iter=100, multi_class='auto', verbose=0, warm_start=False, n_jobs=None, l1_ratio=None)参数说明: solver:求解逻辑回归损失函数对应参数的优化算法。str类型,有以下五种算法可以选择,默值为’lbfgs’。 liblinear:使用开源的liblinear库实现,内部使用坐标轴下降法来迭代优化损失函数,适用于小数据集。 lbfgs:拟牛顿法的一种,利用损失函数二阶导数矩阵(海森矩阵)来迭代优化损失函数。 newton-cg:牛顿法家族中的一种,利用损失函数二阶导数矩阵(海森矩阵)来迭代优化损失函数。 sag:随机平均梯度下降,是梯度下降法的变种,和普通梯度下降法的区别是每次迭代仅仅用一部分的样本来计算梯度,适合于样本数据多的时候。 saga:线性收敛的随机优化算法的的变种,适用于大数据集。 注1:对于常见的多元逻辑回归(OvR)和(MvM),一般(MvM)比(OvR)分类相对准确一些,但是liblinear只支持(OvR)不支持(MvM)。这意味着我们需要相对精确的多元逻辑回归时,不能选择liblinear,从而也不可以使用优化算法只能选择liblinear的L1正则。 注2:sag每次仅仅使用了部分样本进行梯度迭代,所以当样本量少的时候最好不要选择它。而如果样本量非常大,比如大于10万,sag是第一选择。但是sag不能用于L1正则化(没有连续导数)。如果你有大量的样本,同时模型的特征非常多,想要用L1正则化让模型系数稀疏化,这时就需要进行取舍。要么通过对样本采样来降低样本量 ,要么通过特征筛选提前挑选出重要变量,要么回到L2正则化。 penalty:为了解决过拟合问题,给模型加一个惩罚项。可选{‘l1’,‘l2’, ‘elasticnet’,‘none’},默认值为’l2’,如果选择’none’是不加惩罚项。 如果模型的特征非常多,我们希望一些不重要的特征系数归为零,从而让模型系数稀疏化的话,可以使用L1正则化(这个可以考虑用在变量挑选,把使用L1正则化系数为0的变量剔除掉)。penalty参数的选择会影响我们损失函数优化算法的选择。即参数solver的选择。 如果是L1正则化,只能选择’liblinear’。这是因为L1正则化的损失函数不是连续可导的,而使用{‘newton-cg’,‘lbfgs’,‘sag’}这三种优化算法时都需要损失函数的一阶或者二阶连续导数,而’liblinear’并没有这个依赖。如果是L2正则化,4种算法{‘newton-cg’,‘lbfgs’, ‘liblinear’, ‘sag’}都可以选择。 class_weight:由于样本不平衡,导致样本不是总体样本的无偏估计,使得模型的预测能力下降。 为解决样本不均衡问题,可通过调节样本权重,使某种类型的样本量越多则权重越低,样本量越少则权重越高。可选参数为{dict,‘balanced’},默认值为None,即不调节样本权重。当class_weight为balanced时,类权重的计算方法为:n_samples/(n_classes*np.bincount(y)),其中n_samples为样本数,n_classes为类别数,np.bincount(y)会输出每个类的样本数。 比如当样本标签为[1,1,0,0,0,0,0,0,0,0]时,n_samples为10,n_classes为2,np.bincount(y)为[2,8],类权重为10/(2*[2,8]),结果为[2.5,0.625]。即1的样本权重为2.5,0的样本权重为0.625,从而可以让标签数量少的样本占更高的权重。当class_weight为自定义时,对于0,1二元模型,我们可以定义class_weight={0:0.2,1:0.8},这样类型0的权重为20%,类型1的权重为80%。 什么情况下要对class_weight进行调整?下面举两个例子(只是为了举例说明,不是真实统计数据): 样本高度失衡。比如在第三方支付公司的欺诈领域,由于欺诈商户是极少一的部分,绝大部分的商户是正常商户。在建立欺诈模型的时候,99901个商户是正常商户,99个商户是欺诈商户。即0.1%的商户是欺诈商户,99.9%的商户是正常商户。如果我们不考虑权重,把所有商户都预测成正常商户,那么模型的预测准确率为99.9%,但是这种预测结果是没有任何意义的,没有抓到任何欺诈商户。 误分类代价很高。如果我们将欺诈商户分类为正常商户,可能会带来上万的损失。这时,在模型上我们可能愿意误判一些正常商户,让监控运营进行甄别,尽可能多地识别出欺诈商户,减少资金损失。 针对以上两种情况,我们可以选择balanced,或者自己确定各个类别的权重,让类库自动提高数量少的样本的权重。提高了某种分类的权重,相比不考虑权重,会有更多的样本分类划分到高权重的类别,从而可以解决上述问题。 注1:建模时使用balance这个参数,对于两端的数据可能会比较均匀。即不使用balance参数在高分区出现的坏样本占比可能会高于使用balance参数的模型(可能和行业数据有关)。如果想要在高分段准确率更高,要慎用balance参数。 注2:调节样本权重的方法有两种,第一种是在class_weight中使用balanced。另一种是在调用fit函数时,通过sample_weight来自己调节每个样本权重。那么样本的真正权重是:class_weight*sample_weight。 tol:迭代终止的条件。float类型,默认值为0.0001。 比如我们想要求取使得损失函数最小化的参数θ,现用梯度下降法进行求解,每迭代一次,损失函数的值都会减少一点,当迭代前后损失函数的差值小于0.0001时,迭代停止。 random_state:随机数种子。int类型,默认为None。仅在正则化优化算法为sag、liblinear时使用。 比如要随机产生一个初始值,可以设置种子的值为20,那么每次随机产生的值都是20这个种子对应的值,可以用此方法复现建模时的数据。 C:正则化系数的倒数。float类型,默认值为1.0,该值越小正则化越强。 fit_intercept:确定是否有一个**常数项(截距项)**应该添加到逻辑函数中的线性表达式中。bool类型,默认值为True。 intercept_scaling:仅在正则化项为‘liblinear’且fit_intercept设置为True时有用。float类型,默认值为1。 二、逻辑回归模型项目实战项目背景:由于公司发展车贷业务,需要判断新进来的申请人有多大的概率会逾期,根据逾期的概率和资金的松紧程度决定是否放贷。现在有一批历史上是否违约的客户样本数据(由于数据涉及安全问题,也是职业操守要求,故此数据不是原始数据,是经过处理的)。想根据这批历史数据训练逻辑回归模型,得到模型参数,预测未来新申请的客户逾期概率。从而决定新申请人是通过、转人工核验还是拒绝。 2.1 导入基本库并设置文件存放路径 从Python中导入最常使用的数据处理库,并设置数据的存放的地址。 # coding: utf-8 import os #导入设置路径的库 import pandas as pd #导入数据处理的库 import numpy as np #导入数据处理的库 os.chdir('F:/微信公众号/Python/19.逻辑回归/项目实战数据') #把路径改为数据存放的路径 os.getcwd() #看下当前路径2.2 导入待建模的数据 data = pd.read_csv('testtdmodel.csv',sep=',',encoding='gb18030') 注:由于数据中存在中文,如果不使用encoding对编码进行申明会报如下错误: UnicodeDecodeError: 'utf-8' codec can't decode byte 0xb6 in position 2: invalid start byte把endcoding的值设置为gb18030或gbk可以解决此类问题,成功导入数据。 2.3 分析数据基本情况 2.3.1 用head函数看下数据表头和前几行数据 我选择看前两行的数据,如果括号里为空默认展示前五行的数据,可以根据需要把2改为你想展示的行数。也可以用tail函数展示后几行数据。 data.head(2)结果:
在信贷中,有些客户因为忘记了还款日期、或者资金在短期内存在缺口(不是恶意不还),可能会导致几天的逾期,在催收后会及时还款。故一般不把历史逾期不超过x天(根据公司的实际业务情况和数据分析结果得出)的客户定义为坏客户(这里的坏不是坏人的意思,纯粹指逾期超过x天的客户)。在本文把逾期超过20天的客户标签y定义为1(坏客户),没有逾期和逾期不超过20天的客户标签y定义为0(好客户)。 data.y.value_counts()结果:
一般建模之前要看下数据的缺失情况、检查一下数据是不是存在错误。如果数据存在缺失值考虑删除这个样本,或用0值或中位数等统计变量去填充。如果删除存在缺失值的样本,模型用到的信息量就会减少。如果数据存在错误,考虑从源头纠正错误数据或删除该样本。在Python中可以用describe()函数方便地获取样本数量,变量均值,变量最小值、25%分位数、50%分位数、75%分位数、最大值等信息。 data.describe()结果:
对外拓展感觉有说不完的注意事项,本文着重讲逻辑回归的实现,故后文不再在细枝末节处做过多说明。有小细节需要注意的地方,我会在后续文章中分专题详细阐述。在变量缺失值处理好,并验证数据没有问题后。可以把数据集割分成训练集、测试集、验证集。由于本文中的标签1只有97个,再细分可能出现1过少,导致信息过少,不满足统计特性。故不区分训练集、测试集、验证集,直接把所有数据都当成训练集。接下来我们一起挑选重要变量,建立逻辑回归模型。 2.4 用IV挑选变量 挑选变量的方法多种多样,可以用IV、GBDT、随机逻辑回归、随机森林、逐步回归、cluster等等(我在建模中实际用到)。本文采用信贷中最常用的方法IV进行阐述,其它方法会在本公众号后续挑选变量专题中进行详细阐述。对于用IV挑选变量,在风控建模中的IV和WOE一文中有详细的阐述,感兴趣的可以仔细阅读一遍,本文只引用计算函数。 2.4.1 用等频分割的方法计算单个变量的IV值等频计算IV的函数如下: #等频切割变量函数 def bin_frequency(x,y,n=10): # x为待分箱的变量,y为target变量.n为分箱数量 total = y.count() #1 计算总样本数 bad = y.sum() #2 计算坏样本数 good = total-bad #3 计算好样本数 if x.value_counts().shape[0]==2: #4 如果该变量值是0和1则只分两组 d1 = pd.DataFrame({'x':x,'y':y,'bucket':pd.cut(x,2)}) else: d1 = pd.DataFrame({'x':x,'y':y,'bucket':pd.qcut(x,n,duplicates='drop')}) #5 用pd.cut实现等频分箱 d2 = d1.groupby('bucket',as_index=True) #6 按照分箱结果进行分组聚合 d3 = pd.DataFrame(d2.x.min(),columns=['min_bin']) d3['min_bin'] = d2.x.min() #7 箱体的左边界 d3['max_bin'] = d2.x.max() #8 箱体的右边界 d3['bad'] = d2.y.sum() #9 每个箱体中坏样本的数量 d3['total'] = d2.y.count() #10 每个箱体的总样本数 d3['bad_rate'] = d3['bad']/d3['total'] #11 每个箱体中坏样本所占总样本数的比例 d3['badattr'] = d3['bad']/bad #12 每个箱体中坏样本所占坏样本总数的比例 d3['goodattr'] = (d3['total'] - d3['bad'])/good #13 每个箱体中好样本所占好样本总数的比例 d3['WOEi'] = np.log(d3['badattr']/d3['goodattr']) #14 计算每个箱体的woe值 IV = ((d3['badattr']-d3['goodattr'])*d3['WOEi']).sum() #15 计算变量的iv值 d3['IVi'] = (d3['badattr']-d3['goodattr'])*d3['WOEi'] #16 计算IV d4 = (d3.sort_values(by='min_bin')).reset_index(drop=True) #17 对箱体从大到小进行排序 cut = [] cut.append(float('-inf')) for i in d4.min_bin: cut.append(i) cut.append(float('inf')) WOEi = list(d4['WOEi'].round(3)) return IV,cut,WOEi,d4先用如下语句整理好原始自变量和因变量: columns_x =[ '7天内申请人在多个平台申请借款', '1个月内申请人在多个平台申请借款', '3个月内申请人在多个平台申请借款', '7天内借款人手机申请借款平台数', '1个月内借款人手机申请借款平台数', '3个月内借款人手机申请借款平台数', '7天内借款人身份证申请借款平台数', '1个月内借款人身份证申请借款平台数', '3个月内借款人身份证申请借款平台数', '7天内关联P2P网贷平台数', '1个月内关联P2P网贷平台数', '3个月内关联P2P网贷平台数', '7天内申请人关联融资租赁平台数', '1个月内申请人关联融资租赁平台数', '3个月内申请人关联融资租赁平台数', '1个月内申请人关联一般消费分期平台数', '3个月内申请人关联一般消费分期平台数', '风险名单占比', '一度关联节点个数', '二度关联节点个数', '一度风险名单个数', '二度风险名单个数', '一度风险名单占比', '二度风险名单占比', 'X3个月内申请人手机号作为第二联系人手机号出现的次数', 'X3个月内申请人手机号作为前三联系人手机号出现的次数', '是否命中法院执行模糊名单', '是否命中法院结案模糊名单', '是否命中手机风险关注名单', '是否命中身份证风险关注名单', '命中中风险关注名单笔数', '客户异常借款笔数', '信用异常笔数', '执行标的', '申请人执行标的是否超过100000', '3个月手机号关联身份证数', '3个月身份证关联手机号数', '三个月银行相关平台数' ] #自变量名称 X = data[columns_x] #生成自变量数据框 Y = data['y'] #生成因变量y再用调用等频法算IV的函数,计算单个变量的IV值,并打印结果。 IV,cut,WOEi,d4 = bin_frequency(X['1个月内申请人在多个平台申请借款'], Y) print('IV=',IV) d4得到结果: 在变量one-by-one分析之前可以用等频切分的方法,快速算出所有变量的IV值,一般挑选IV值大于0.02的变量进入后续建模。可以用如下语句批量计算变量的IV值,并打印每个变量的分箱woe情况: ivs=[] for i in columns_x: print(i) IV,cut,WOEi,d4 = bin_frequency(X[i], Y) print('IV=', IV) ivs.append(IV) print(d4)得到结果:
得到结果(部分截图):
在用IV值大于0.02的规则挑选完变量后可以用相关性、vif、逐步回归等方法进一步挑选变量。注:IV值多少可以进入模型,需要根据公司的数据情况进行调整,一般IV值低于0.02的变量几乎没有预测效果。如果很多变量的IV值都很高,阈值可以相应提高。如果变量整体的IV值都不高,根据业务逻辑也可以加一些IV值不是很高的变量测试模型效果。挑选好变量后可以调用sklearn中的lr函数建模。 2.5 建立模型 2.5.1 用挑选好的变量建立原始模型columns_model = ['1个月内借款人身份证申请借款平台数','7天内关联P2P网贷平台数','3个月内关联P2P网贷平台数','3个月手机号关联身份证数','3个月内申请人关联融资租赁平台数','二度风险名单个数','是否命中身份证风险关注名单','原始分','一度风险名单个数']X_model = data[columns_model] #生成入模自变量y = data['y'] #生成入模因变量 from sklearn.linear_model import LogisticRegression as lr #导入逻辑回归库lr_model_1 = lr() #调用逻辑回归lr_model_1_y = lr_model_1.fit(X_model, y) #用样本数据训练逻辑回归模型y_proba_model_1 = lr_model_1_y.predict_proba(X_model) #用训练好的模型预测y_proba_model_1 注:本文为了不泄露公司的数据信息,挑选的变量已经经过数据替换,不是真实数据,只是为了数据展示。 得到结果:
得到结果: 2.5.2 把挑选好的变量转成woe再建立模型 在建完原始模型后一般要把变量转成woe后,再用逻辑回归训练一次变量,得到相应的系数。因为把变量转成woe后变量具有更好的鲁棒性,模型会更加稳定。比如年龄这个变量,如果不分箱转成woe,在客户从25岁变到26岁时评分可能完全不一样。而转成woe后变量是一个一个的小箱子,在箱子内值的变动不会对模型分产生影响。如果25到26刚好在一个箱子里,这个人的评分不会因为年龄的改变而发生变化。由于篇幅问题,在本文中只给转出转woe后建模的结果: 2.6 把模型转成评分卡的形式 把变量转成woe后,可以根据分箱情况和逻辑回归的结果,通过转换把变量变成评分卡的形式: 你可能感兴趣: 用Python绘制皮卡丘 用Python绘制词云图 逻辑回归三部曲——逻辑回归和sigmod函数的由来 逻辑回归三部曲——逻辑回归(logistics regression)原理-让你彻底读懂逻辑回归 Python画好看的星空图V2版——添加背景图片和音乐 ![]() |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |