利用決策樹(shù)制定互金風(fēng)控策略(一)

筆者最近利用決策樹(shù)對(duì)貸前風(fēng)控的策略進(jìn)行調(diào)整和優(yōu)化,因?yàn)槟壳暗娜蝿?wù)是降低資損,所以對(duì)好用戶的誤殺高一點(diǎn)是可以容忍的,但是任然想在降低誤殺的前提下提升識(shí)別壞用戶的水平,今兒得空,將有關(guān)的東西整理一下。

整理的流程是:決策樹(shù)簡(jiǎn)介--->數(shù)據(jù)整理---->決策樹(shù)建模---->查看規(guī)則效果---->搭建規(guī)則----->規(guī)則上線

為什么要先將決策樹(shù)放最前講呢?因?yàn)楣P者認(rèn)為不同的模型算法對(duì)數(shù)據(jù)方面的要求是不一樣的,所以最好是在了解了算法對(duì)數(shù)據(jù)的要求的前提下再去清洗整理數(shù)據(jù)會(huì)更有效果一些


1.決策樹(shù)

決策樹(shù)之所以能成為常用的建模工具,從使用經(jīng)歷來(lái)看,有以下幾點(diǎn)吧:

A.生成的結(jié)果易于解釋,在實(shí)際工作中容易部署,尤其是對(duì)于金融風(fēng)控來(lái)講,在什么變量的什么閾值下的用戶該被拒絕或通過(guò),這個(gè)很依賴if-then這種判斷

B.能有效處理各類數(shù)據(jù),例如稀疏的,偏態(tài)的,連續(xù)的,類別的,缺失值,很少需要對(duì)變量的值進(jìn)行什么標(biāo)準(zhǔn)化啊,類別轉(zhuǎn)數(shù)值啊

C.可以對(duì)變量重要性進(jìn)行評(píng)估,有時(shí)候可以當(dāng)做特征選擇的手段來(lái)使用

但是也有一些缺陷,而這些缺陷決定了我們的數(shù)據(jù)處理過(guò)程:

A.當(dāng)預(yù)測(cè)變量彼此高度相關(guān)時(shí),那么選擇哪個(gè)變量作為切分點(diǎn)有很大幾率是隨機(jī)的,會(huì)導(dǎo)致彼此相關(guān)的變量間一些微小的變動(dòng)會(huì)導(dǎo)致隨機(jī)選擇不同的變量作為切分點(diǎn),結(jié)果可能會(huì)得到一組完全不同的劃分,即模型的方差很大,出來(lái)的規(guī)則策略不穩(wěn)定,且會(huì)選擇比實(shí)際需要更多的變量,雖然集成方法能夠解決這個(gè)問(wèn)題,但是

集成方法的解釋性不好,目前筆者的水平還沒(méi)發(fā)現(xiàn)可以用在金融風(fēng)控策略方面的,如果有大佬知道還請(qǐng)答答疑。針對(duì)這塊,可以對(duì)預(yù)測(cè)變量查看兩兩相關(guān)性,相關(guān)性大的選擇數(shù)據(jù)質(zhì)量較好的,且業(yè)務(wù)上更有解釋性的變量

B.便宜沒(méi)好貨雖然不是絕對(duì)的,但是基本上是這樣的,而決策樹(shù)因?yàn)橛辛己玫慕忉屝郧乙子谟?jì)算會(huì)使得單棵決策樹(shù)較其他模型而言一般具有次優(yōu)的預(yù)測(cè)能力。原因在于樹(shù)模型會(huì)將數(shù)據(jù)劃分為若干矩形的區(qū)域,如果預(yù)測(cè)變量和結(jié)果變量之間的關(guān)系并不能由矩形來(lái)刻畫,那么樹(shù)的預(yù)測(cè)能力就不是最優(yōu)的

C.決策樹(shù)還具有選擇偏差:****具有很多不同取值的預(yù)測(cè)變量通常比取值較離散的變量更容易出現(xiàn)在模型中,且缺失值越多,變量選擇會(huì)更有有偏。針對(duì)這個(gè)問(wèn)題,筆者想到的辦法是盡可能的減少變量的缺失值,并用變量的WOE值來(lái)代替原始數(shù)值,或者盡可能選擇值較為集中的變量

通過(guò)對(duì)決策樹(shù)的優(yōu)缺點(diǎn)進(jìn)行進(jìn)行梳理,得到我們的數(shù)據(jù)處理過(guò)程

2.數(shù)據(jù)處理

2.1查看數(shù)據(jù)分布

對(duì)于風(fēng)控策略來(lái)講,假定壞用戶永遠(yuǎn)是少數(shù),那么好的數(shù)據(jù)分布應(yīng)該是比較集中的,異常值是較少的,所以在處理數(shù)據(jù)之前可以看看各個(gè)白能量的數(shù)據(jù)分布

