本文為根據風控課程總結
個人信貸產品的信用評分
商業銀行三大風險流動性風險、市場風險(利率、信用)和操作風險,其他(欺詐風險)
信用風險:在合約到期日不完全履約
信用風險重要參數:PD(違約概率)、LGD(違約條件下的損失率)、EAD(違約風險下的敞口暴露)、RWA(風險權重資產)、EL(期望損失)
銀行風控步驟
准入規則---》Pre A模型----》反欺詐----》新的規則----》A卡----》B卡
一般這里面不用選用相同的特征。這是因為客戶由於一些特征上表現差才會被拒絕,而隨着時間的偏移,這樣會出現偏差,因為迭代到下一個模型的時候,用之前的特征規則雖然表現好,但篩選掉的用戶將不在我們的建模樣本里,特征的樣本分布已經改變了。
A卡的y一般可以用客戶歷史逾期天數最大的天數來定義;B卡的y一般則可以用多期借款中逾期最大的一次。
什么是評分卡模型
以分數形式來衡量風險幾率的一種手段。
是對未來一段時間內違約/逾期/失聯概率的預測。(每個評分卡對應的都有對應的人群)
通常分數越高越安全。
申請評分卡(資信狀況)、行為評分卡(消費賬戶歷史上表現,通常進行行為評分卡的產品期限至少會是半年以上還款的才能看到歷史表現,比如房貸、車貸、信用卡有循環貸款的模式比較適用)、催收評分卡(違約概率評分卡(輕度逾期到違約)、損失回收評分、催收響應類評分卡)
評分卡常用模型
邏輯回歸:簡單、穩定、可解釋、易於監測和部署 缺點准確率不高
決策樹:對數據質量要求低(數值型非數值、缺失容忍、共現容忍)、易解釋 缺點准確率不高
組合模型:准確率高、不易過擬合 缺點不易解釋、計算量大
壞樣本定義
M3 &M3+ 、債務重組、個人破產、銀行主動關戶或注銷
時間窗口
觀察期與表現期(行為評分卡)
表現期:搜集是否觸發壞樣本定義的時間窗口,與前面M1\M0什么的沒關系,通常6個月~1年,但也不能定的過長,因為你的貸款產品的還款周期是固定的,如果表現期定的過長,那觀察期的數據就會變少。過短模型會不穩定。
觀察期:搜集特征的時間窗口,通常3年以內; 帶有時間切片的變量(如果你的特征有多是長期特征,而你的新客戶又沒有使用很長時間的信貸產品,那不太適合放在這個評分卡里面)
行為評分卡
y:貸款產品用戶在放貸后、產品期限結束之前的某段時間(表現期)內違約或逾期風險
適用產品:分期付款的產品房貸、車貸、裝修貸;循環授信產品信用卡或純信用類現金貸
特征構造
業務上所需要的變量是什么樣的呢?
1.變量必須對模型有貢獻,也就是說對客群加以區分
2.缺失值的填充,可以考慮使用同樣壞賬率區間的樣本去填充
3.邏輯回歸要求變量之間線性無關(不是正交基不能學習的很完整)的
4.評分卡模型通常要求變量呈現單調的趨勢,也就是BIVar, 首先是業務角度這樣更過關,比如貸款次數越多的bad_rate應該越高 ,還有就是對於最后評分卡來說,值越大分加的分越多;其次是邏輯回歸模型本身更可能處理這種單調的變量。
5.客群在每個變量的分布式穩定的,分布遷移無可避免,但不能波動太大(特征的穩定性,一個是計算PSI 另一個是可以通過做跨時間交叉驗證即1月做測試集,其他的做訓練集,求特征重要度,2月的做測試集,其他的做訓練集,求特征重要度,。。依次,把各組求出的特征求交,每次進入模型的特征即為穩定的特征,見金融風控中的06 LightGBM評分卡.ipynb)
#BIVar圖
# 等頻切分 df_train.loc[:,'fare_qcut'] = pd.qcut(df_train['Fare'], 10) df_train.head() df_train = df_train.sort_values('Fare') alist = list(set(df_train['fare_qcut'])) badrate = {} for x in alist: a = df_train[df_train.fare_qcut == x] bad = a[a.label == 1]['label'].count() good = a[a.label == 0]['label'].count() badrate[x] = bad/(bad+good) f = zip(badrate.keys(),badrate.values()) f = sorted(f,key = lambda x : x[1],reverse = True ) badrate = pd.DataFrame(f) badrate.columns = pd.Series(['cut','badrate']) badrate = badrate.sort_values('cut') print(badrate) badrate.plot('cut','badrate')
特征選擇
特征選擇通常考慮兩個方面,一是特征是否發散,即方差(一般針對分類變量,因為數值變量存在量綱問題,方差大小與量綱相關);二是特征與目標的相關性
現在很多公司不再精調,一個個看BIVar圖了,二是直接xgboost看重要度
基於重要度的特征篩選一般就是,1.IV值 2.卡方檢驗 3.模型篩選 選一種就好
有些風控會考慮變量的穩定性,會用PSI來篩選
#生成可以傳入PSI的數據集 def make_psi_data(dff_train): dftot = pd.DataFrame() for col in dff_train.columns: zero= sum(dff_train[col] == 0) one= sum(dff_train[col] == 1) ftdf = pd.DataFrame(np.array([zero,one])) ftdf.columns = [col] if len(dftot) == 0: dftot = ftdf.copy() else: dftot[col] = ftdf[col].copy() return dftot psi_data_train = make_psi_data(dff_train) psi_data_val = make_psi_data(dff_val) #定義根據psi_data計算psi的函數 def var_PSI(dev_data, val_data): dev_cnt, val_cnt = sum(dev_data), sum(val_data) if dev_cnt * val_cnt == 0: return 0 PSI = 0 for i in range(len(dev_data)): dev_ratio = dev_data[i] / dev_cnt val_ratio = val_data[i] / val_cnt + 1e-10 psi = (dev_ratio - val_ratio) * math.log(dev_ratio/val_ratio) PSI += psi return PSI psi_dct = {} for col in dff_train.columns: psi_dct[col] = var_PSI(psi_data_train[col],psi_data_val[col])
常用特征
時間切片特征,例如觀察期之前180天內,平均每月的逾期次數
時間序列衍生特征,(基礎特征,月份)假設基礎特征為“加油金額”,分別計算出最近1月、2月、3月。。。6月的“加油金額”然后由此再衍生出,最近幾個月加油金額>0的次數、等於0的次數、最近1個月/以往平均金額等等變量
還款率類型特征(本月還款率,過去半年內最大的還款率,過去半年內平均月還款率)、額度使用率特征(過去6個月內平均額度使用率,過去6個月內額度使用率增高的次數)、逾期類特征(過去6個月的最大逾期狀態、過去6個月M1\M2\M3的次數)、消費類型特征(“國外使用”類型特征,“提現“”類型特征)
特征分箱
分箱:將連續變量離散化,除此之外將多狀態的離散變量合並為少狀態也屬於。
分箱的重要性:1.連續變量離散化,robust更強不易受噪聲影響;2.分箱后one-hot變成N個變量,引入了非線性,增強了邏輯回歸的表達 3.離散化后模型也會更穩定 4.離散化后還可以做特征交叉 5.不離散的話評分卡沒法做成加法減法的形式。
分箱的優勢:可以將缺失值作為一箱,將所有變量轉換到同一尺度
分箱的限制:計算量大、分箱后需要編碼;
要求:分箱后要保證變量的單調性,不單增的變成單調的(更粗的分箱)
分箱的方法:
best-ks:
卡方分箱:相鄰的屬性對壞事件的相關性是不是一致,一致就合並。依賴於閾值的選定,也可以考慮最小區間數或最大區間數。
自由度是類別數-1,在置信度給定的情況下確定卡方閾值。
等距分箱、等頻分箱
分箱的注意點: 連續變量如果有特殊值需要單獨分箱。例如在還款率變量中,有時需將“上月末欠款額為0”的情形設置為特殊值-1,此時需要單獨分箱。
WOE編碼
分箱完之后的組別沒有任何意義,所以需要編碼。評分卡里面常用的編碼是WOE編碼,要計算WOE每個組別里面必須同時有好壞樣本。
woe處理后,邏輯回歸變量前面的系數已經不是越大越重要了,因為WOE本身已經是重要度了,此時邏輯回歸變量前的系數就是擬合值。
以前風控公司一定會做WOE,現在有些不做,有些只有文本型的做,數值型的不做,因為其他模型使用WOE只能帶來千分位的模型提升。
WOE的符號與好樣本比例相關,要求回歸模型的系數為負(壞樣本比例值要小)
IV值
衡量特征包含預測變量濃度的一種指標。該變量的IV值是每一箱的IV值相加,一個變量只有一個IV。而IV是從加權后的WOE(權重是衡量差異的重要性,絕對值的重要性),WOE是每一箱都有的。一般分箱數越多IV值會越高,所以在計算IV值前要做較好的分箱。
用戶衡量變量的區分度。
IV一定是正值、一個變量只有一個IV。
woe后如果變量的符號是正的,和我們的業務邏輯是相反的,我們認為該變量有問題。當我們特征工程完了以后,對於大部分變量我們不能直接丟到模型里面去的,需要做變量篩選,包括單變量分析和多變量分析。
單變量分析
分箱后的WOE值。
1. 如果分箱后,某一個特征的某一個值占比達90%以上,我們不建議把這個特征放到模型里面去。在分箱之前如果某變量的方差很小也可以提前進行刪除。
2. 保證bad rate的單調性(U型也可以,再奇怪的不可以,要么拿掉要么重新處理分箱),但不能保證WOE的單調性,一般WOE不單調可能是某一箱占比過小
3. IV值要么0.1要么0.2
雙變量分析
1. 消除兩兩變量的相關性。可以預估變量重要性,繼而選擇重要性更高的變量,例如借助與隨機森林或GBDT對特征重要度的排序
2. 變量的多重共線性,β的估計無偏,但是會影響顯著性。計算每個特征相對於其他特征的VIF,如果發現某個特征的VIF比較高,需要逐項排查是哪一個或哪幾個,然后再根據IV決定拿掉哪個。
行為評分卡模型構建
邏輯回歸不適合放很多變量,一般現實中使用IV+隨機森林進行變量挑選。挑選完變量后,運行邏輯回歸模型要求1. 系數的符號為負(woe=ln(G/B),如果沒有做WOE不需要統一符號為負) 2.系數顯著
邏輯回歸一般選擇L2正則效果更好。里面的class weight參數可以解決類別不平衡問題。
Lasso在保證一定精度的情況下,考慮模型的復雜度。
從模型到分數,參數前面負號和y前面的負號抵消了,
50這個數值就是PDO,隨着模型的更新需要動態調整,保障各區間(A B C D)的分數刻度不變,保障每個區間的人數比例不會波動太大
def score(person_info,finance_info,credit_info,act_info): xbeta = person_info * ( 3.49460978) + finance_info * ( 11.40051582 ) + credit_info * (2.45541981) + act_info * ( -1.68676079) --0.34484897 score = 650-34* (xbeta)/math.log(2) return score
如果是xgboost模型轉換成分數,可以直接把概率進行替換
def score(xbeta): score = 1000-500*(math.log2(1-xbeta)/xbeta) #好人的概率/壞人的概率 return score evl['xbeta'] = model.predict_proba(evl_x)[:,1]
模型過擬合的處理方法
1. 特征篩選減少特征 2.正則 3.分箱的箱子划分更粗一點(變量變得更穩定)4.增加樣本(一般做不到)
模型驗證與監控
1.監控通常會看通過率(捕獲率),看上線后各組的捕獲率是不是還是前面的組就可以捕獲大部分壞人。
2.分數的分布,客群沒有發生太大變化,但分數越來越低了,這種時候會對模型改動。低分原因分析。
3. 還會看主要特征的PSI和模型的PSI
4. 模型的KS值, KS和AUC實際是一樣的,只是坐標不一樣
樣本不均衡
1.半監督算法
拒絕推斷,從模型預測出的每個分組里面取出一定比例的黑樣本,作為擴充
用半監督的算法,把樣本分成兩類,分別用不同的特征訓練,然后再分別交叉進行預測,將預測出的高概率樣本標記為黑樣本
2.代價敏感學習
利用不同分類的樣本被誤分類而產生不同的代價,即給予不同的樣本不同的權重,模型的fit里面都有參數(sample_weight= )
3.采樣算法
朴素隨機采樣
Smote 對於少類樣本a,隨機選擇一個最近鄰的樣本b,然后從a與b的連線上隨機選取一個c作為新的少數類樣本。這個方法比較容易過擬合
Borderline-Smote-1 只對靠近邊界的樣本去造新的負樣本,這樣可以讓我們學習到更清晰的邊界。推薦使用。
from imblearn.oversample import SMOTE
SMOTE(kind = 'borderline1')
過擬合問題
1.找更多的數據集來學習,緩解過擬合問題
2.特征選擇,降低特征維度
3.用差異化的模型去做模型融合
風控實踐中問題
可參考 https://github.com/xsj0609/data_science/tree/master/ScoreCard
1.模型效果不好
數據就有問題
2.訓練集效果好,跨時間測試效果不好
樣本分布不一樣導致
解決方法:去掉表現很不一樣的特征。
沒辦法的時候用,存在泄漏, 在跨時間測試集上訓練一個模型,然后去之前的8個月上做預測,懸着跨時間測試集里面的變量去訓練集里面訓練,再在跨時間上去做
3.跨時間測試效果也好,上線后效果不好
原因1:線上線下做變量的邏輯不一致
原因2:可能包括了未來信息的變量做進來了
4.上線之后效果好,幾周后分數分布開始下滑
即幾周后,根據拒絕率划分的A\B\C\D類客戶,出現A類客戶下滑到了B
模型的問題,效果不好
有一兩個變量在跨時間上表現不好
5.一兩個月內比較穩定,突然分數分布驟降
關注外部環境變化,是否政策變化,某個行業是不是暴雷了,運營拉了新客
6.沒有明顯問題,但模型每個月逐步失效
正常的