評分卡建模學習

評分卡模型 Credit card

1. 模型理論知識

金融行業常用的評分卡模型流程圖:
在這裏插入圖片描述

1.1 數據準備

數據源主要包含行內行外兩部分:行內的有客戶的基礎人口統計特徵數據、交易歷史數據、信用歷史數據等;外部數據有人行徵信數據、第三方徵信機構數據及社交行爲數據等。
人行徵信在中小型企業中的徵信檢測效果比較好

1.2 數據探索

對獲得的原始數據進行進一步的探索

  1. 觀察樣本的總體分佈情況,正負樣本是否均衡?
    –不均衡樣本的處理方法:從數據角度、從算法角度、代價敏感學習
  2. 單變量分佈是否滿足正態分佈?
  3. 變量的缺失情況?
    –缺失值處理方法:整列刪除、衆數填充
  4. 是否有異常值?
    –箱線圖觀察、woe變換可以消除異常值影響
  5. 變量間的共線性情況如何,評分卡模型主要是使用邏輯迴歸算法進行建模,要求變量間共線性儘可能低。
    –熱力圖觀察變量間共線性
  6. 變量規模
    一切就緒後,確定模型的觀察期和表現期,確定數據集分割方法,劃分訓練集和測試集。
  7. 確定壞用戶的標準?–逾期多久算違約

1.3 數據預處理

主要工作包括數據清洗、缺失值處理、異常值處理、數據標準化等,主要目的是將獲取的原始數據轉變成可用於建模的結構化數據。
1. 離散型變量處理方式:無序類別變量、有序類別變量
2. 連續型變量處理方式:分箱

1.4 模型建立

在信用評分卡中一般使用邏輯迴歸作爲主要的模型。
過程主要包括變量分箱、變量的WOE(證據權重)變換和變量選擇(IV值)、邏輯迴歸估算。

(1)類別變量根據類別直接進行WOE變換,連續變量要先進行變量分箱再進行WOE變換。
(2)特徵處理階段主要有兩個概念:WOE和IV。
1.分箱——將連續變量離散化,或者將具有很多狀態的離散變量合併成少狀態
2.分箱的優勢:
-對異常值不敏感,如年齡300歲;
-降低模型過擬合風險;
-可以學習到樣本的非線性信息?
3.分箱方法:
無監督:等寬、等頻、聚類(k-means)
有監督:卡方分箱法、單變量決策樹算法(ID3、C4.5、CART)、IV最大化分箱法、best-ks分箱法
creportgen.utils.discretization
4.卡方分箱算法:
卡方分箱是自底向上的(即基於合併的)數據離散化方法。具有最小卡方值的相鄰區間合併在一起,直到滿足確定的停止準則。

4.1基本思想:對於精確的離散化,相對類頻率在一個區間內應當完全一致。因此,如果兩個相鄰的區間具有非常類似的類分佈,則這兩個區間可以合併;否則,它們應當保持分開。而低卡方值表明它們具有相似的類分佈。

4.2分箱步驟:
1)設定卡方閾值
2)根據要離散的屬性值對實例進行排序
3)計算每一對相鄰區間的卡方值
4)將卡方值最小的一對區間進行合併
5)重複3)4)兩步直至滿足停止條件
在這裏插入圖片描述
停止條件有如下兩種選擇:
(1)分箱個數:限制最終的分箱個數結果,每次將樣本中具有最小卡方值的 區間與相鄰的最小卡方區間進行合併,直到分箱個數達到限制條件爲止。
(2)卡方閾值:根據自由度和顯著性水平得到對應的卡方閾值,如果分箱的各區間最小卡方值小於卡方閾值,則繼續合併,直到最小卡方值超過設定閾值爲止。

4.3卡方閾值的確定: 根據顯著性水平和自由度得到卡方值 ,卡方閾值的自由度爲 分箱數-1,顯著性水平可以取10%,5%或1%。
例如:有3類,自由度爲2,則90%置信度(10%顯著性水平)下,卡方的值爲4.6。

