上個單元,我們介紹了很好用的LabelEncodr, 可以自動將類別型特徵轉換成數值型特徵。已經有了這麼方便的工具,為什麼我們還要多學一個OneHotEncoder呢? 先說結論,LabelEncoder適合有序型的類別型資料,如衣服大小(S,M,L)這種類別之間其實是有程度差異的資料。而OneHotEncoder則是適用在無序型的類別型資料,如性別、國家等等。
在LabelEncoder中,我們會自動把類別型資料轉換成0,1,2,…的數值標籤,這些數字僅是我們用來辨別用的,然而,對於模型來說,卻有著0<1<2…這樣的意涵。因此,當我們類別型的特徵有著順序的關係,如大小、或是我們上次範例中的weather,feeling等等有著程度上的差異,就很適合採用LabelEncoder! 然而,當我們的類別型特徵之間沒有順序關係的話,0,1,2,…這樣的數值標籤則容易讓模型產生誤解。因此,更好的做法就是將這些特徵轉換成二元特徵,意即每個類別都是一個新的特徵,是這個類別就給1,不是就給0,這就是所謂的OneHotEncoder!
以我們上個單元的範例為例,我們在特徵中再加入一個區域特徵(Area)。很顯然的,這個區域特徵為無序的特徵,因此我們可以採用OneHotEncoder來做轉換!
OneHotEncoder
我們可以從sklearn所提供的preprocessing模組裡面引入這個自動標籤功能。
import pandas as pd
from sklearn.preprocessing import OneHotEncoder
from sklearn.preprocessing import LabelEncoder
1. 預先處理
值得注意的是,OneHotEncoder無法直接轉換字串資料。因此我們可以透過上個單元學到的LabelEncoder先將字串資料轉換成數值,之後再將數值資料轉換成二元的特徵資料。
le=LabelEncoder()
for col in df[[‘Area’,’weather’,’feeling’]]:
df[col]=le.fit_transform(df[col])
2. 自動轉換成二元資料
緊接著,我們透過OneHotEncoder把數值型的類別資料轉換成二元資料。
df_ohe=enc.fit_transform(df).toarray()
pd.DataFrame(df_ohe)
另外,其實我們也可以透過參數categorical_features來設定我們想要轉換的特徵,不必每個特徵都做轉換。比方說,觀察我們現有的資料中,其實只有特徵weather為非二元的類別型資料,其他類別型資料其實早就是二元的了! 因此,我們就可以透過categorical_features的設定來限制我們只要將weather這個特徵做one hot encoding.
enc_1=OneHotEncoder(categorical_features=[1])
df_ohe=enc_1.fit_transform(df).toarray()
pd.DataFrame(df_ohe)
get_dummies
另外,在處理金融資料時,大多數我們都會採用pandas。在pandas中,我們可以透過get_dummies()直接將類別型資料轉換成二元的數值型資料,不需再透過LabelEncoder先將類別型資料轉換成數值型,再將其轉換成二元數值型。
df_dum=pd.get_dummies(df)
同樣的,我們也可以透過columns的選取來決定我們想要做one hot encoding的特徵。值得注意的是,這邊其實就回歸pandas的基本語法,只會顯示出我們抓出來的columns。因此如果沒有被轉換的特徵仍然是我們需要的特徵,最後只要再多一個合併回去的動作即可。
df_dum=pd.get_dummies(df[['Area','weather']])
df_new=pd.concat([df_dum,df['temperature']],axis=1)
總結
OneHotEncoder是一個將類別型資料轉換成數值型資料相當好用的一個工具,並且可以避免不相關資料被順序化的問題。從結果中我們也可以看到,當類別型資料裡面的種類愈多時,最終我們產生的特徵也會大量增加!當特徵數過多,也很有可能讓我們面臨維度災難的問題。因此,當特徵數較多的情況下,還是會建議將自動化標籤這件事情分開處理。有序的類別特徵採用LabelEncoder,無序的類別特徵採用OneHotEncoder. 另外,如果類別本身就是二元的類別如男女、大小、冷熱、高低等等的類別型特徵,也可以直接採用LabelEncoder就可以了。有效的處理特徵,不但可以降低我們面臨維度災難的風險,更可能讓模型精度更加提升唷!
程式檔案,歡迎於此下載。