金融信用卡評(píng)分模型的R實(shí)現(xiàn)

注盟迟,有疑問 加QQ群..[174225475].. 共同探討進(jìn)步
有償求助請(qǐng) 出門左轉(zhuǎn) door , 合作愉快

信用評(píng)分是指根據(jù)客戶的信用歷史資料贸弥,利用一定的信用評(píng)分模型,得到不同等級(jí)的信用分?jǐn)?shù)河咽。根據(jù)客戶的信用分?jǐn)?shù)胞皱, 授信者可以分析客戶按時(shí)還款的可能性。據(jù)此综芥, 授信者可以決定是否準(zhǔn)予授信以及授信的額度和利率

原理

  1. A/B系數(shù)計(jì)算
    Score= A - B * log(odds)
    Score + pdo = A - B * log(odds/2)
    B = pdo / log(2)
    A = Score + B* log(odds)
    odds - 壞好比 , 目標(biāo)變量值 1 的占比 除以 0 的占比
    pdo - odds 變化時(shí) Score 得分的上下浮動(dòng)差
    初始計(jì)算A/B值時(shí), odds 為整體數(shù)據(jù)的壞好比,即
    odds = P_bad / (1-P_bad)
    一般設(shè)定 Score 為600 ; Odds 減半時(shí)丽蝎,Score +20,假設(shè)初始 odds = (p/1-p)=0.2/0.8=0.25 則
    B = 20 / log(2)=28.8539
    A = 600 + 28.8539 * log(0.25) = 560

  2. 邏輯回歸系數(shù)轉(zhuǎn)化
    log(odds)=Beta_0+Beta_1 * x_1+Beta_2 * x_2+Beta_3 * x_3+...
    Score = A - B * log(odds)
    = A - B * (Beta_0+Beta_1 * x_1+Beta_2 * x_2+Beta_3 * x_3+...)
    = A - B * Beta_0-B * Beta_1 * x_1-B * Beta_2 * x_2-B * Beta_3 * x_3...
    =(A - B * Beta_0)-(B * Beta_1) * x_1-(B * Beta_2) * x_2-(B * Beta_3) * x_3...
    注: x_i = woe_i

案例應(yīng)用

1. 數(shù)據(jù)讀取

library(openxlsx)
library(data.table)
# 讀取各網(wǎng)點(diǎn)的日運(yùn)營明細(xì)
data1<-read.xlsx("../data1.xlsx",sheet=1)
data2 <- data.table(data1)[,lapply(.SD,sum),
                          keyby=.(UID,month),
                          .SDcols=names(data1)[4:17]]
# 列名稱中不能帶'.',若有則需要修改,考慮到作圖名稱過長也改掉
colnames(data2)[3:7]=c('lin_zhi','lin_zhuan','kuasheng','G_G','G_M')
colnames(data2)[ncol(data2)-c(2,1)] <- c('pingtai','quantity')

2. 數(shù)據(jù)清洗

2.1 NA 處理
2.1.1 NA 的列處理方式
VIM::matrixplot(res1)
na1 <- as.data.frame(sapply(res1,function(x){sum(is.na(x))/length(x)}))
colnames(na1)='per1';na1$col1 <- rownames(na1)
na1[order(-na1$per1),]
                    per1          col1
lin_zhi       0.99480405       lin_zhi
M-G           0.90656099           M-G
M-M           0.83540291           M-M
lin_zhuan     0.09749009     lin_zhuan
G_G           0.07476882           G_G
G_M           0.04720387           G_M
... ...

res10 <- res1[,-c(1,6,7)]
na1
2.1.2 NA 的行處理方式
na_cnt1 <- apply(res10,1,function(x)sum(is.na(x)))
table(na_cnt1)
na_cnt1
   0    1    2    3    4    5    6   11 
9416 1372  309   31   44    4    4  175 
res101 <- res10[-which(na_cnt1>=round(ncol(res10)/3)),]
VIM::matrixplot(res101)
na2
2.1.3 其他 NA 的處理方式
  • 自動(dòng)填充 rcaret::knnImputation()
  • 均值替代 rx[is.na(x)] = mean(x, na.rm=TRUE)
  • 全部用 0 填充
    本案例結(jié)合實(shí)際情況,采集 0 填充的方案
res11 <- res101[,lapply(.SD,function(x) ifelse(is.na(x),0,x))]
2.2 異常值處理

異常值檢測 可以用 rquantile(x,c(0.25,0.75)) +/- 1.5(or 3) * diff(quantile(x,c(0.25,0.75))) 的標(biāo)準(zhǔn)來完成

3. 共線性診斷處理和變量篩選