4.4閾值的意義
類別和屬性獨立時,有90%的可能性,計算得到的卡方值會小於4.6。 大於閾值4.6的卡方值就說明屬性和類不是相互獨立的,不能合併。如果閾值選的大,區間合併就會進行很多次,離散後的區間數量少、區間大。
5.分箱後檢驗Bad Rate單調性
Bad Rate:壞樣本率,指的是將特徵進行分箱之後,每個bin下的樣本所統計得到的壞樣本率
bad rate 單調性與不同的特徵場景:
在評分卡模型中,對於比較嚴格的評分模型,會要求連續性變量和有序性的變量在經過分箱後需要保證bad rate的單調性。

  1. 連續性變量:
    在嚴格的評分卡模型中,對於連續型變量就需要滿足分箱後 所有的bin的 bad rate 要滿足單調性,只有滿足單調新的情況下,才能進行後續的WOE編碼
  2. 離散型變量:
    離散化程度高,且無序的變量:
    比如省份,職業等,我們會根據每個省份信息統計得到bad rate 數值對原始省份信息進行編碼,這樣就轉化爲了連續性變 量,進行後續的分箱操作,對於經過bad rate編碼後的特徵數據,天然單調。
    只有當分箱後的所有的bin的bad rate 呈現單調性,纔可以進行下一步的WOE編碼。
    離散化程度低,且無序的變量:
    比如婚姻狀況,只有四五個狀態值,因此就不需要專門進行bad rate數值編碼,只要求出每個離散值對應的bin的bad rate比例是否出現0或者1的情況,若出現說明正負樣本的分佈存在極端情況,需要對該bin與其他bin進行合併, 合併過程完了之後 就可以直接進行後續的WOE編碼
    有序的離散變量:
    對於學歷這種情況,存在着小學,初中,高中,本科,碩士,博士等幾種情況,而且從業務角度來說 這些離散值是有序的, 因此我們在分箱的時候,必須保證bin之間的有序性,再根據bad rate 是否爲0 或者1的情況 決定是否進行合併,最終將合併的結果進行WOE編碼

因此bad rate單調性只在連續性數值變量和有序性離散變量分箱的過程中會考慮。

bad rate要求單調性的原因分析:

  1. 邏輯迴歸模型本身不要求特徵對目標變量的單調性。之所以要求分箱後單調,主要是從業務角度考慮,解釋、使用起來方便一點。如果有某個(分箱後的)特徵對目標變量不單調,會加劇模型解釋型的複雜化
  2. 對於像年齡這種特徵,其對目標變量往往是一個U型或倒U型的分佈,有些公司/部門/團隊是允許變量的bad rate呈(倒)U型的。

5.WOE變換

在這裏插入圖片描述
其中,pyi是這個組中壞客戶(此處風險模型中判別的是好壞客戶)佔所有樣本中所有壞客戶的比例,pni是這個組中好客戶佔樣本中所有好客戶的比例,#yi是這個組中壞客戶的數量,#ni是這個組中好客戶的數量,#yT是樣本中所有壞客戶的數量,#nT是樣本中所有好客戶的數量。

  WOE表示的實際上是“當前分組中壞客戶佔所有壞客戶的比例”和“當前分組中好客戶佔所有好客戶的比例”的差異。WOE也可以這麼理解,他表示的是當前這個組中壞客戶和好客戶的比值,和所有樣本中這個比值的差異。這個差異是用這兩個比值的比值,再取對數來表示的。WOE越大,這種差異越大,這個分組裏的樣本是壞客戶的可能性就越大,WOE越小,差異越小,這個分組裏的樣本是壞客戶的可能性就越小。
  sklearn.reportgen.utils.weightOfEvidence

