五、逻辑回归

统计模型综述

变量预测变量
分类连续连续和分类
反应变量连续方差分析普通最小二乘法协方差分析
分类列联表分析、逻辑回归逻辑回归逻辑回归

1. 引言——汽车贷款信用违约预测案例

- 1.导入数据:汽车金融数据
##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---是否二手车
##weight---样本权重
import os
import numpy as np
from scipy import stats
import pandas as pd
import statsmodels.api as sm
import statsmodels.formula.api as smf
import matplotlib.pyplot as plt

#pd.set_option('display.max_columns', None)
os.chdir(r"E:\脚本")
accepts = pd.read_csv(r'accepts.csv').dropna()
accepts

在这里插入图片描述

1.1 分析衍生变量

  • 拿到数据之后,可以考虑是否做衍生变量。
# 定义除法函数
def divMy(x,y):
    import numpy as np
    if x==np.nan or y==np.nan:
        return np.nan
    elif y==0:
        return -1
    else:
        return float(x)/float(y)
- 衍生变量
- 1.历史负债收入比:tot_rev_line/tot_income
accepts["dti_hist"]=accepts[["tot_rev_line","tot_income"]].apply(lambda x:divMy(x[0],x[1]),axis = 1)
- 2.本次新增负债收入比:loan_amt/tot_income
accepts["dti_mew"]=accepts[["loan_amt","tot_income"]].apply(lambda x:divMy(x[0],x[1]),axis = 1)
- 3.本次贷款首付比例:down_pyt/loan_amt
accepts["fta"]=accepts[["down_pyt","loan_amt"]].apply(lambda x:divMy(x[0],x[1]),axis = 1)
- 4.新增债务比:loan_amt/tot_rev_debt
accepts["nth"]=accepts[["loan_amt","tot_rev_debt"]].apply(lambda x:divMy(x[0],x[1]),axis = 1)
- 5.新增债务额度比:loan_amt/tot_rev_line
accepts["nta"]=accepts[["loan_amt","tot_rev_line"]].apply(lambda x:divMy(x[0],x[1]),axis = 1)

在这里插入图片描述

1.2 判断是否相关

Y(是否违约)是二分类变量,判断是否相关:计算频次并且频次求行百分比,若百分比相差不大则无相关性。

步骤一
原假设:是否破产与是否违约没有关系
备择假设:是否破产与是否违约是有相关关系的。
步骤二
判断相关性,分类变量计算行百分比
步骤三
检验相关性:分类变量采用卡方检验

1.2.1 分类变量相关性:交叉表

  • Y:是否违约;X:是否二手车
    行变量:解释变量(X);列变量:被解释变量(Y)
- 1.分类变量的相关关系:交叉表 
cross_table = pd.crosstab(accepts.used_ind,accepts.bad_ind,margins=True)
cross_table

在这里插入图片描述

  • 2.计算行百分比,判断相关性
- 2.计算行百分比
def percConvert(ser):
    return ser/float(ser[-1])

cross_table.apply(percConvert, axis=1)

在这里插入图片描述
百分比相差不大,认为是相互独立的。

  • 3.数据独立满足的公式
    X、Y独立,则满足 P ( X = 0 , Y = 0 ) = P ( X = 0 ) ∗ P ( Y = 0 ) P(X=0,Y=0) = P(X=0) * P(Y=0) P(X=0,Y=0)=P(X=0)P(Y=0)

1.3 检验相关性

X、Y是分类变量,所以用卡方检验来检验相关性。公式即:
χ 2 = ∑ i = 1 R ∑ j = 1 C ( O b s i j − E x p i j ) 2 E x p i j \chi^2 =\sum_{i=1}^{R}\sum_{j=1}^{C}\frac{(Obs_ij - Exp_ij)^2}{Exp_ij} χ2=i=1Rj=1CExpij(ObsijExpij)2
卡方值 = (样本量的观测 - 原假设成立时的期望)^2/期望值

- 4.卡方检验
print(''' chisq = %6.4f p-value=%6.4f dof=%i excepted_freq=%s''' %stats.chi2_contingency(cross_table.iloc[:2,:2]))

在这里插入图片描述
模型解释:
原假设是X与Y之间是独立的,样本量是8211,则对应的α是【0.001 - 0.1】,P值<α表示原假设不成立,P值>α表示原假设是成立的。结果可知,P值为0.0004,所以是有关系的。

2.逻辑回归

