woe全稱是“Weight of Evidence”,即證據權重,是對原始自變量的一種編碼形式。

進行WOE編碼前,需要先把這個變量進行分組處理(離散化)
其中,pyi是這個組中響應客戶(即模型中預測變量取值為“是”或1的個體,也叫壞樣本)占所有樣本中所有響應客戶的比例,pni是這個組中未響應客戶(也叫好樣本)占樣本中所有未響應客戶的比例;
#yi是這個組中響應客戶的數量,#ni是這個組中未響應客戶的數量,#yT是樣本中所有響應客戶的數量,#nT是樣本中所有未響應客戶的數量。
從這個公式中我們可以體會到,WOE表示的實際上是“當前分組中響應客戶占所有響應客戶的比例”和“當前分組中沒有響應的客戶占所有沒有響應的客戶的比例”的差異。
為了更簡單明了一點,我們來做個簡單變換,得:

不難看出,woe表示的是當前這個組中響應客戶和未響應客戶的比值,和所有樣本中這個比值的差異。這個差異是用這兩個比值的比值,再取對數來表示的。例子如下:
| Age | #bad | #good | Woe |
|---|---|---|---|
| 0-10 | 50 | 200 | =ln((50/100)/(200/1000))=ln((50/200)/(100/1000)) |
| 10-18 | 20 | 200 | =ln((20/100)/(200/1000))=ln((20/200)/(100/1000)) |
| 18-35 | 5 | 200 | =ln((5/100)/(200/1000))=ln((5/200)/(100/1000)) |
| 35-50 | 15 | 200 | =ln((15/100)/(200/1000))=ln((15/200)/(100/1000)) |
| 50以上 | 10 | 200 | =ln((10/100)/(200/1000))=ln((10/200)/(100/1000)) |
| 匯總 | 100 | 1000 |
WOE越大,這種差異越大,這個分組里的樣本響應的可能性就越大,WOE越小,差異越小,這個分組里的樣本響應的可能性就越小。woe反映的是在自變量每個分組下違約用戶對正常用戶占比和總體中違約用戶對正常用戶占比之間的差異;從而可以直觀的認為woe蘊含了自變量取值對於目標變量(違約概率)的影響。再加上woe計算形式與logistic回歸中目標變量的logistic轉換(logist_p=ln(p/1-p))如此相似,因而可以將自變量woe值替代原先的自變量值。
那woe編碼有什么意義呢?
很明顯,它可以提升模型的預測效果,提高模型的可理解性。
-
標准化的功能。
WOE編碼之后,自變量其實具備了某種標准化的性質,也就是說,自變量內部的各個取值之間都可以直接進行比較(WOE之間的比較)
-
異常值處理。
一些極值變量,可以通過分組的WOE,變為非異常值
- 檢查變量WOE后與違約概率的關系
一般篩選的變量WOE與違約概率都是單調的,如果出現U型,或者其他曲線形狀,則需要重新看下變量是否有問題。
-
核查WOE變量模型的變量系數出現負值。
如果最終模型的出來的系數出現負值,需要考慮是否出現了多重共線性的影響,或者變量計算邏輯問題。
woe的意義,大家可以再體會一下。下面附上一段woe自編Code:
## 證據權重函數
def total_response(data,label):
value_count = data[label].value_counts()
return value_count
def woe(data,feature,label,label_value):
'''
data:傳入需要做woe的特征和標簽兩列數據
feature:特征名
label:標簽名
label_value:接收字典,key為1,0,表示為響應和未響應,value為對應的值
'''
import pandas as pd
import numpy as np
idx = pd.IndexSlice # 創建一個對象以更輕松地執行多索引切片
data['woe'] = 1
groups = data.groupby([label,feature]).count().sort_index()
## 使用上述函數
value_counts = total_response(data,label)
resp_col = label_value[1]
not_resp_col = label_value[0]
resp = groups.loc[idx[resp_col,:]]/value_counts[resp_col]
not_resp = groups.loc[idx[not_resp_col,:]]/value_counts[not_resp_col]
Woe = np.log(resp/not_resp).fillna(0)
return Woe
既然講到這了,就再講講IV吧。
公式如下:

有了一個變量各分組的IV值,我們就可以計算整個變量的IV值,方法很簡單,就是把各分組的IV相加:

其中,n為變量分組個數。
