機器學習中的編碼:Index編碼、OneHot編碼和Multiple編碼及其對比

一、 Index編碼

用來對離散的類型特徵進行編碼,如,不連續的數值、文本,將離散的特徵轉換成連續的數值型變量。基於索引的編碼可以起到數據歸一化的作用,如,id爲1和10000,當id作爲LR的特徵時,id爲1的用戶和id爲10000的用戶基本屬性一樣,但LR算法中10000權重過大,會導致id=1的特徵基本不起作用,必須進行歸一化,類似特徵都應單獨進行歸一化。

如特徵A取值共有9種情況,如,[1, 200, 10000, 30000, 100000],則索引編碼後爲[0, 1, 2, 3, 4]。

代碼示例:

from sklearn.preprocessing import LabelEncoder
a = [1, 200, 10000, 30000, 100000]
label_coder = LabelEncoder()
label_coder.fit(a)
b = label_coder.transform(a)
print(b)

二、 OneHot編碼

OneHot編碼也叫獨熱編碼或啞編碼,可以解決某些分類器不好處理離散屬性數據的問題,在一定長度上也起到了對特徵進行擴充的作用。

大部分算法是基於向量空間中的距離度量來進行計算的,爲了使非偏序關係的變量取值不具有偏序性,並且到圓點是等距的。使用one-hot編碼,將離散特徵的取值擴展到了歐式空間,離散特徵的某個取值就對應歐式空間的某個點。將離散型特徵使用one-hot編碼,會讓特徵之間的距離計算更加合理。離散特徵進行one-hot編碼後,編碼後的特徵,其實每一維度的特徵都可以看做是連續的特徵。跟對連續型特徵的歸一化方法一樣,對每一維特徵進行歸一化。比如歸一化到[-1,1]或歸一化到均值爲0,方差爲1。

爲什麼特徵向量要映射到歐式空間?

在迴歸,分類,聚類等機器學習算法中,特徵之間距離的計算或相似度的計算是非常重要的,而我們常用的距離或相似度的計算都是在歐式空間的相似度計算,如,計算餘弦相似性,就是基於歐式空間。

代碼示例:

from sklearn.preprocessing import OneHotEncoder
onehot_coder = OneHotEncoder()
onehot_coder.fit([[0, 0, 3], [1, 1, 0], [0, 2, 1], [1, 0, 2]])
c = onehot_coder.transform([[0, 0, 3]])
print(c.toarray())

獨熱編碼優缺點

優點:獨熱編碼解決了分類器不好處理屬性數據的問題,在一定程度上也起到了擴充特徵的作用。它的值只有0和1,不同的類型存儲在垂直的空間。

缺點:當類別的數量很多時,特徵空間會變得非常大。在這種情況下,一般可以用PCA來減少維度。而且one hot encoding+PCA這種組合在實際中也非常有用。

什麼情況下(不)用獨熱編碼?

  • 用於類別型數據的離散值。

  • 不用

    讓距離計算更合理,但如果特徵是離散的,並且不用one-hot編碼就可以很合理的計算出距離,那麼就沒必要進行one-hot編碼。 有些基於樹的算法在處理變量時,並不是基於向量空間度量,數值只是個類別符號,即沒有偏序關係,所以不用進行獨熱編碼。 Tree Model不太需要one-hot編碼: 對於決策樹來說,one-hot的本質是增加樹的深度。

總的來說,要是oneHot encoding的類別數目不太多,即升維不大,建議優先考慮。

什麼情況下(不)需要歸一化?

  • 需要

    基於參數的模型或基於距離的模型,都是要進行特徵的歸一化。

  • 不需要

    基於樹的方法不需要進行特徵的歸一化,例如隨機森林,bagging 和 boosting等。

三、 Multiple編碼

顧名思義,Multiple編碼特徵將多個屬性同時編碼到一個特徵中。在推薦場景中,單個用戶對哪些物品感興趣的特徵就是一種Multiple編碼特徵,如,表示某用戶對產品1、產品2、產品3、產品4是否感興趣,則這個特徵可能有多個取值,如用戶A對產品1和產品2感興趣,用戶B對產品1和產品4感興趣,用戶C對產品1、產品3和產品4感興趣,則用戶興趣特徵爲

用戶 UserInterests
A [1, 2]
B [1, 4]
C [1, 3, 4]

Multiple編碼採用類似oneHot編碼的形式進行編碼,根據物品種類數目,展成物品種類數目大小的向量,當某個用戶感興趣時,對應維度爲1,反之爲0,如下

用戶 UserInterests
A [1, 1, 0, 0]
B [1, 0, 0, 1]
C [1, 0, 1, 1]

代碼示例:

from sklearn.preprocessing import LabelEncoder
d = [[1, 2], [1, 4], [1, 3, 4]]  // 原始特徵
e = set()
for i in d:  // 求d中所有物品類別
    for j in i:
        e.add(j)
        
// 對d中物品進行Index編碼
label_coder = LabelEncoder()
label_coder.fit(list(e))

// 特徵[1, 2]進行編碼
f = [0]*len(e)
for i in label_coder2.transform([1, 2]):
    f[i] = 1
print(f)
//[1, 2] 轉換後爲 [1, 1, 0, 0]

如何使用Multiple編碼呢?

我們將多個屬性同時編碼到同一個特徵中,目的就是同時利用多個屬性的特徵。經過Multiple編碼後的特徵大小爲[batch_size, num_items],記作U,構建物品items的Embedding矩陣,該矩陣維度爲[num_items, embedding_size],記作V,將矩陣U和矩陣V相乘,我們就得到了大小爲[batch_size, embedding_size]的多屬性表示。

上述過程實現了多維多屬性特徵的構建,該手段在深度學習特徵工程中被廣泛應用。

四、 編碼比較

以下通過應用場景對以上3種編碼方式進行比較:

  • 當離散型特徵的方差較大,即相似特徵取值差異較大時,需要進行歸一化,可採用Index編碼;

  • 當所使用的算法基於空間向量時,需要進一步對特徵進行oneHot編碼,需要注意避免維度爆炸,當維度較大時應考慮採用降維方法,如PCA;

  • 當需要對特徵進行多維編碼時,可採用Multiple編碼,多維度多屬性特徵的構建可以在此基礎上增加Embedding的特徵得到;

參考文獻

  1. OneHotEncoder獨熱編碼和 LabelEncoder標籤編碼
  2. multi-hot編碼原理
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章