# --- 多重共線性診斷
corr1 <- cor(res101[,!'clus1'])
kappa(corr1,exact = TRUE)
# 條件數(shù)<100,則認(rèn)為多重共線性的程度很小,
# 若100<=條件數(shù)<=1000,則認(rèn)為存在中等程度的多重共線性,
# 若條件數(shù)>1000,則認(rèn)為存在嚴(yán)重的多重共線性.

# lasso變量篩選
# 如有疑問 請(qǐng)咨詢QQ群 174225475 

head(res11)

4. WoE 計(jì)算

indx1 <- sample(c(0,1),nrow(res11),prob = c(0.3,0.7),replace = TRUE)
train1 <- res11[indx1==1,] 
test1 <- res11[indx1==0,]
dat <- data.frame(train1) # train data
y='clus1' # target var
var_d <- c() # category var
var_c <- c() # numeric var

if(length(var_d1)==0){
  var_d = NULL
}else{var_d = var_d1}

if(length(var_c1)==0){
  var_c = NULL
}else{var_c = var_c1}

fit_data <- dat # testdata

source('./woe_repalce.R') # 調(diào)用 woe 計(jì)算函數(shù)
# woe_replace函數(shù), 請(qǐng)咨詢QQ群 174225475

library(smbinning)
woe_info1 <- woe.replace(dat,var_c,var_d,y,fit_data)
woe1 <- woe_info1[[1]] # woe 分值
(rules1 <- woe_info1[[2]]) # 各變量內(nèi)分組與woe分值對(duì)應(yīng)關(guān)系
     Cutpoint     WoE      varIndex
1   <= 0.1139 -5.9691 jiesuanshouru
2    <= 0.356 -2.3566 jiesuanshouru
3   <= 0.5561 -1.0874 jiesuanshouru
4   <= 0.8008  0.2356 jiesuanshouru
5   <= 1.0811  1.6840 jiesuanshouru
6   <= 1.3079  2.7690 jiesuanshouru
...  ...

5. 最終得分計(jì)算及評(píng)分規(guī)則整理

5.1 計(jì)算系數(shù) A/B
> (pdo <- 30)
[1] 30
> (B <- pdo/log(2))
[1] 43.28085
> (odds <- table(train1$clus1)[2]/table(train1$clus1)[1])
        1 
0.2579551 
> (SC <- 600)
[1] 600
> (A <- SC + B*log(odds))
       1 
541.3558 
5.2 利用 WoE 值重新建立 logistic 模型計(jì)算 各項(xiàng)系數(shù)

實(shí)際操作中, 因變量的分布是極度不平衡的, 因此在建模時(shí)就有了要不要人工設(shè)定 weights 參數(shù)對(duì)建模數(shù)據(jù)進(jìn)行樣本比例矯正, 以下是兩種方案(設(shè)置/不設(shè)置weights)的比較

> woe2 <- data.frame(cbind(woe1,clus1=train1$clus1))
> lgc3 <- glm(clus1~.,data=woe2,
            family = binomial(link = 'logit'))
> lgc_res3 <- predict(lgc3,data.frame(woe1),type = 'response')
> table(ifelse(lgc_res3 >0.5,1,0),train1$clus1)  
       0    1
  0 6100   90
  1   91 1507
> library(ModelMetrics)
> auc(ifelse(lgc_res3 >0.5,1,0),train1$clus1)
[1] 0.9642571

# ------------------
> lgc3 <- glm(clus1~.,data=woe2,weights = ifelse(woe2$clus1>0,5,1),
+             family = binomial(link = 'logit'))
> lgc_res3 <- predict(lgc3,data.frame(woe1),type = 'response')
> table(ifelse(lgc_res3 >0.5,1,0),train1$clus1)
       0    1
  0 5991   18
  1  200 1579
> library(ModelMetrics)
> auc(ifelse(lgc_res3 >0.5,1,0),train1$clus1)
[1] 0.9422909

> woe_info2 <- woe.replace(dat,var_c,var_d,y,
+                          fit_data = data.frame(test1))
> woe3 <- woe_info2[[1]]
> lgc_res4 <- predict(lgc3,data.frame(woe3),type = 'response')
> table(ifelse(lgc_res4 >0.5,1,0),test1$clus1)
   
      0   1
  0 534  10
  1  29  18

添加了 weights 參數(shù), 模型對(duì) 違約客戶 的預(yù)測準(zhǔn)確率會(huì)更高, 但整體AUC 會(huì)受影響, 因此在建模時(shí)可根據(jù) 業(yè)務(wù)的實(shí)際需求進(jìn)行 weights 參數(shù)的取舍

5.3 WoE 向?qū)嶋H得分轉(zhuǎn)化及其規(guī)則整理
# --- train1 樣本總得分計(jì)算
coef1 <- lgc3$coefficients
(BaseSC <- A-B*coef1[1])
Tsc1 <- BaseSC + woe1 %*% coef1[-1]

