其中count encoder,one-hot encoder,label encoder主要針對低基數無序特征,比如性別。可以采用target encoder或者mean encoder的方法來針對高基數無序特征,比如地區,郵編等
一、Label Encoding
LabelEncoder() 將轉換成連續的數值型變量。即是對不連續的數字或者文本進行編號,我們知道,梯度提升樹模型是無法對此類特征進行處理的。直接將其輸入到模型就會報錯。而這個時候最為常見的就是使用LabelEncoder對其進行編碼。LabelEncoder可以將類型為object的變量轉變為數值形式
from sklearn.preprocessing import LabelEncoder le = LabelEncoder() city_list = ["paris", "paris", "tokyo", "amsterdam"] le.fit(city_list) print(le.classes_) # 輸出為:['amsterdam' 'paris' 'tokyo'] city_list_le = le.transform(city_list) # 進行Encode print(city_list_le) # 輸出為:[1 1 2 0] city_list_new = le.inverse_transform(city_list_le) # 進行decode print(city_list_new) # 輸出為:['paris' 'paris' 'tokyo' 'amsterdam']
Label encoding在某些情況下很有用,但是場景限制很多。再舉一例:比如有[dog,cat,dog,mouse,cat],我們把其轉換為[1,2,1,3,2]。這里就產生了一個奇怪的現象:dog和mouse的平均值是cat。所以目前還沒有發現標簽編碼的廣泛使用
Pandas的factorize()可以將Series中的標稱型數據映射稱為一組數字
import numpy as np import pandas as pd df = pd.DataFrame(['green','bule','red','bule','green'],columns=['color']) pd.factorize(df['color']) #(array([0, 1, 2, 1, 0], dtype=int64),Index(['green', 'bule', 'red'], dtype='object')) pd.factorize(df['color'])[0] #array([0, 1, 2, 1, 0], dtype=int64) pd.factorize(df['color'])[1] #Index(['green', 'bule', 'red'], dtype='object')
Label Encoding只是將文本轉化為數值,並沒有解決文本特征的問題:所有的標簽都變成了數字,算法模型直接將根據其距離來考慮相似的數字,而不考慮標簽的具體含義。使用該方法處理后的數據適合支持類別性質的算法模型,如LightGBM
LabelEncoder默認會先將object類型的變量進行排序,然后按照大小順序進行的編碼,此處N為該特征中不同變量的個數。幾乎所有的賽題中都會這么做,這樣做我們就可以將轉化后的特征輸入到模型,雖然這並不是模型最喜歡的形式,但是至少也可以吸收10%左右的信息,會總直接丟棄該變量的信息好很多。
模板代碼如下:
from sklearn import preprocessing df = pd.DataFrame({'color':['red','blue','black','green']}) le = preprocessing.LabelEncoder() le.fit(df['color'].values) df['color_labelencode'] = le.transform(df['color'].values) df
二、One-Hot Encoding
在實際的機器學習的應用任務中,特征有時候並不總是連續值,有可能是一些分類值,如性別可分為male和female。在機器學習任務中,對於這樣的特征,通常我們需要對其進行特征數字化,比如有如下三個特征屬性:
- 性別:[“male”,”female”]
- 地區:[“Europe”,”US”,”Asia”]
- 瀏覽器:[“Firefox”,”Chrome”,”Safari”,”Internet Explorer”]
對於某一個樣本,如[“male”,”US”,”Internet Explorer”],我們需要將這個分類值的特征數字化,最直接的方法,我們可以采用序列化的方式:[0,1,3]。但是,即使轉化為數字表示后,上述數據也不能直接用在我們的分類器中。因為,分類器往往默認數據是連續的,並且是有序的。按照上述的表示,數字並不是有序的,而是隨機分配的。這樣的特征處理並不能直接放入機器學習算法中。
為了解決上述問題,其中一種可能的解決方法是采用獨熱編碼(One-Hot Encoding)。獨熱編碼,又稱為一位有效編碼。其方法是使用N位狀態寄存器來對N個狀態進行編碼,每個狀態都由他獨立的寄存器位,並且在任意時候,其中只有一位有效。可以這樣理解,對於每一個特征,如果它有m個可能值,那么經過獨熱編碼后,就變成了m個二元特征。並且,這些特征互斥,每次只有一個激活。因此,數據會變成稀疏的。
對於上述的問題,性別的屬性是二維的,同理,地區是三維的,瀏覽器則是四維的,這樣,我們可以采用One-Hot編碼的方式對上述的樣本[“male”,”US”,”Internet Explorer”]編碼,male則對應着[1,0],同理US對應着[0,1,0],Internet Explorer對應着[0,0,0,1]。則完整的特征數字化的結果為:[1,0,0,1,0,0,0,0,1]。
為什么能使用One-Hot Encoding
- 使用one-hot編碼,將離散特征的取值擴展到了歐式空間,離散特征的某個取值就對應歐式空間的某個點。在回歸,分類,聚類等機器學習算法中,特征之間距離的計算或相似度的計算是非常重要的,而我們常用的距離或相似度的計算都是在歐式空間的相似度計算,計算余弦相似性,也是基於的歐式空間。
- 將離散型特征使用one-hot編碼,可以會讓特征之間的距離計算更加合理。比如,有一個離散型特征,代表工作類型,該離散型特征,共有三個取值,不使用one-hot編碼,計算出來的特征的距離是不合理。那如果使用one-hot編碼,顯得更合理。
獨熱編碼優缺點
- 優點:獨熱編碼解決了分類器不好處理屬性數據的問題,在一定程度上也起到了擴充特征的作用。它的值只有0和1,不同的類型存儲在垂直的空間。
- 缺點:當類別的數量很多時,特征空間會變得非常大。在這種情況下,一般可以用PCA(主成分分析)來減少維度。而且One-Hot Encoding+PCA這種組合在實際中也非常有用
One-Hot Encoding的使用場景
- 獨熱編碼用來解決類別型數據的離散值問題。將離散型特征進行one-hot編碼的作用,是為了讓距離計算更合理,但如果特征是離散的,並且不用one-hot編碼就可以很合理的計算出距離,那么就沒必要進行one-hot編碼,比如,該離散特征共有1000個取值,我們分成兩組,分別是400和600,兩個小組之間的距離有合適的定義,組內的距離也有合適的定義,那就沒必要用one-hot 編碼。
- 基於樹的方法是不需要進行特征的歸一化,例如隨機森林,bagging 和 boosting等。對於決策樹來說,one-hot的本質是增加樹的深度,決策樹是沒有特征大小的概念的,只有特征處於他分布的哪一部分的概念
再插一個
五. 什么情況下(不)需要歸一化?
- 需要: 基於參數的模型或基於距離的模型,都是要進行特征的歸一化。
- 不需要:基於樹的方法是不需要進行特征的歸一化,例如隨機森林,bagging 和 boosting等。
模板代碼
from sklearn import preprocessing df = pd.DataFrame({'color':['red','blue','black','green']}) pd.get_dummies(df['color'].values)
三、Frequency編碼
Frequency編碼是數據競賽中使用最為廣泛的技術,在90%以上的數據建模的問題中都可以帶來提升。因為在很多的時候,頻率的信息與我們的目標變量往往存在有一定關聯,例如:
- 在音樂推薦問題中,對於樂曲進行Frequency編碼可以反映該樂曲的熱度,而熱度高的樂曲往往更受大家的歡迎;
- 在購物推薦問題中,對於商品進行Frequency編碼可以反映該商品的熱度,而熱度高的商品大家也更樂於購買;
- 微軟設備被攻擊概率問題中,預測設備受攻擊的概率,那么設備安裝的軟件是非常重要的信息,此時安裝軟件的count編碼可以反映該軟件的流行度,越流行的產品的受眾越多,那么黑客往往會傾向對此類產品進行攻擊,這樣黑客往往可以獲得更多的利益
Frequency編碼通過計算特征變量中每個值的出現次數來表示該特征的信息,詳細的案例如下所示:
在很多實踐問題中,Count編碼往往可以給模型的效果帶來不錯的幫助
from sklearn import preprocessing df = pd.DataFrame({'color':['red','red','red','blue','blue','black','green','green','green']}) df['color_cnt'] = df['color'].map(df['color'].value_counts()) df
======================================================================================================================
- label encoding
- 特征存在內在順序 (ordinal feature)
- one hot encoding
- 特征無內在順序,category數量 < 4
- target encoding (mean encoding, likelihood encoding, impact encoding)
- 特征無內在順序,category數量 > 4
- beta target encoding
- 特征無內在順序,category數量 > 4, K-fold cross validation
- 不做處理(模型自動編碼)
- CatBoost,lightgbm