案例:最久账号存续时间和违约有什么影响?
反应变量(X):违约
预测变量(Y):最久账号存续时间

2.1 构建假设

原假设:借贷时间与是否违约没有关系
备择假设:借贷事件与是否违约有关系

2.2 绘制散点图

accepts.plot(x='age_oldest_tr',y='bad_ind',kind='scatter')

在这里插入图片描述
模型解释
账户存续时间越长,不违约的人要多一点,违约的人相对少一点。

2.3 选择回归模型

2.3.1 普通最小二乘法模型(OLS)

OLS回归: Y i = β 0 + β 1 ∗ X 1 i + ϵ i Y_i = \beta_0 + \beta_1*X_{1i} + \epsilon_i Yi=β0+β1X1i+ϵi
Y的取值可能为[0,1]之间的小数,也可能为>1或<0的数。而原数据只有0和1两种情况,不符常理。

2.3.2 线性回归模型

若构建线性回归, P i = β 0 + β 1 ∗ X 1 i P_i = \beta_0 + \beta_1*X_{1i} Pi=β0+β1X1i
P(Y = 1)的范围是[0,1],而X变量的范围(-∞,+∞),等号两侧是不匹配的。
在这里插入图片描述

2.3.3 逻辑回归模型

2.3.3.1优势比(Odd Ratios)

优势比 = 事件发生的概率/事件不发生的概率,即 O d d s = P e v e n t 1 − P e v e n t Odds = \frac{P_{event}}{1 - P_{event}} Odds=1PeventPevent

原本P(概率)的范围为(0,1),经过优势比(Odds Ratios),P的范围变为(-∞,+∞),Odds的值域[0,+∞)

2.3.3.2 逻辑回归公式

逻辑回归公式1
l o g i t ( p i ) = β 0 + β 1 ∗ X 1 i + . . . + β k ∗ X k i logit(p_i) = \beta_0 + \beta_1*X_{1i} + ... + \beta_k*X_{ki} logit(pi)=β0+β1X1i+...+βkXki
l o g i t ( p i ) logit(p_i) logit(pi):事件发生概率的logit
β 0 \beta_0 β0:回归式的截距
β k \beta_k βk:第k个预测变量的参数估计

逻辑回归公式2
l o g i t ( p i ) = l n ( p i 1 − p i ) logit(p_i) = ln(\frac{p_i}{1 - p_i}) logit(pi)=ln(1pipi)
logit:是Odds的自然对数
i:是所有案例(观察值)
p i p_i pi:在第i个案例中一个事件发生的概率
ln:自然对数(底数为e)

逻辑回归总公式
l n ( p i 1 − p i ) = β 0 + β 1 ∗ X 1 i + . . . + β k ∗ X k i ln(\frac{p_i}{1 - p_i}) = \beta_0 + \beta_1*X_{1i} + ... + \beta_k*X_{ki} ln(1pipi)=β0+β1X1i+...+βkXki

在这里插入图片描述
:逻辑回归可以反求出概率

3.逻辑回归建模

3.1 划分训练集和测试集

- 1.数据分为训练集(70%)和测试集(30%)
train = accepts.sample(frac=0.7, random_state=1234).copy()
test = accepts[~ accepts.index.isin(train.index)].copy()  #~表示否定
print(' 训练集样本量: %i \n 测试集样本量: %i' %(len(train), len(test)))

在这里插入图片描述

3.2 建立回归模型

根据下图,回归模型中红线上面的内容没有实际意义,红线下面是变量每个水平的估计系数,这里的“估计”等同于回归结果。

- 2.建立回归模型
import statsmodels.formula.api as smf
# family:族,伯努利分布族(0-1分布)
# 连接函数(link)为logit或probit
lg = smf.glm('bad_ind ~ age_oldest_tr', data=train, 
             family=sm.families.Binomial(sm.families.links.logit)).fit()
lg.summary()

在这里插入图片描述
模型解释
intercept:截距项
age_oldest_tr(即X):只跟logit有关,历史账户存续时间每增加一个单位,违约的logit会下降0.0057个单位

3.3 模型进行预测

根据公式 P = 1 1 + e − ( β 0 + β 1 ∗ X ) P = \frac{1}{1 + e^{-(\beta_0 + \beta_1*X)}} P=1+e(β0+β1X)1,可以预测得到P值(每个样本违约的预测)。