# ---得分轉(zhuǎn)化規(guī)則梳理
rules1$coef1 <- coef1[rules1$varIndex]
rules1$sc1 <- with(rules1,WoE*coef1)
# --- 分值分布情況
library(dplyr)
rules1 %>% 
  group_by(varIndex) %>%
  summarise(max1=max(sc1),
            min1=min(sc1),
            mean1=mean(sc1))
# A tibble: 7 x 4
       varIndex      max1      min1       mean1
          <chr>     <dbl>     <dbl>       <dbl>
1   feiyongheji 2.4498204 -3.176858 -0.12697315
2       jianshu 2.9163435 -3.223899  0.18207080
3 jiesuanshouru 2.8838985 -3.500189  0.29030440
4       pingtai 3.4201266 -5.301336 -0.02456898
5      quantity 0.9789534 -1.492049 -0.11555953
6          tiji 2.8583949 -3.338300 -0.08009086
7        yunfei 2.4681047 -3.475437 -0.14391316
# --- 規(guī)則展示
> rules1[,.(varIndex,Cutpoint,sc1)]
         varIndex   Cutpoint         sc1
 1: jiesuanshouru  <= 0.1139 -3.50018886
 2: jiesuanshouru   <= 0.356 -1.38187416
 3: jiesuanshouru  <= 0.5561 -0.63763471
 4: jiesuanshouru  <= 0.8008  0.13815223
 5: jiesuanshouru  <= 1.0811  0.98747182
 6: jiesuanshouru  <= 1.3079  1.62369921
 7: jiesuanshouru  <= 1.4988  2.20891113
 8: jiesuanshouru   > 1.4988  2.88389855
 9:   feiyongheji  <= -0.449 -3.17685829
10:   feiyongheji  <= 0.2052 -1.85452835
11:   feiyongheji  <= 0.4717 -0.89196384
12:   feiyongheji  <= 0.7499 -0.19168770
13:   feiyongheji  <= 1.0887  0.92124707
14:   feiyongheji  <= 1.4839  1.85515871
15:   feiyongheji   > 1.4839  2.44982037
16:        yunfei <= -0.5582 -3.47543677
17:        yunfei  <= 0.2745 -1.86611915
...  ...
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末膀藐,一起剝皮案震驚了整個(gè)濱河市屠阻,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌额各,老刑警劉巖国觉,帶你破解...
    沈念sama閱讀 222,627評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異虾啦,居然都是意外死亡麻诀,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,180評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門傲醉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蝇闭,“玉大人,你說我怎么就攤上這事硬毕《⊙郏” “怎么了?”我有些...
    開封第一講書人閱讀 169,346評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵昭殉,是天一觀的道長苞七。 經(jīng)常有香客問我,道長挪丢,這世上最難降的妖魔是什么蹂风? 我笑而不...
    開封第一講書人閱讀 60,097評(píng)論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮乾蓬,結(jié)果婚禮上惠啄,老公的妹妹穿的比我還像新娘。我一直安慰自己任内,他們只是感情好撵渡,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,100評(píng)論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著死嗦,像睡著了一般趋距。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上越除,一...
    開封第一講書人閱讀 52,696評(píng)論 1 312
  • 那天节腐,我揣著相機(jī)與錄音外盯,去河邊找鬼。 笑死翼雀,一個(gè)胖子當(dāng)著我的面吹牛饱苟,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播狼渊,決...
    沈念sama閱讀 41,165評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼箱熬,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了狈邑?” 一聲冷哼從身側(cè)響起城须,我...
    開封第一講書人閱讀 40,108評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎官地,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體烙懦,經(jīng)...
    沈念sama閱讀 46,646評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡驱入,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,709評(píng)論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了氯析。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片亏较。...
    茶點(diǎn)故事閱讀 40,861評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖掩缓,靈堂內(nèi)的尸體忽然破棺而出雪情,到底是詐尸還是另有隱情,我是刑警寧澤你辣,帶...
    沈念sama閱讀 36,527評(píng)論 5 351
  • 正文 年R本政府宣布巡通,位于F島的核電站,受9級(jí)特大地震影響舍哄,放射性物質(zhì)發(fā)生泄漏宴凉。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,196評(píng)論 3 336
  • 文/蒙蒙 一表悬、第九天 我趴在偏房一處隱蔽的房頂上張望弥锄。 院中可真熱鬧,春花似錦蟆沫、人聲如沸籽暇。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,698評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽戒悠。三九已至,卻和暖如春舟山,著一層夾襖步出監(jiān)牢的瞬間救崔,已是汗流浹背惶看。 一陣腳步聲響...
    開封第一講書人閱讀 33,804評(píng)論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留六孵,地道東北人纬黎。 一個(gè)月前我還...
    沈念sama閱讀 49,287評(píng)論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像劫窒,于是被迫代替她去往敵國和親本今。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,860評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容