如下是Coursera上的How to Win a Data Science Competition: Learn from Top Kagglers課程筆記。python
均值編碼是一種很是強大的技術,它有不少名字,例如:likelihood encoding、target encoding,但這裏咱們叫它均值編碼。咱們舉一個二分類任務的例子。dom
feature | feature_label | feature_mean | target | |
---|---|---|---|---|
0 | Moscow | 1 | 0.4 | 0 |
1 | Moscow | 1 | 0.4 | 1 |
2 | Moscow | 1 | 0.4 | 1 |
3 | Moscow | 1 | 0.4 | 0 |
4 | Moscow | 1 | 0.4 | 0 |
5 | Tver | 2 | 0.8 | 1 |
6 | Tver | 2 | 0.8 | 1 |
7 | Tver | 2 | 0.8 | 1 |
8 | Tver | 2 | 0.8 | 0 |
9 | Klin | 0 | 0.0 | 0 |
10 | klin | 0 | 0.0 | 0 |
11 | Tver | 2 | 1 | 1 |
咱們想對feature
變量進行編碼,最直接、經常使用的方式就是label encoding
,這就是第二列數據。
平均編碼以不一樣的方式去完成這個任務,它用每一個城市自身對應的目標均值來進行編碼。例如,對於Moscow
,咱們有五行,三個0和兩個1。 因此咱們用2除以5或0.4對它進行編碼。用一樣的方法處理其餘城市。ide
如今瞭解一下細節。當咱們的數據集很是大,包含數百個不一樣的城市,讓咱們試着比較一下。咱們繪製了0,1 class的直方圖。
oop
在label encoding
的狀況下,咱們獲得的圖看起來沒有任何邏輯順序。
學習
可是當咱們使用mean encoding
對目標進行編碼時,類看起來更加可分了,像是被排序過。ui
通常來講,模型對複雜、非線性的特徵目標越依賴,均值編碼
越有效。例如樹模型的深度有限,能夠用平均編碼來補償它,能夠用它的短板來得到更好的分數。編碼
以上只是一個例子,傳遞的是一種思想,實際上能夠作不少相似的操做。3d
Goods-number of ones in a group,
Bads-number of zeroscode
構造Mean encoding
的例子orm
means= X_tr.groupby(col).target.mean() train_new[col+'_mean_target'] = train_new[col].map(means) val_new[col+'_mean_target'] = val_new[col].map(means)
將它運用到模型中,出現了嚴重的過擬合,可是爲何呢?
feature | feature_label | feature_mean | target | |
---|---|---|---|---|
8 | Tver | 2 | 0.8 | 0 |
9 | Klin | 0 | 0.0 | 0 |
feature | feature_label | feature_mean | target | |
---|---|---|---|---|
10 | klin | 0 | 0.0 | 0 |
11 | Tver | 2 | 1 | 1 |
When they are categorized, it's pretty common to get results like in an example, target 0 in train and target 1 in validation. Mean encodings turns into a perfect feature for such categories. That's why we immediately get very good scores on train and fail hardly on validation.
在上一節,咱們意識到平均編碼不能按原樣使用,須要對訓練數據進行某種正規化。如今咱們將實施四種不一樣的正則化方法。
一般作四到五折的交叉驗證就能獲得不錯的結果,無序調整此數字。
代碼例子
這個方法看起來已經徹底避免了目標變量的泄露,但事實並不是如此。
這裏咱們經過留一法
對Moscow
進行編碼
feature | feature_mean | target | |
---|---|---|---|
0 | Moscow | 0.50 | 0 |
1 | Moscow | 0.25 | 1 |
2 | Moscow | 0.25 | 1 |
3 | Moscow | 0.50 | 0 |
4 | Moscow | 0.50 | 0 |
對於第一行,咱們獲得0.5,由於有兩個1和 其他行中有兩個0。 一樣,對於第二行,咱們獲得0.25,依此類推。 但仔細觀察,全部結果和由此產生的特徵。 它完美地分割數據,具備等於或等的特徵的行 大於0.5的目標爲0,其他行的目標爲1。 咱們沒有明確使用目標變量,但咱們的編碼是有偏置的。
目標變量的泄露效果對於KFold scheme
仍然是有效的,只是效果溫和了點。
在實踐中,若是您有足夠的數據並使用四或五折,編碼將經過這種正規化策略正常工做。 只是要當心並使用正確的驗證。
$$\frac{mean(target)nrows + globalmeanalpha}{nrows+alpha}$$
它具備控制正則化量的超參數alpha。 當alpha爲零時,咱們沒有正則化,而且當alpha接近無窮大時,一切都變成了globalmean。
在某種意義上,alpha等於咱們能夠信任的類別大小。也可使用其餘一些公式,基本上任何懲罰編碼類別的東西均可以被認爲是smoothing
。
經過添加噪聲,會下降訓練數據的編碼質量。這種方法很不穩定,很難使它工做。主要問題在於咱們須要添加的噪聲量。
太多的噪聲會把這個特徵變成垃圾,雖然噪聲過小意味着更正規化。你須要努力地微調它。
這種方法一般與LOO正則化一塊兒使用。若是你沒有不少時間,它可能不是最好選擇。
代碼例子
cumsum = df_tr.groupby(col)['target'].cumsum() - df_tr['target'] cumcnt = df_tr.groupby(col).cumcount() train_new[col + '_mean_target'] = cusum/cumcnt
cumsum存儲目標變量的累計和,直到給定行,cumcnt存儲累積計數。該方法引入的目標變量的泄漏量最少,惟一的缺點是特徵質量不均勻。但這不是什麼大不了的事,咱們能夠從不一樣的數據排列計算編碼的平均模型。
它被用於CatBoost庫中,證實了它在分類數據集上表現很是出色。
Mean encoding
User_id | APPS | Target |
---|---|---|
10 | APP1;APP2;APP3 | 0 |
11 | APP4;APP1 | 1 |
12 | APP2 | 1 |
100 | APP3;APP9 | 0 |
如今考慮一個例子,基於用在智能手機上已裝的APP,預測它是否會安裝,這是一個二分類任務。從表中數據可知,每一個用戶可能有多個應用程序,每一個應用程序由多個用戶使用,所以這是多對多的關係。而麻煩在於,如何從多對多的關係中提取均值。
User_id | APP_id | Target |
---|---|---|
10 | APP1 | 0 |
10 | APP2 | 0 |
10 | APP3 | 0 |
11 | APP4 | 1 |
11 | APP1 | 1 |
把原始數據轉爲長數據表示,如上表。使用此表,咱們能夠天然地計算APP的均值編碼
。可是如何將其映射回用戶呢?
每一個用戶都有許多APP,但不都是「APP1,APP2,APP3」。所以咱們用向量表示(0.1,0.2,0.1),咱們還能夠從向量中收集各類統計數據,好比均值、標準差、最大最小值等等。
一方面,這是一種限制,另外一方面,它容許咱們只作一些複雜的特徵。考慮一個例子:
Day | User | Spend | Amount | Prev_user | Prev_spend_avg |
---|---|---|---|---|---|
1 | 101 | FOOD | 2.0 | 0.0 | 0.0 |
1 | 101 | GAS | 4.0 | 0.0 | 0.0 |
1 | 102 | FOOD | 3.0 | 0.0 | 0.0 |
2 | 101 | GAS | 4.0 | 6.0 | 4.0 |
2 | 101 | TV | 8.0 | 6.0 | 0.0 |
2 | 102 | FOOD | 2.0 | 3.0 | 2.5 |
咱們須要預測用戶會爲哪一個類別花錢。 咱們有兩天的時間,兩個用戶, 和三個支出類別。 一些好的特徵是用戶在前一天消費總額,全部用戶在給定類別中花費的平均金額。 所以,在第1天,用戶101花費6美圓,用戶102花費$3。 所以,咱們認爲這些數字是第2天的將來值。 一樣,能夠按類別劃分平均金額。
咱們擁有的數據越多,能夠創造的特徵就越複雜。
在實踐中,一般須要編碼數字特徵以及進行特徵組合。要對數字特徵進行編碼,咱們只須要對其進行分區,而後將其視爲分類。咱們以沒有進行任何編碼的原始特徵和決策樹模型爲例。
如何爲數字特徵分組?
若是數字特徵有不少分裂點,則表示它於目標有一些複雜的依賴,而且試圖去編碼它。此外這些精確的分裂點可用於對特徵進行分類,因此經過分析模型結構,咱們既能夠識別這些可疑的數字特徵,又能夠找到很好的方法去給它分組。
如何挑選特徵組合?
先看決策樹中如何提取交互特徵。參照上圖,若是兩個特徵在相鄰的節點中,則這兩個特徵在相互做用。考慮到這點,咱們能夠遍歷模型中的全部樹,計算每一個特徵組合出現的次數。最多見的組合可能值得進行均值編碼。
例如,若是咱們發現feature1
和feature2
這一對特徵最多見,咱們能夠在數據中鏈接這些特徵,這意味編碼產生交互。