6.IV值計算
計算公式如下:
在這裏插入圖片描述
有了一個變量各分組的IV值,我們就可以計算整個變量的IV值,方法很簡單,就是把各分組的IV相加:
在這裏插入圖片描述
其中,n爲變量分組個數。
IV的特點:
a、對於變量的一個分組,這個分組的好用戶和壞用戶的比例與樣本整體響應和未響應的比例相差越大,IV值越大,否則,IV值越小;
b、極端情況下,當前分組的好用戶和壞用戶的比例和樣本整體的好用戶和壞用戶的比例相等時,IV值爲0;
c、IV值的取值範圍是[0,+∞),且,噹噹前分組中只包含好用戶或者壞用戶時,IV = +∞。
使用IV其實有一個缺點,就是不能自動處理變量的分組中出現響應比例爲0或100%的情況。那麼,遇到響應比例爲0或者100%的情況,我們應該怎麼做呢?建議如下:

(1)如果可能,直接把這個分組做成一個規則,作爲模型的前置條件或補充條件;
(2)重新對變量進行離散化或分組,使每個分組的響應比例都不爲0且不爲100%,尤其是當一個分組個體數很小時(比如小於100個),強烈建議這樣做,因爲本身把一個分組個體數弄得很小就不是太合理。
(3)如果上面兩種方法都無法使用,建議人工把該分組的響應數和非響應的數量進行一定的調整。如果響應數原本爲0,可以人工調整響應數爲1,如果非響應數原本爲0,可以人工調整非響應數爲1.
IV值判斷變量預測能力的標準
< 0.02: unpredictive,0.02 to 0.1: weak,0.1 to 0.3: medium,0.3 to 0.5: strong,>0.5: suspicious,一般選取大於0.02的

2.R語言實現

信用評分是指根據客戶的信用歷史資料,利用一定的信用評分模型,得到不同等級的信用分數。
根據客戶的信用分數,授信者可以分享客戶按時還款的可能性。據此,授信者可以決定是否准予
授信以及授信的額度和利潤。
首先,使用logistic和NaiveBayes建模 本文中建模所用到的數據是關於德國公民的信用相關數據,接下來我們針對這個數據集進行模型。

library(ggplot2)
library(klaR)
library(sqldf)
german_credit = read.csv('/Users/Desktop/german_credit.csv',stringsAsFactors = TRUE)
str(german_credit)

數據中的字段主要包含信用(模型中的因變量1爲好客戶,0爲壞客戶),賬戶餘額,信用月數,貸款目的等。由於上面的數據大都都是數值型的,故需要根據實際情況將數值變量轉換成因子型變量。

for (i in 1:21) german_credit[,i]=as.factor(german_credit[,i])
#個別數據回到數值型
german_credit$Duration <- as.numeric(german_credit$Duration) 
german_credit$CreditAmount <- as.numeric(german_credit$CreditAmount)
german_credit$Age <- as.numeric(german_credit$Age)

根據好客戶,壞客戶劃分數據集

good=german_credit[german_credit$Creditability==1,]
bad=german_credit[german_credit$Creditability==0,]
a=colnames(german_credit)

爲了瞭解數據,我們對數據集中的各變量繪製條形圖,這裏僅以客戶的存款餘額爲例,如果想了解更多其他變量的分佈信息,可以稍作修改下方的代碼。

#整體用戶的存款餘額條形圖 AccountBalance在第二列
ggplot(german_credit,aes(german_credit[,2])) +   geom_bar(aes(fill = as.factor(german_credit[,2]))) +    scale_fill_discrete(name=a[2]) +    theme(axis.text.x=element_blank(),axis.ticks.x=element_blank()) +  
      labs(x= a[2],y= "Frequency" , title = "german_credit")
#好客戶的條形圖
ggplot(good,aes(good[,2])) +   geom_bar(aes(fill = as.factor(good[,2]))) +    scale_fill_discrete(name=a[2]) +    theme(axis.text.x=element_blank(),axis.ticks.x=element_blank()) +  
      labs(x= a[2],y= "Frequency" , title = "german_credit for good")