library(readxl)
library(data.table)
Sys.setlocale(category = "LC_ALL", locale = "zh_cn.utf-8") #mac系統(tǒng)對(duì)于中文在R中的支持

origin_data <- read_excel('數(shù)據(jù).xlsx',sheet = 'Sheet1')
study_data <- data.table(origin_data)
sd <- study_data[,.SD,.SDcols=-c(1,3,4,5)] #將沒(méi)有業(yè)務(wù)含義的數(shù)據(jù)剔除

我們可以構(gòu)建一個(gè)自定義函數(shù),對(duì)于數(shù)值型數(shù)據(jù)用直方圖來(lái)和密度圖來(lái)展示,類別型數(shù)據(jù)用條形圖來(lái)展示

plots(sd,save = TRUE) #save代表將圖保存到本地

這里只挑選兩個(gè)結(jié)果圖來(lái)

image
image

2.2 查看缺失值并進(jìn)行缺失值填補(bǔ)

在前面我們講到,缺失值如果比較多的話,決策樹(shù)就越會(huì)進(jìn)行有偏選擇變量,所以要盡可能保證沒(méi)有缺失值,但是在實(shí)際業(yè)務(wù)中缺失值在所難免,比如購(gòu)買的第三方數(shù)據(jù)并沒(méi)有這個(gè)用戶的相關(guān)數(shù)據(jù),那就有缺失值了,所以缺失值處理要根據(jù)業(yè)務(wù)來(lái)定,如果第三方數(shù)據(jù)的缺失值很低,可以進(jìn)行填補(bǔ)或者刪除,如果缺失值太大,那么就只能刪除了

筆者這里也自定義了一個(gè)查看各個(gè)變量的缺失率的函數(shù)

 n_r <- na_ratio(sd)
> head(n_r)
    vars na_ratio
1 target        0
2     V1        0
3     V2        0
4     V3        0
5     V4        0
6     V5        0
> tail(n_r)
    vars   na_ratio
130 V129 0.00000000
131 V130 0.02855439
132 V131 0.12752863
133 V132 0.12752863
134 V133 0.12752863
135 V134 0.00000000

可以看到有些變量是有缺失值的,因?yàn)楣P者所在公司目前的策略平臺(tái)并不支持線上處理數(shù)據(jù),只能進(jìn)行簡(jiǎn)單的四則運(yùn)算,所以對(duì)于缺失值只能將其刪除,但是也不妨礙我們?cè)谧约壕毩?xí)的時(shí)候?qū)W一些填補(bǔ)方法

缺失值填補(bǔ)方法整理如下:

1.中心趨勢(shì)值填補(bǔ),即對(duì)于數(shù)值型變量,用平均值或者中位數(shù)填補(bǔ),類別型用眾數(shù)填補(bǔ),這類填補(bǔ)方式的優(yōu)點(diǎn)是計(jì)算方便快捷,缺點(diǎn)是沒(méi)有考慮目標(biāo)變量的情況

2.處理缺失值的方法,根據(jù)變量之間的相關(guān)關(guān)系填補(bǔ)缺失值。比如選取離缺失值比較近的幾行數(shù)據(jù)來(lái)進(jìn)行填補(bǔ),用戶的最多的就是k近鄰算法了,可以用VIM包的中kNN函數(shù)來(lái)操作,也可以用caret包中的preProcess函數(shù)。需要注意的是,采用K近鄰方法時(shí),會(huì)對(duì)原始數(shù)據(jù)進(jìn)行標(biāo)準(zhǔn)化,如果需要返回原始值,還需將標(biāo)準(zhǔn)化公式倒推回來(lái);

3.使用Bagging樹(shù)集成方法,理論上對(duì)缺失值的填補(bǔ)更權(quán)威,但其效率比較低,這個(gè)可以用caret包中的preProcess函數(shù)

4.多重插補(bǔ)法,可以試試mice包,其操作原理是基于MC(蒙特卡洛模擬法)

這里筆者用的是最簡(jiǎn)單的方式:

如果缺失率超過(guò)某一閾值,刪除那一列;對(duì)于數(shù)值型變量,符合正態(tài)分布的變量用平均值填補(bǔ),不符合正態(tài)分布的用中位數(shù)填補(bǔ);對(duì)于名義變量,我們用眾數(shù)填補(bǔ)

#threshold=0.3代表缺失率超過(guò)30%就把這一列數(shù)據(jù)刪除,alpha=0.05用來(lái)判斷正態(tài)分布的
sd <- centralImputation(sd,threshold = 0.3,alpha = 0.05) 

no_null_data <- sd$complete_data

> sd$delete_vars

以下數(shù)值型變量的不重復(fù)值少于3個(gè)(包含缺失值),建議剔除該變量`
[1] "V11"    "V133"   "target"

以下類別型變量的不重復(fù)值少于2個(gè)(包含缺失值),建議剔除`
NULL