- 3.作预测
# 基于训练集的预测
train['proba'] = lg.predict(train)
# 基于测试集的预测
test['proba'] = lg.predict(test)
# 测试集的预测
test['proba'].head(10)

在这里插入图片描述

4. 模型评估

模型评估最重要的指标:成对比较

4.1 成对比较

  • 1.一致对:模型预测和实际结果一致

在最久账号存续时间和客户履约正相关,客户A履约20个月后违约,客户B履约36个月,账户时长越长,违约概率越小,履约概率越大。
在这里插入图片描述

  • 2.不一致对:模型预测和实际结果不一致
    客户A履约20个月后违约,客户B 履约10个月,得到的是A履约的概率大于B履约的概率。
    在这里插入图片描述

  • 3.相等对:X的取值一样,Y的取值不一样
    客户A履约1个月,客户B履约1个月后违约,两客户履约的概率相等。
    在这里插入图片描述

  • 4.成对比较的结果(SAS提供)
    在这里插入图片描述
    c的结果很重要,因为python的statmodels中不提供,所以采用ROC曲线完成。

4.2 ROC曲线面积

AUC = C统计量(SAS)
在这里插入图片描述

  • 1.绘制ROC曲线
import sklearn.metrics as metrics
#测试集中真实的Y值和测试集中Y的概率,并返回三个值
fpr_test, tpr_test, th_test = metrics.roc_curve(test.bad_ind, test.proba)

# 训练集真实的Y值和训练集Y的概率作散点图
fpr_train, tpr_train, th_train = metrics.roc_curve(train.bad_ind, train.proba)
plt.figure(figsize=[3, 3])
plt.plot(fpr_test, tpr_test, 'b--')
plt.plot(fpr_train, tpr_train, 'r-')
plt.title('ROC curve')
plt.show()

在这里插入图片描述

  • 2.计算曲线面积
- AUC面积范围[0.5,1],面积越大越好
print('AUC = %.4f' %metrics.auc(fpr_test,tpr_test))

Out[]: AUC = 0.6541

4.3 混淆矩阵

混淆矩阵:给定一个阈值,就可以做出一个混淆矩阵

混淆矩阵打分值合计
反应(预测=1)未反应(预测=0)
真实结果呈现信号(真实=1)A(击中)B(漏报)A+B
未呈现信号(真实=0)C(虚报)D(正确否定)C+D
合计A+CB+DA+B+C+D
  • 正确率 = (A+D)/(A+B+C+D):只有样本模型是1:1时才可用
  • 灵敏度(recall) = A/(A+B):实际违约人中,模型预测出了多少
  • 命中率(PV+) = A/(A+C):预测违约的人中,有多少人是真正的违约
  • 特异度 = D/(C+D):特异度越高越好
  • 负命中率 = D/(D+B)

步骤一:预测情况

- 可以根据Y的预测情况,大于0.3的为1,小于0.3的为0
test['prediction'] = (test['proba']>0.3).astype('int')
test['prediction']

在这里插入图片描述
步骤二:混淆矩阵

pd.crosstab(test.bad_ind,test.prediction,margins=True)

在这里插入图片描述
步骤三:根据混淆矩阵计算准确度

Int[]:acc = sum(test['prediction'] == test['bad_ind']) /np.float(len(test))
	  print('The accurancy is %.2f' %acc)

Out[]:The accurancy is 0.78
  • 计算
- 精确度:A/A+B
- 召回率:A/A+C
- 特异度:D/C+D
for i in np.arange(0.02, 0.3, 0.02):              # 阈值0.02 - 0.3  步长0.02
    prediction = (test['proba'] > i).astype('int')
    confusion_matrix = pd.crosstab(test.bad_ind,prediction,
                                   margins = True)
    if i == 0.02:
        precision = 0
        recall = confusion_matrix.iloc[0,0] / confusion_matrix.iloc[2, 0]
        Specificity = 0
        f1_score = 2 * (precision * recall) / (precision + recall)
    else: 
        precision = confusion_matrix.iloc[0,0] / confusion_matrix.iloc[0, 2]
        recall = confusion_matrix.iloc[0,0] / confusion_matrix.iloc[2, 0]
        Specificity = confusion_matrix.iloc[1,1] / confusion_matrix.iloc[1,2]
        f1_score = 2 * (precision * recall) / (precision + recall)
    print('threshold: %s, precision: %.2f, recall:%.2f ,Specificity:%.2f , f1_score:%.2f'%(i, precision, recall, Specificity,f1_score))

在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值