#壞客戶的條形圖
ggplot(bad,aes(bad[,2])) +   geom_bar(aes(fill = as.factor(bad[,2]))) +    scale_fill_discrete(name=a[2]) +    theme(axis.text.x=element_blank(),axis.ticks.x=element_blank()) +  
      labs(x= a[2],y= "Frequency" , title = "german_credit for bad")

數據集的劃分

set.seed(1)
index = sample(1:2,size=nrow(german_credit),replace = T,prob=c(0.7,0.3))
train_data=german_credit[index==1,]
test_data=german_credit[index==2,]
model1=glm(formula=train_data$Creditability~.,data=train_data,family='binomial',
           control = list(maxit = 100))
summary(model1)
#一開始不放maxit=100的時候說算法不收斂,不聚合,當數據不太好時,經過25次
#迭代可能還不收斂,所以要增大迭代次數。
#從模型結果來看,很多自變量都沒有通過顯著性檢驗,接下來利用逐步迴歸進行改進。
model2=step(object=model1,trace=0)
summary(model2)

經過逐步迴歸以後,模型的效果得到了一定的提升,留下了很多顯著的自變量,同時AIC信息也下降了很多。我們知道,通過logistic模型可以得到每個樣本的概率值prob,該概率值是可以根據實際的業務進行調整的,如果風控要求的比較嚴格,那麼就需要把prob的值調的更大。
下面對模型的效果做一個評估,使用混淆矩陣。

# 返回模型在測試集上的概率值
prob <- predict(object = model2, newdata= test_data, type = 'response')
# 根據閾值,將概率值分爲兩類
pred <- ifelse(prob >= 0.8, 'yes','no')
# 將pred變量設置爲因子
pred <- factor(pred, levels =c('no','yes'), order = TRUE)
#混淆矩陣
f <- table(test_data$Creditability, pred) 
f
(89+126)/(89+126+11+78)
pred2 <- ifelse(prob >= 0.5, 'yes','no')
pred2 <- factor(pred2, levels =c('no','yes'), order = TRUE)
#混淆矩陣
f2 <- table(test_data$Creditability, pred) 
f2
(40+186)/(40+186+78)

通過改變模型的閾值,模型的準確性有所提升。當然,我們還可以更換模型,根據實際的業務進行變量的篩選,這個過程會比較繁瑣。下面使用貝葉斯方法進行模型預測。

#貝葉斯模型
library(klaR)
model3=NaiveBayes(formula=Creditability~.,data=train_data)
#預測
pre=predict(model3,newdata=test_data)
#posterior存儲每個樣本爲壞客戶和好客戶的概率值
str(pre$posterior)
#將好客戶的概率閾值設爲0.8
pred <- ifelse(pre$posterior[,2] >= 0.8, 'yes','no') 
f <- table(test_data$Creditability, pred) 
f

同樣0.8的閾值,相比於logistic模型,貝葉斯效果更佳。
Score Card原理

  評分卡模型在國外是一種成熟的預測方法,尤其在信用風險評估以及金融風險控制領域更是得到了比較廣泛的使用,其原理是將模型變量離散化之後用WOE編碼,在建立模型。ScoreCard用IV值來篩選變量,而且ScoreCard輸出爲分值。

對IV的直觀理解

  IV的全稱是Information Value,中文意思是信息價值,或者信息量。從直觀邏輯上大體可以這樣理解“用IV去衡量變量預測能力”這件事情:我們假設在一個分類問題中,目標變量的類別有兩類:Y1,Y2。對於一個待預測的個體A,要判斷A屬於Y1還是Y2,我們是需要一定的信息的,假設這個信息總量是I,而這些所需要的信息,就蘊含在所有的自變量C1,C2,C3,……,Cn中,那麼,對於其中的一個變量Ci來說,其蘊含的信息越多,那麼它對於判斷A屬於Y1還是Y2的貢獻就越大,Ci的信息價值就越大,Ci的IV就越大,它就越應該進入到入模變量列表中。

參考鏈接https://blog.csdn.net/kMD8d5R/article/details/79005347

