前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >评分卡模型开发-主标尺设计及模型验证

评分卡模型开发-主标尺设计及模型验证

作者头像
Erin
发布2018-01-09 10:53:44
1.7K0
发布2018-01-09 10:53:44
举报
文章被收录于专栏:大数据风控大数据风控

上一步中开发的信用风险评分卡模型,得到的是不同风险等级客户对应的分数,我们还需要将分数与违约概率和评级符号联系起来,以便差异化管理证券公司各面临信用风险敞口的客户,这就需要对证券公司各面临信用风险敞口业务中的个人客户开发一个一致的主标尺。最容易理解、最容易操作的方式就是根据违约概率从低到高分为不同的区间,这就相当于把违约概率这把尺子标上刻度,用这把尺子可以把证券公司需承担信用风险敞口的不同业务中的个人客户划分到不同的信用等级,这样各项业务中个人客户的信用等级分布差异、信用风险分布高低,就可以一目了然地展现出来了。这种违约概率和信用等级之间的映射关系就称为主尺标。

由逻辑回归方程原理的分析可知,客户的违约概率p=Odds/(1+Odds),由式 Score=A-Blog(Odds)中得分与违约概率和Odds之间的对应关系,我们可计算出客户得分对应的违约概率。

由信用风险标准评分卡可知,该评分卡的最高分是89分,最低分是-41分。因此,我们可以计算出该评分卡所有得分范围对应的违约概率:

这里写图片描述
这里写图片描述

根据表3.22的结果可见,我们可简单地将每10分对应一个信用等级,并用每相邻得分对应的违约概率(这种方法计算得出的违约概率只能用作风险排序,而不是客户的真实违约概率)的算术平均值作为该信用风险等级对应的平均违约概率,得到最终的主尺标及其内部信用等级对照表3.23:

这里写图片描述
这里写图片描述

在主标尺和内部信用等级确定后,接下来我们需要进行模型的区分能力、预测准确度和稳定性等模型的验证工作了。回顾模型开发的过程,在模型开发时我们采用随机抽样的方法将数据分为样本集和测试集,并用样本集开发模型,用测试集做模型验证。因此,做模型验证时,我们应当首先用开发好的模型对测试集中的每一个样本评级一遍,并根据评级结果来计算模型的区分能力和预测准确度。 用已开发好的模型对测试集中所有样本重新评级一遍的代码如下:

