不要再做One Hot Encoding!!

Categorical feature的正確開啟方式

倢愷 Oscar
9 min readApr 15, 2021

--

One Hot Encoding,幾乎是現在所有Data Scientist或是ML Scientist在做資料前處理的時候的起手式,但是實際上在Kaggle跟ML實務上,使用One Hot Encoding的機會其實很少(最少如果你想要好的成績的話不太會這樣做),而這篇文章我就會來講解為甚麼!!

這篇文章我會介紹1. Categorical Feature的常見處理方法
2. 為甚麼One Hot Encoding不好
3. 替代方案:Frequency Encoding and Target Encoding

一、Categorical Feature的常見處理方法

一般而言我們9成的機器學習模型或是數據分析方法,我們都會要求輸入的是「Numerical Data」,也就是說我們希望每一筆Data的每一個feature都是「數值」。

簡單舉一個例子,Linear Regression的運算是把每一個 feature的數值乘上對應的weight,然後再Sum起來,如果今天我們輸入的並不是數值,那可能就會出現 「weight *黃色」這種奇怪的運算。

而這種「非數值」呈現「類別型」的feature,我們就稱為Categorical Feature。

常見的Categorical Feature例子就像是地名、人名、性別、在鐵達尼號的資料上有艙等、登船地點…,這些本質上不是數值的資料,都會呈現為Categorical Feature。

而我們一般常見處理Categorical Feature的方法有三個。

  1. Drop Categorical Feature:直接把所有Categorical Feature丟棄,只拿Numerical的部分進行訓練跟預測。
  2. Ordinal Encoding (又稱為Label Encoding):把Categorical Feature裡面的類別,轉換成0~N-1的數值。
  3. One Hot Encoding:新增N個Columns,每個Columns利用0與1表示原本的Feature是不是這個類別。

Ordinal跟One Hot Encoding的差別可以見下圖

Ordinal Encoding vs One-Hot Encoding

如果對One Hot Encoding還不熟悉的話,網路上有非常多相關教學,這部分可以再自行搜索參考資料。

順帶一提,一般而言我們認為Ordinal Encoding最大的問題是「替代成數值後,數值的大小關係是隨機的」,也就是說原本如果有三個類別「紅色/藍色/黃色」,現在被Ordinal Encoding替換掉後,會變成「0 / 1 / 2」,但是這些數值的相對關係是程式隨機給出來的。

二、為甚麼One-Hot Encoding不好

第一、最顯而易見的問題就是 One-Hot Encoding會大幅度增加我們Feature的數量。

如果我們今天對地名、人名之類的資料去做One Hot Encoding,動輒我們的資料就會變成1000維,即便是針對一些類別比較少的資料做處理,也會很容易增加個30~50維。

增加維度對大部分的ML演算法都是不好的

這也是為甚麼我之前會寫一個文章講解Feature Selection的方法,在Kaggle上,如果不想要Overfit在Training set或是Public Leaderboard的成績的話,我們大多時候會盡量把feature控制在幾十個,並且能變少就變少。

維度大的核心問題就是來自於Curse Of Dimensionality,而這會讓我們大部分的ML模型不容易收斂、不容易Generalize到其他Case,同時也會讓我們距離函數變成無意義,而導致以距離為核心的很多Clustering方法都直接爛掉。除此之外維度大也會讓我們Training需要的資源大幅度上升,計算時間變久。

第二、One-Hot Encoding會讓我們的data裡面出現非常大量的0

而非常大量的0對ML、DL的模型都非常困擾,尤其是DL的模型,假想一下,一個維度上有大量的0,就代表這個方向是非常平坦的平原,而我們在做Optimization的時候都會依賴各式各樣的「梯度」,而大量的0就會讓我們算不出梯度,所以大量的0本身對model也不好。

One-Hot Encoding還有其他各種問題,包含著很多冗餘的資訊(Feature Importance非常低),不同col可以互相predict對方導致我們很多feature independence的假設不成立…,我這裡不贅述。

三、替代方案

講了很多One-Hot Encoding的問題,接下來我就要介紹兩個在Kaggle上極為常用,並且使用難度極低的Encoding方法,通常能夠快速帶來效果。

Frequency Encoding

Frequency Encoding相當簡單,就是我們把Categorical Feature裡面每個類別出現的數量,當成他的數值。

簡單來講,一樣的例子我們今天有一個Categorical Feature裡面是「紅色/藍色/黃色」,而其中紅色出現90次、藍色出現50次、黃色出現10次,我們就把這個feature轉換成「90 / 50 / 10」,所以每一個data裡面只要這個欄位原本是紅色,就會被填入90。

Frequency Encoding其實本身假設我們收集Data時,資訊出現的頻率本身就是極有價值的事情。而這個假設在很多情況為真。

我們可以使用pandas的value_counts()來快速計算頻率

Frequency Encoding最大的問題是如果有多個類別是相同的Frequency,那我們的model就會認為他們是一樣的數值。

Target Encoding

Target Encoding又稱為mean encoding,所做的事情是,把同樣類別的資料對應「Target值」全部抓出來,並且將這些Target值的平均當成Encoding的值。

用文字敘述很饒口,下面看我的圖片

Target Encoding方法

假設我們資料總共只有6筆,裡面只有一個Feature是「顏色」,而我們要預測的Target是「價格」,Target Encoding做的事情就是把同樣顏色的資料中,所對應的所有價格算出平均,並以這個平均值當成我們Target Encoding的結果。

所以上圖藍色做完Target Encoding應該是40,而黃色應該是85

Target Encoding等於是強制把Categorical Feature跟Target的關係算出來。

但是Target Encoding也有一些使用上要注意的地方

  1. 隨時注意模型是否過於依賴Target Encoding的數值
  2. 在算Target Encoding的時候,應該要去除Outlier,不然如果mean(1, 1, 1, 1, 100),會變成20.8,跟實際的數值特性不相同。

要使用Target Encoding可以藉由Category Encoders這個Package

下載一樣非常簡單

pip install category_encoders
or
conda install -c conda-forge category_encoders

使用上也跟sklearn的oneHotEncoder一樣,藉由 .fit() 跟 .transform() 以及 .fit_transform() 三個method完成。

# use target encoding to encode two categorical features
enc = TargetEncoder(cols=['CHAS', 'RAD'])

# transform the datasets
training_numeric_dataset = enc.fit_transform(X_train, y_train)
testing_numeric_dataset = enc.transform(X_test)

而實際上基於Target Encoding,有大神在競賽中發明了更為強大的Beta Target Encoding,而Beta Target Encoding在很多比賽上都得到了非常好的效果,可參考以下blog。(之後我會再寫一篇補充比較冷門但是在有用的Categorical Encoding Methods)

看完這篇應該就要把自己pipeline裡面的One-Hot Encoding換成Frequency Encoding跟Target Encoding了,不過實際上沒有「一定好用的Encoding」,同時在Target Encoding之上還有很多改善的方法,具體還是要看Data再進行選擇。

如果喜歡這篇文章可以幫我多拍手幾次XD,或是對於哪個類型文章有興趣都可以在留言區跟我講~ 後續會以中難度的ML/DS/AI知識為主,以及AI/HCI研究相關知識

--

--

倢愷 Oscar

我是倢愷,CTO at TeraThinker an AI Adaptive Learning System Company。AI/HCI研究者,超過100場的ML、DL演講、workshop經驗。主要學習如何將AI落地於業界。 有家教、演講合作,可以email跟我聯絡:axk51013@gmail.com