由結(jié)果可看到,V11,V133列因?yàn)椴恢貜?fù)值太少太少,做規(guī)則都不合適了,所以建議剔除

no_null_data <- subset(no_null_data,select=-c(V11,V133))

2.3 刪除高相關(guān)的預(yù)測(cè)變量和完全線性關(guān)系的變量

上面我們講到了,如果變量之間相關(guān)性較大的話,會(huì)導(dǎo)致決策樹(shù)算出來(lái)的模型不穩(wěn)定

可以利用cor函數(shù)來(lái)查看每個(gè)變量之間的相關(guān)性,但是如果變量太多的話人工看過(guò)去是很花費(fèi)時(shí)間和精力的,除非自己寫個(gè)函數(shù)把相關(guān)性弱的挑出來(lái)

這里可以使用caret包中的

函數(shù)語(yǔ)法及參數(shù)介紹:

findCorrelation(x, cutoff = .90, verbose = FALSE,names = FALSE, exact = ncol(x) < 100)

x:為一個(gè)相關(guān)系數(shù)矩陣

cutoff:指定高度線性相關(guān)的臨界值,默認(rèn)為0.9

verbose:邏輯值,指定是否打印出函數(shù)運(yùn)算的詳細(xì)結(jié)果

names:邏輯值,是否返回變量名,默認(rèn)返回需要?jiǎng)h除變量的對(duì)應(yīng)索引值

exact:邏輯值,是否重新計(jì)算每一步的平均相關(guān)系數(shù)

x = subset(no_null_data,select = -c(target))
x_no_character <- subset(x,select = -c(V1)) #去除已知的類別型數(shù)據(jù)
corr <- cor(x_no_character) #在用findCorrelation之前要先計(jì)算出相關(guān)性矩陣

發(fā)現(xiàn)這里出現(xiàn)了個(gè)錯(cuò)誤,如下所示,這說(shuō)明數(shù)據(jù)里面混入了我所不知道的類別型數(shù)據(jù)

 corr <- cor(x_no_character)

> Error in cor(x_no_character) : 'x' must be numeric

所以只好寫了個(gè)識(shí)別數(shù)據(jù)類型的函數(shù)

>> data_type(x_no_character)
$numeric
  [1] "V47"  "V58"  "V69"  "V80"  "V91"  "V102" "V113" "V2"   "V13"  "V24"  "V35" 
 [12] "V41"  "V42"  "V43"  "V44"  "V45"  "V46"  "V48"  "V49"  "V50"  "V51"  "V52" 
 [23] "V53"  "V54"  "V55"  "V56"  "V57"  "V59"  "V60"  "V61"  "V62"  "V63"  "V64" 
 [34] "V65"  "V66"  "V67"  "V68"  "V70"  "V71"  "V72"  "V73"  "V74"  "V75"  "V76" 
 [45] "V77"  "V78"  "V79"  "V81"  "V82"  "V83"  "V84"  "V85"  "V86"  "V88"  "V89" 
 [56] "V90"  "V92"  "V93"  "V94"  "V95"  "V96"  "V97"  "V98"  "V99"  "V100" "V101"
 [67] "V103" "V104" "V105" "V106" "V107" "V108" "V109" "V110" "V111" "V112" "V114"
 [78] "V115" "V116" "V117" "V118" "V119" "V120" "V121" "V122" "V123" "V125" "V126"
 [89] "V127" "V128" "V129" "V130" "V131" "V132" "V134" "V3"   "V4"   "V5"   "V6"  
[100] "V7"   "V8"   "V9"   "V10"  "V12"  "V14"  "V15"  "V16"  "V17"  "V18"  "V19" 
[111] "V20"  "V21"  "V22"  "V23"  "V25"  "V26"  "V27"  "V28"  "V29"  "V30"  "V31" 
[122] "V32"  "V33"  "V34"  "V36"  "V37"  "V38"  "V39"  "V40" 

$category
[1] "V124" "V87" 

終于發(fā)現(xiàn)了問(wèn)題所在,分別查看這兩列數(shù)據(jù),發(fā)現(xiàn)是用戶ID,是沒(méi)有用的,所以將其刪除

x_no_character <- subset(x_no_character,select = -c(V124,V87))
data_type(x_no_character) #發(fā)現(xiàn)已經(jīng)沒(méi)有類別型數(shù)據(jù)了
corr <- cor(x_no_character) #在用findCorrelation之前要先計(jì)算出相關(guān)性矩陣
corr[upper.tri(corr)] #返回相關(guān)系數(shù)矩陣中的上三角值,預(yù)先查看高相關(guān)性值,但不能明確那組變量間是高相關(guān)的。
library(caret)
fc <- findCorrelation(corr,cutoff=0.80) #返回需要?jiǎng)h除變量的對(duì)應(yīng)索引值
x_need_data <- subset(x_no_character,select = -fc)

2.4 計(jì)算各個(gè)變量的WOE值

后續(xù)的下回再寫

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容