特徵工程(下)

  工作中常用的特徵工程有哪些方法呢?首先,我們需要了解業務中的模型會遇到什麼問題,定位了問題才能找到貼合業務場景的特徵工程方法。這比你會一些處理特徵的騷操作重要很多,畢竟模型落地不是在打比賽,某個評價指標提高一點點就行,需要考慮的方面更多,比如變量的可解釋性、模型的可解釋性、模型的部署和監控等等。

  下面是我們在業務中的模型中會遇到的問題:

  • 模型效果不好
  • 訓練集效果好,跨時間測試效果不好
  • 跨時間測試效果也好,上線之後效果不好(一定是變量邏輯出問題,特徵出現穿越)
  • 上線之後效果還好,幾周之後分數分佈開始下滑(有一兩個變量跨時間測試不好)
  • 一兩個月內都比較穩定,突然分數分佈驟降(關注外部環境)
  • 沒有明顯問題,但模型每個月逐步失效(無解)

  以上問題是建模的核心,個人覺得比高大上的算法重要得多,可以針對這些問題多深入思考原因。然後我們來考慮一下業務所需要的變量是什麼。

  • 變量必須對模型有貢獻,也就是說必須能對客羣加以區分
  • 邏輯迴歸要求變量之間線性無關
  • 邏輯迴歸評分卡也希望變量呈現單調趨勢 (有一部分也是業務原因,但從模型角度來看,單調變量未必一定比有轉折的變量好)
  • 客羣在每個變量上的分佈穩定,分佈遷移無可避免,但不能波動太大

import pandas as pd
import numpy as np
df_train = pd.read_csv('train.csv')
df_train.head()
#數據集爲kaggle上的Titanic數據集。

變量重要性

  • IV值
  • 卡方檢驗
  • 模型篩選
    這裏我們使用IV值或者模型篩選多一點(一般一種方法就行,差別不大)

分箱、WOE、IV

import numpy as np
import pandas as pd
from scipy import stats

def mono_bin(Y,X,n=20):
    r=0
    good = Y.sum()
    bad = Y.count()-good
    while np.abs(r)< 1:
        d1=pd.DataFrame({"X":X,"Y":Y,"Bucket":pd.qcut(X,n)})
        d2=d1.groupby('Bucket',as_index=True)
        r,p=stats.spearmanr(d2.mean().X,d2.mean().Y)
        n=n-1
    d3=pd.DataFrame(d2.X.min(),columns=['min'])
    d3['min']=d2.min().X
    d3['max']=d2.max().X
    d3['sum']=d2.sum().Y
    d3['total']=d2.count().Y
    d3['rate']=d2.mean().Y
    d3['woe']=np.log((d3['rate']/(1-d3['rate']))/(good/bad))
    d3['iv']=(d3['rate']/(1-d3['rate']) - (good/bad)) * np.log((d3['rate']/(1-d3['rate']))/(good/bad))
    d4=(d3.sort_index(by='min')).reset_index(drop=True)
    print("="*60)
    print(d4)
    return d4


  可以看到將年齡分爲3箱,每一箱的最小值,最大值,壞樣本數量,總數量,壞樣本佔比,WOE值,IV值。將IV值求和之後就是Age變量的IV值。
變量的IV值一般取大於0.02。
這裏用到的分箱方法有時間在深入瞭解一下,和常用的卡方分箱還不一樣。

集成模型輸出特徵重要性

  集成學習方法可以評估特徵重要性指標,一般評估指標有weight, gain, cover等,這裏找了一篇博客,後續有時間會寫一篇文章講解。
https://blog.csdn.net/sujinhehehe/article/details/84201415

#lightGBM中的特徵重要性
feature = pd.DataFrame(
            {'name' : model.booster_.feature_name(),
            'importance' : model.feature_importances_
          }).sort_values(by =  ['importance'],ascending = False)

共線性

  • 相關係數
  • 方差膨脹係數

      可以用matplotlib畫個熱力圖啥的。

  在多元迴歸中,我們可以通過計算方差膨脹係數VIF來檢驗迴歸模型是否存在嚴重的多重共線性問題。 定義:
VIF=11R2VIF=\frac{1}{1-R^2}
  其中,RR爲自變量 對其餘自變量作迴歸分析的負相關係數。方差膨脹係數是容忍度1R21-R^2的倒數。

  方差膨脹係數VIF越大,說明自變量之間存在共線性的可能性越大。一般來講,如果方差膨脹因子超過10,則迴歸模型存在嚴重的多重共線性。又根據Hair(1995)的共線性診斷標準,當自變量的容忍度大於0.1,方差膨脹係數小於10的範圍是可以接受的,表明白變量之間沒有共線性問題存在。
VIF函數詳細使用方法可以看statsmodels官方文檔.

單調性

  • 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')



  對應上面的建模變量中,邏輯迴歸評分卡也希望變量呈現單調趨勢 (有一部分也是業務原因,但從模型角度來看,單調變量未必一定比有轉折的變量好)。

穩定性

  • PSI
  • 跨時間交叉檢驗

PSI

PSI公式如下:

  對跨時間分箱的數據分別求PSI,因爲預期佔比需要建模之後根據模型來算,所以需要和集成學習輸出特徵重要性一樣先計算出預期佔比,不知道是不是這個意思,那也太麻煩了。。。
  一般認爲psi小於0.1時候模型穩定性很高,0.1-0.25一般,大於0.25模型穩定性差,建議重做。

跨時間交叉檢驗

  就是將樣本按照月份切割,一次作爲訓練集和測試集來訓練模型,取進入模型的變量之間的交集,但是要小心共線特徵!

解決方法

  • 不需要每次都進入模型,大部分都在即可
  • 先去除共線性(這也是爲什麼集成模型我們也會去除共線性)

【作者】:Labryant
【原創公衆號】:風控獵人
【簡介】:某創業公司策略分析師,積極上進,努力提升。乾坤未定,你我都是黑馬。
【轉載說明】:轉載請說明出處,謝謝合作!~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章