代码语言:javascript
复制
tmp1<-test_kfolddata[,-21]
credit_risk1<-ifelse(test_kfolddata[,"credit_risk"]=="good",0,1)
data_tmp<-as.matrix(cbind(tmp1,credit_risk1))
##降维purpose(对测试集中的样本做同样的降维处理)##
for(i in 1:nrow(data_tmp))
{
  #合并car(new)、car(used)
  if(as.character(data_tmp[i,"purpose"])=="car (new)")  
  {
    data_tmp[i,"purpose"]<-as.character("car(new/used)")
  }
  if(as.character(data_tmp[i,"purpose"])=="car (used)")
  {
    data_tmp[i,"purpose"]<-as.character("car(new/used)")
  }
  #合并radio/television、furniture/equipment
  if(as.character(data_tmp[i,"purpose"])=="radio/television") 
  {
    data_tmp[i,"purpose"]<-as.character("radio/television/furniture/equipment")
  }
  if(as.character(data_tmp[i,"purpose"])=="furniture/equipment")
  {
    data_tmp[i,"purpose"]<-as.character("radio/television/furniture/equipment")
  }
  #合并others、repairs、business
  if(as.character(data_tmp[i,"purpose"])=="others")
  {
    data_tmp[i,"purpose"]<-as.character("others/repairs/business")
  }
  if(as.character(data_tmp[i,"purpose"])=="repairs")
  {
    data_tmp[i,"purpose"]<-as.character("others/repairs/business")
  }
  if(as.character(data_tmp[i,"purpose"])=="business")
  {
    data_tmp[i,"purpose"]<-as.character("others/repairs/business")
  }
  #合并retraining、education
  if(as.character(data_tmp[i,"purpose"])=="retraining")
  {
    data_tmp[i,"purpose"]<-as.character("retraining/education")
  }
  if(as.character(data_tmp[i,"purpose"])=="education")
  {
    data_tmp[i,"purpose"]<-as.character("retraining/education")
  }
}
##purpose变量降维结束##
###用R代码实现打分卡模型###
data1<-as.data.frame(data_tmp)
tot<-nrow(data1)
score<-list()
for(i in 1:tot)
{
  lst<-as.matrix(data1[i,])
  #duration
  score_duration<-NA
  if(lst[,"duration"]<=8)
  {
    score_duration<-14
  }else
  if(lst[,"duration"]>8&lst[,"duration"]<=33)
  {
    score_duration<-1
  }else
  if(lst[,"duration"]>33)
  {
    score_duration<--7
  }
  #amount
  score_amount<-NA
  if(lst[,"amount"]<=3913)
  {
    score_amount<-3
  }else
    if(lst[,"amount"]>3913&lst[,"amount"]<=9283)
    {
      score_amount<--5
    }else
      if(lst[,"amount"]>9283)
      {
        score_amount<--14
      }
  #age
  score_age<-NA
  if(lst[,"age"]<=34)
  {
    score_age<--2
  }else
    if(lst[,"age"]>34)
    {
      score_age<-3
    }
  #installment_rate
  score_installment_rate<-NA
  if(lst[,"installment_rate"]==1)
  {
    score_installment_rate<-2
  }else
    if(lst[,"installment_rate"]==2)
    {
      score_installment_rate<-5
    }else
      if(lst[,"installment_rate"]==3)
      {
        score_installment_rate<--1
      }else
        if(lst[,"installment_rate"]==4)
        {
          score_installment_rate<--6
        }
  #status
  score_status<-NA
    if(lst[,"status"]=="... < 100 DM")
    {
      score_status<--10
    }else
      if(lst[,"status"]=="0 <= ... < 200 DM")
      {
        score_status<--5
      }else
      if(lst[,"status"]=="... >= 200 DM / salary for at least 1 year")
      {
        score_status<-5
      }else
        if(lst[,"status"]=="no checking account")
        {
          score_status<-14
        }
  #credit_history
  score_credit_history<-NA
  if(lst[,"credit_history"]=="critical account/other credits existing")
  {
    score_credit_history<-8
  }else
    if(lst[,"credit_history"]=="existing credits paid back duly till now")
    {
      score_credit_history<--1
    }else
      if(lst[,"credit_history"]=="all credits at this bank paid back duly")
      {
        score_credit_history<--10
      }else
        if(lst[,"credit_history"]=="delay in paying off in the past")
        {
          score_credit_history<-0
        }else
          if(lst[,"credit_history"]=="no credits taken/all credits paid back duly")
          {
            score_credit_history<--16
          }
  #savings
  score_savings<-NA
  if(lst[,"savings"]=="... < 100 DM")
  {
    score_savings<--3
  }else
    if(lst[,"savings"]=="... >= 1000 DM")
    {
      score_savings<-13
    }else
      if(lst[,"savings"]=="500 <= ... < 1000 DM")
      {
        score_savings<-9
      }else
        if(lst[,"savings"]=="unknown/no savings account")
        {
          score_savings<-9
        }else
          if(lst[,"savings"]=="100 <= ... < 500 DM")
          {
            score_savings<--2
          }
  #property
  score_property<-NA
  if(lst[,"property"]=="unknown/no property")
  {
    score_property<--4
  }else
    if(lst[,"property"]=="real estate")
    {
      score_property<-3
    }else
      if(lst[,"property"]=="building society savings agreement/life insurance")
      {
        score_property<--1
      }else
        if(lst[,"property"]=="car or other")
        {
          score_property<-1
        }
  #purpose
  score_purpose<-NA
  if(lst[,"purpose"]=="domestic appliances")
  {
    score_purpose<-6
  }else
    if(lst[,"purpose"]=="radio/television/furniture/equipment")
    {
      score_purpose<--3
    }else
      if(lst[,"purpose"]=="car(new/used)")
      {
        score_purpose<--1
      }else
        if(lst[,"purpose"]=="retraining/education")
        {
          score_purpose<--5
        }else
          if(lst[,"purpose"]=="others/repairs/business")
          {
            score_purpose<--1
          }
  score[i]<-sum(20,score_duration,score_amount,score_age,score_installment_rate,
                score_status,score_credit_history,score_savings,
                score_property,score_purpose)
  rm(lst)
}
###用R代码实现打分卡模型结束###
#合并处理测试集样本得分,并输出到指定的CSV文件中#
score_M<-as.matrix(score,ncol=1)
score_data<-cbind(data1,score_M)
score_risk<-score_data[,c("credit_risk1","score_M")]
write.csv(as.matrix(score_risk),"C:/Users/ZL/Desktop/creditcard_model/2.csv")

从理论上说,信用评级无法给出主体是否违约的判断,只能给出主体违约的概率,而评级符号对应的就是主体发生违约的平均违约概率。但对评级结果的实际应用中,实在存在评级结果是否“准确”的质疑。那么,通常情况下如果某主体被评级为投资级(BBB及以上),但发生了违约,则被认为“不准确”或者“误判”。如果某主体被评级为投机级(BB及以下),且发生了违约,则被认为“预测准确”。如果被评级为投机级的主体没发生违约事件(并不是每个被评级为投机级的主体都会发生违约),则可以用概率去解释,那就是“大概率事件并不一定发生,小概率事件也并不一定不发生”。 我们采用ROC作为模型区分能力的验证指标,采用AR(accuracy ratio,准确率)作为模型预测准确性的验证指标,并且两者存在AR=2×ROC-1的关系式。验证模型的稳定性需要多年的历史数据,由于数据原因此处略去。

由内部等级与主尺标的对应关系可知,投资级和投机级的分界点为20分,即大于20分的主体发生发生了违约,我们认为是“误判”,小于20分的主体为发生违约,我们也认为是“误判”。则经统计图 中的数据可知,误判的主体总数为50个,则AR=1-50/200=0.75,此时ROC=(1+AR)/2=0.875。此时模型的预测准确度和区分能力均达到了较好地要求,可以进行部署使用。

上述模型的验证方法采用的是将测试样本集中的所有样本在生成的评分卡中全部评级一遍的方法,当然也可以采用直接将WOE变量的逻辑回归方程作为评级模型的方法。此时,也需要将测试样本集中的所有入模变量计算其WOE,并代入上述逻辑回归方程。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017年08月03日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档