利用R语言对贷款客户作风险评估(下)——零膨胀回归分析

利用R语言对贷款客户作风险评估(下)——零膨胀回归分析

前言

上一篇的分类预测是决定好坏客户的初步判断, 不足以直接决策, 因此还需要进一步分析. 通过随机森林, 对影响好坏客户的解释变量的重要性进行排序. 由结果可以得出, 六个月内的还款状态是决定客户是非为好客户的最为重要的影响因素.因此, 本部分将由六个月的还款状态产生新的新的因变量, 即逾期还款次数, 其他变量作为解释变量, 从而研究影响逾期还款次数的因素.

初步分析

将数据中的6个月的还款状态做合并处理得到新的因变量逾期还款次数, 并删除还款状态6个解释变量;再将因子变量性别、教育程度和婚姻转化为哑变量. 由此得到20个解释变量, 1个计数因变量的数据. 因变量。逾期还款次数的计数分布如图, 计数分布不均衡, 零计数所占的比例为66.44%.
在这里插入图片描述
先使用传统的计数分布模型对数据进行拟合数据, 然后与简单线性回归做比较.为了比较模型, 将全部数据按因变量分层抽样抽取5份, 使得每份样本中因变量的分布均匀, 然后采用5折交叉验证得到模型的测试集和训练集的拟合结果. 模型的拟合结果如表:
结果表明, 虽然线性回归模型理论上并不适用, 其结果优于泊松回归和负二项回归, 表明传统的计数分布模型不如简单的线性回归有效。零点观测的比例较大, 远远超过了poisson分布中零值的概率分布所允许的范围. 当事件发生数中含有大量的零值, 我们把这种现象称为零膨胀现象, 并且这一类特殊的计数数据广泛的存在于自然、社会科学的实际研究中.

零膨胀数据

由于零事件所占比例过高, 传统模型的预测能力不足以解决, 将会导致有偏的统计推断结果, 所以需要找到适合的模型用来拟合这一类计数数据。
零膨胀模型, 由取值为零的计数数据和取值服从某特殊分布的计数数据各占一定比例组成的混合分布, 然后分别建立logit回归模型和一般的计数回归模型. 其中,logit 回归模型拟合的是解释变量与事件发生与否的关系, 而计数回归模型拟合的是解释变量与事件发生次数的关系。在这里插入图片描述
在这里插入图片描述
实现的R代码如下:

library(pscl)
library(MASS)
card=read.csv("card.csv")
card[,-c(2,3,16:21)]<-scale(card[,-c(2,3,16:21)])#标准化
library(ggplot2)
tx<-ggplot(data=card,mapping=aes(x=yqcs))+geom_bar(stat='count',fill ='pink',colour = 'grey')

fit1<-glm(yqcs~.,family="poisson",data=card,control=list(maxit=1000))
summary(fit1)

fit2=lm(yqcs~.,data=card)
summary(fit2)
#library(arm) 
#bayesglm(yqcs~.,family="poisson",data=card)

#负二项回归
fit3<-glm(yqcs~., family = negative.binomial(theta=1),data=card) 

#过度离势检验
mean(card$yqcs) #0.8342
var(card$yqcs)  #2.415858
library(qcc)
qcc.overdispersion.test(card$yqcs,type="poisson")

#ZIP回归
library(pscl)
fit4<-zeroinfl(yqcs~.|.,card)
fit5<-zeroinfl(yqcs~.|.,card,EM=TRUE)
summary(fit4)


#zip结果有两部分:计数模型--泊松回归;零膨胀模型
#检验两个模型的参数都具有统计意义,即含有预测变量的模型优于null
#模型,可以用lmtest()检验(似然比检验)。
library(zoo)
library(lmtest)
lrtest(fit4)#卡方值为6357.6,自由度为40,对应的P值为2.2e-16<0.0001
#说明模型具有统计显著性

#但是以上的检验没有给出与传统的泊松回归模型相比,零膨胀模型是否有改进
#检验zip优于poisson
vuong(fit1,fit4)

fit0<-hurdle(yqcs~.|., data=card,dist="poisson")
summary(fit0)
lglk0<-fit0$loglik#df=42

#####分割训练集和测试集 ,用NMSE比较模型
##(1)留出法:按照Y进行分层抽样,可以保证训练集和测试集中Y的比例是一致的
library(caret)
set.seed(123)
table(card$yqcs)
table(card$yqcs)/nrow(card)#应变量各个水平的比例
index=createFolds(card$yqcs,k=5,list=FALSE)
mse0<-rep(0,5)
mse<-rep(0,5)

#泊松回归
for(i in 1:5){
  train<-card[-which(index==i),]
  test<-card[which(index==i),]
  a=glm(yqcs~.,family="poisson",data=train)
  y0=predict(a,train)#对训练集预测
  y1=predict(a,test)#对测试集预测
  mse0[i]=mean((train[,21]-y0)^2)/mean((train[,21]-mean(train[,21]))^2)
  mse[i]=mean((test[,21]-y1)^2)/mean((test[,21]-mean(test[,21]))^2)
}
nmse01<-mean(mse0)#2.712316
nmse1<-mean(mse)#2.745967

#负二项分布
for(i in 1:5){
  train<-card[-which(index==i),]
  test<-card[which(index==i),]
  a<-glm(yqcs~., family = negative.binomial(theta=1),data=train)
  y0=predict(a,train)#对训练集预测
  y1=predict(a,test)#对测试集预测
  mse0[i]=mean((train[,21]-y0)^2)/mean((train[,21]-mean(train[,21]))^2)
  mse[i]=mean((test[,21]-y1)^2)/mean((test[,21]-mean(test[,21]))^2)
}
nmse02<-mean(mse0)#2.172339
nmse2<-mean(mse)#2.193163

