機器學習“特徵編碼”的經驗分享:魚還是熊掌?

路遠發表於2019-02-16

作者:xiaoyu

微信公眾號:Python資料科學

知乎:python資料分析師


1. 為什麼要進行特徵編碼?

我們拿到的資料通常比較髒亂,可能會帶有各種非數字特殊符號,比如中文。下面這個表中顯示了我們最原始的資料集。而實際上機器學習模型需要的資料是數字型的,因為只有數字型別才能進行計算。因此,對於各種特殊的特徵值,我們都需要對其進行相應的編碼,也是量化的過程。

2. 特徵編碼型別

本篇,我們主要說一下分型別特徵的編碼方式。對於分型別資料的編碼,我們通常會使用兩種方式來實現,分別是:one-hot encoding 和 label-encoding。下面我們先介紹一下這兩種編碼。

One-hot encoding

one-hot encoding也就是我們常常聽到的獨熱編碼(啞變數)。那麼到底什麼是獨熱編碼呢?我們來看一個例子,是二手房房價分析中所使用的資料:

可以看到,圖中的ElevatorRenovation都是定型別資料。除去缺失值,Elevator分類有電梯和無電梯兩種。Renovation分為有精裝,簡裝,毛坯和其它四種。下面,我們要對Elevator這個變數進行編碼,在pandas中有現成的獨熱編碼方法get_dummy,程式碼如下:

pd.get_dummies(lianjia_df[`Elevator`])

原來的Elevator變數被拆分為兩個單獨的變數,這兩個變數就是原來的分類特徵值:有電梯和無電梯。並且新變數的特徵值用數字0和1來替代,代表是否或者有無的概念。比如無電梯變數的1代表是(沒有電梯),相反,0就代表否(有電梯)。因此概括一下,獨熱編碼就是將原始特徵變數轉換成以原始特徵值分類的多維度的變數,並用是否(0,1)這種方式的新特徵值替代和量化

Label encoding

label-encoding就是用標籤進行編碼的意思,即我們給特徵變數自定義數字標籤,量化特徵。來看一個例子:

Class=[`大一`,`大二`,`大三`,`大四`]
df = pd.DataFrame({`Class`:Class})
df

Class特徵是定序資料型別,也是分類型別,但比定類更高階,因為有排序。Label encoding就是對特徵值進行自定義式的標籤編碼。比如將大一變為1,大二變為2,大三為3,大四為4。那麼經過編碼後,特徵值將變為以下的樣子:

classMap = {`大一`:1,`大二`:2,`大三`:3,`大四`:4}
df[`Class`] = df[`Class`].map(classMap)
df

上面就將Class特徵進行相應的編碼。其實,Label encoding並沒有任何限制,你也可以將Class定義為10,20,30,40,只不過1,2,3,4看起來比較方便。因此總結概括,Label encoding就是將原始特徵值編碼為自定義的數字標籤完成量化編碼過程。

3. 兩種編碼方式的優缺點

One-hot encoding

  • 優點:解決了分類器不好處理分類資料的問題,在一定程度上也起到了擴充特徵的作用。它的值只有0和1,不同的型別儲存在垂直的空間。
  • 缺點:當類別的數量很多時,特徵空間會變得非常大,容易造成維度災難。

Label encoding

  • 優點:解決了分類編碼的問題,可以自由定義量化數字。但其實也是缺點,因為數值本身沒有任何含義,只是排序。如大中小編碼為123,也可以編碼為321,即數值沒有意義。
  • 缺點:可解釋性比較差。比如有[dog,cat,dog,mouse,cat],我們把其轉換為[1,2,1,3,2],這裡就產生了一個奇怪的現象:dog和mouse的平均值是cat。因此,Label encoding編碼其實並沒有很寬的應用場景。

4. 兩種編碼該如何區分和使用?

明白這兩種編碼方式並不難,難的是如何區分和使用。好多朋友面對資料,會產生困惑,不知該使用哪種編碼方式最為合適。對於這個問題,有以下幾點需要考量:

  • 特徵的資料型別
  • 所要使用的模型

事先宣告:編碼方式沒有固定的方式,具體問題還需具體分析。對模型結果有利的編碼才是最正確的。所以,實際中如果分不清哪種更好的時候,可能需要將兩種都嘗試進行對比。

下面分享一下自己淺顯的經驗(一般情況下的使用):

特徵資料型別

  • 對於定類型別的資料,建議使用one-hot encoding。定類型別就是純分類,不排序,沒有邏輯關係。比如性別分男和女,男女不存在任何邏輯關係,我們不能說男就比女好,或者相反。再者,中國各省市分類也可以用獨熱編碼,同樣各省不存在邏輯關係,這時候使用one-hot encoding會合適些。但注意,一般會捨去一個變數,比如男的對立面肯定是女,那麼女就是重複資訊,所以保留其中一個變數即可。
  • 對於定序型別的資料,建議使用label encoding。定序型別也是分類,但有排序邏輯關係,等級上高於定類。比如,學歷分小學,初中,高中,本科,研究生,各個類別之間存在一定的邏輯,顯然研究生學歷是最高的,小學最低。這時候使用Label encoding會顯得更合適,因為自定義的數字順序可以不破壞原有邏輯,並與這個邏輯相對應。

所使用的模型

  • 對數值大小敏感的模型必須使用one-hotencoding。典型的例子就是LR和SVM。二者的損失函式對數值大小是敏感的,並且變數間的數值大小是有比較意義的。而Label encoding的數字編碼沒有數值大小的含義,只是一種排序,因此對於這些模型都使用one-hot encoding。
  • 對數值大小不敏感的模型(如樹模型)不建議使用one-hotencoding。一般這類模型為樹模型。如果分類類別特別多,那麼one-hot encoding會分裂出很多特徵變數。這時候,如果我們限制了樹模型的深度而不能向下分裂的話,一些特徵變數可能就因為模型無法繼續分裂而被捨棄損失掉了。因此,此種情況下可以考慮使用Label encoding。

以上兩點考量需要綜合考慮,而非單獨判斷。也就是說需要結合資料型別和模型的情況來具體選擇編碼方式。

5. 總結

以上是博主對於兩種編碼方式的一些理解,如果有什麼不對或者需要補充的地方,請大家指正。而對於連續型的變數,如果需要編碼首先需要進行離散化(分箱),然後再使用上述編碼方式編碼。資料離散化的內容我們後續進行介紹。

關注微信公眾號:Python資料科學,發現更多精彩內容。

相關文章