Naive Bayes 評分卡
首先需要對部分變量作重編碼的操作,這個操作在實際工作中需要不斷的調試才能得到比較理想的效果。


# 分箱
german_credit$Duration[german_credit$Duration > 40] <- '1'
german_credit$Duration[german_credit$Duration <= 40 & german_credit$Duration > 30] <- '2'
german_credit$Duration[german_credit$Duration<=30 & german_credit$Duration >20] <- '3'
german_credit$Duration[german_credit$Duration<=20] <- '4'
german_credit$Purpose[german_credit$Purpose==8] <- 1
german_credit$Purpose[german_credit$Purpose==10] <- 0
german_credit$Purpose[german_credit$Purpose==4] <- 3
german_credit$Purpose[german_credit$Purpose==9] <- 5


library(sqldf)
#對month變量進行分組統計
a1=sqldf("select `Duration`,count(1) from train_data where `Creditability`=1         group by `Duration` ") 
a2=sqldf("select `Duration`,count(1) from train_data where `Creditability`=0         group by `Duration` ")

#或者用tidyverse得到相似效果
library(tidyverse)
attach(train_data)
train_data%>%group_by(Duration)%>%count()
a1=a1[1:21,]
# 合併數據集
b1=cbind(a1,a2)
head(b1)
# 添加一列變量名稱
b1[,5]=colnames(b1)[1]
# 類型轉換
b1=as.matrix(b1)

# 對Balance變量進行分組統計
a1=sqldf("select `AccountBalance`,count(1) from train_data where `Creditability`=1         group by `AccountBalance` ") 
a2=sqldf("select `AccountBalance`,count(1) from train_data where `Creditability`=0         group by `AccountBalance` ") 
b2=cbind(a1,a2) 
b2[,5]=colnames(b2)[1] 
b2=as.matrix(b2)
c=rbind(b1,b2)
colnames(c)=c('Bin','Good','Bin','Bad','Variable')
head(c)

接下來還需要把數據框中c中的Good變量

c=as.data.frame(c)
c$Good=as.numeric(c$Good)
c$Bad=as.numeric(c$Bad)
#各組好壞客戶之和
c$Total_Number_of_Loans=c$Good+c$Bad
#各組壞客戶的比例
c$BadLoans=c$Bad/c$Total_Number_of_Loans

# train_data數據集中好客戶和壞客戶的數量分別是700和300
# 計算每組好客戶佔總的好客戶的比例
c$Distibution_Good_PG <- c$Good/700
# 計算每組壞客戶佔總的好客戶的比例
c$Distibution_Bad_PB <- c$Bad/300
# 好壞客戶比例差異
c$P(GB) <- c$Distibution_Good_PG-c$Distibution_Bad_PB
#計算WOE
c$WOE=log(c$Distibution_Good_PG/c$Distibution_Bad_PB)
#計算IV
c$IV <- c$WOE*c$P(GB)
# 查看統計的c數據集
c
# 彙總計算
aggregate(x=c[,c("IV")],by=list(c$Variable),FUN=sum)
#取出IV值比較大的變量
index5 <- which(c$Variable %in% c('AccountBalance','Duration','PaymentStatusofPreviousCredit','Purpose','Mostvaluableavailableasset','ValueSavings')) 
d <- c[index5,]
str(german_credit)

#算每個變量的最大,與最小WOE與其差值
f1 <- aggregate(x=d[,c("WOE")],by=list(d$Variable),FUN=max) 
f2 <- aggregate(x=d[,c("WOE")],by=list(d$Variable),FUN=min) 
f3 <- cbind(f1,f2) 
colnames(f3) <- c(1,'max',1,'min') 
f3

接下來我們再計算貝葉斯模型的評分:

f3$deff = f3$max-f3$min
#將分數1設置爲最大與最小差800分,分數1是用一個常量乘以WOE
ad = 800/sum(f3$deff) 
d$Score1 = d$WOE*ad 
d
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章