#线性回归
for(i in 1:5){
  train<-card[-which(index==i),]
  test<-card[which(index==i),]
  a=lm(yqcs~.,data=train)
  y0=predict(a,train)#对训练集预测
  y1=predict(a,test)#对测试集预测
  mse0[i]=mean((train[,21]-y0)^2)/mean((train[,21]-mean(train[,21]))^2)
  mse[i]=mean((test[,21]-y1)^2)/mean((test[,21]-mean(test[,21]))^2)
}
nmse03<-mean(mse0)#0.9061491
nmse3<-mean(mse)#0.9093126
#a<-glm(yqcs~., family = negative.binomial(theta=1),data=card)


#ZIP回归
for(i in 1:5){
  train<-card[-which(index==i),]
  test<-card[which(index==i),]
  a<-zeroinfl(yqcs~.|.,train)
  y0=predict(a,train)#对训练集预测
  y1=predict(a,test)#对测试集预测
  mse0[i]=mean((train[,21]-y0)^2)/mean((train[,21]-mean(train[,21]))^2)
  mse[i]=mean((test[,21]-y1)^2)/mean((test[,21]-mean(test[,21]))^2)
}
nmse05<-mean(mse0)#0.8282108
nmse5<-mean(mse)#0.8308125

#ZINB回归
for(i in 1:5){
  train<-card[-which(index==i),]
  test<-card[which(index==i),]
  a<-zeroinfl(yqcs~.|.,train,dist = "negbin")
  y0=predict(a,train)#对训练集预测
  y1=predict(a,test)#对测试集预测
  mse0[i]=mean((train[,21]-y0)^2)/mean((train[,21]-mean(train[,21]))^2)
  mse[i]=mean((test[,21]-y1)^2)/mean((test[,21]-mean(test[,21]))^2)
}
nmse05<-mean(mse0)#0.8354855
nmse5<-mean(mse)#0.836005
  • 6
    点赞
  • 54
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1. 导入必要的库和数据 首先,我们需要导入必要的库和数据。在这里,我们使用的是scikit-learn内置的贷款违约数据集。 ```python import pandas as pd from sklearn.linear_model import LogisticRegression from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score # 导入数据集 data = pd.read_csv('https://raw.githubusercontent.com/jbrownlee/Datasets/master/german.csv', header=None) # 设置列名 data.columns = ['checking_account', 'duration', 'credit_history', 'purpose', 'credit_amount', 'savings_account', 'employment', 'installment_rate', 'personal_status', 'other_debtors', 'residence_since', 'property', 'age', 'other_installment_plans', 'housing', 'existing_credits', 'job', 'num_dependents', 'own_telephone', 'foreign_worker', 'class'] # 查看前5行数据 print(data.head()) ``` 输出: ``` checking_account duration credit_history purpose credit_amount \ 0 A11 6 A34 A43 1169 1 A12 48 A32 A43 5951 2 A14 12 A34 A46 2096 3 A11 42 A32 A42 7882 4 A11 24 A33 A40 4870 savings_account employment installment_rate personal_status other_debtors \ 0 A65 A75 4 A93 A101 1 A61 A73 2 A92 A101 2 A61 A74 2 A93 A101 3 A61 A74 2 A93 A103 4 A61 A73 3 A93 A101 ... property age other_installment_plans housing existing_credits job \ 0 ... A121 67 A143 A152 2 A173 1 ... A121 22 A143 A152 1 A173 2 ... A121 49 A143 A152 1 A172 3 ... A122 45 A143 A153 1 A173 4 ... A124 53 A143 A153 2 A173 num_dependents own_telephone foreign_worker class 0 1 A192 A201 1 1 1 A191 A201 2 2 2 A191 A201 1 3 2 A191 A201 1 4 2 A191 A201 2 [5 rows x 21 columns] ``` 2. 数据预处理 接下来,我们需要对数据进行预处理,包括将分类变量进行编码、将样本分为训练集和测试集等。 ```python # 将分类变量进行编码 data = pd.get_dummies(data, columns=['checking_account', 'credit_history', 'purpose', 'savings_account', 'employment', 'personal_status', 'other_debtors', 'property', 'other_installment_plans', 'housing', 'job', 'own_telephone', 'foreign_worker']) # 将类别变量class转换为0和1 data['class'] = data['class'].apply(lambda x: 0 if x == 2 else 1) # 将数据集分为训练集和测试集 X_train, X_test, y_train, y_test = train_test_split(data.drop('class', axis=1), data['class'], test_size=0.2, random_state=42) ``` 3. 训练模型 接下来,我们使用逻辑回归模型对贷款人的违约风险进行分类。我们使用scikit-learn的LogisticRegression类。 ```python # 训练模型 model = LogisticRegression() model.fit(X_train, y_train) ``` 4. 预测并评估模型 最后,我们使用测试集对模型进行评估,并计算模型的准确性。 ```python # 预测并评估模型 y_pred = model.predict(X_test) accuracy = accuracy_score(y_test, y_pred) print('Accuracy:', accuracy) ``` 输出: ``` Accuracy: 0.775 ``` 这意味着我们的模型可以正确地分类贷款人的违约风险约77.5%的时间。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值