表述類目的變量一般,一般沒有次序概念,且取值範圍有限。例如性別行業信用卡類型。有些模型能夠直接讀類別變量(例如決策樹)。有些模型不能識別類別變量(例如迴歸模型,神經網絡,有距離的度量模型(svn,knn))。html
當類別變量沒法放入模型的時候,須要作編碼處理即以數值的形式替代原有的值:python
- onehot編碼
- dummy
- 濃度編碼
- WOE編碼
咱們主要用onehot編碼,dummy(啞變量)操做,一般會使得咱們模型具備較強的非線性能力。網絡
那麼這兩種編碼方式是如何進行的呢?dom
它們之間是否有聯繫?機器學習
又有什麼樣的區別?svn
是如何提高模型的非線性能力的呢?性能
咱們帶着這三個疑問進入特殊變量的主題:學習
1.爲何測試
這一個迷你數據集,爲何咱們用1,2,3,4這樣的數據值不行呢,非要用00001,01000這樣的才能夠?即爲何不直接提供標籤編碼給模型訓練就夠了?爲何須要one hot編碼?編碼
標籤編碼的問題是它假定類別值越高,該類別更好。
讓我解釋一下:根據標籤編碼的類別值,咱們的迷你數據集中VW > Acura > Honda。
比方說,假設模型內部計算平均值(神經網絡中有大量加權平均運算),那麼1 + 3 = 4,4 / 2 = 2.
這意味着:VW和Honda平均一下是Acura。毫無疑問,這是一個糟糕的方案。該模型的預測會有大量偏差。
咱們使用one hot編碼器對類別進行「二進制化」操做,而後將其做爲模型訓練的特徵,緣由正在於此。
固然,若是咱們在設計網絡的時候考慮到這點,對標籤編碼的類別值進行特別處理,那就沒問題。不過,在大多數狀況下,使用one hot編碼是一個更簡單直接的方案。
若是本來的標籤編碼是有序的,那one hot編碼就不合適了——會丟失順序信息。
轉化成二進制編碼(以下圖所示):
2.怎麼用
咱們先不講各類編碼之間的差異,先講一個案例Demo,什麼編碼轉化。
import pandas pd df = pd.DataFrame({'country': ['russia', 'germany', 'australia','korea','germany']}) pd.get_dummies(df,prefix=['country'])
一些機器學習技術要求,從表示中刪除一個維度,以免變量之間的依賴性。使用「drop_first = True」來實現這一目標。
import pandas as pd # using the same example as above df = pd.DataFrame({'country': ['russia', 'germany', 'australia','korea','germany']}) pd.get_dummies(df,prefix=['country'], drop_first=True)
同時你也要修改測試集上的數據。要和訓練集保持一致才能測試的時候用。
import pandas as pd # say you want a column for "japan" too (it'll be always zero, of course) df["country"] = train_df["country"].astype('category',categories=["australia","germany","korea","russia","japan"]) # now call .get_dummies() as usual pd.get_dummies(df,prefix=['country'])
而後咱們從新關注一下訓練集,咱們剔除原來那一列被編碼的特徵同時,把編碼特徵concat回去。
df = pd.concat([df,pd.get_dummies(df['mycol'], prefix='mycol',dummy_na=True)],axis=1).drop(['mycol'],axis=1)
import pandas as pd # df now has two columns: name and country df = pd.DataFrame({ 'name': ['josef','michael','john','bawool','klaus'], 'country': ['russia', 'germany', 'australia','korea','germany'] }) # use pd.concat to join the new columns with your original dataframe df = pd.concat([df,pd.get_dummies(df['country'], prefix='country')],axis=1) # now drop the original 'country' column (you don't need it anymore) df.drop(['country'],axis=1, inplace=True)
同時咱們也能夠把數據缺失也做爲一種特徵
import pandas as pd import numpy as np df = pd.DataFrame({ 'country': ['germany',np.nan,'germany','united kingdom','america','united kingdom'] }) pd.get_dummies(df,dummy_na=True)
one-hot encoding
one-hot的基本思想:將離散型特徵的每一種取值都當作一種狀態,若你的這一特徵中有N個不相同的取值,那麼咱們就能夠將該特徵抽象成N種不一樣的狀態,one-hot編碼保證了每個取值只會使得一種狀態處於「激活態」,
也就是說這N種狀態中只有一個狀態位值爲1,其餘狀態位都是0。舉個例子,假設咱們以學歷爲例,咱們想要研究的類別爲小學、中學、大學、碩士、博士五種類別,咱們使用one-hot對其編碼就會獲得:3.what
接下來咱們詳細的講一下onehot編碼和dummy之間的區別。
兩者均可以對Categorical Variable作處理,轉換爲定量特徵,轉換爲定量特徵其實就是將原來每一個特徵的類別拿出來做爲一個新的特徵(Dummy Variable)了,
如性別——男,女,定量特徵即將男做爲一個特徵,女做爲一個特徵,若是數據中的Categorical Variable不少,且每一個Variable種類比較多,那麼轉換後的數據可能會很是稀疏。
兩者自己存在差異。
Difference:一個定性特徵或者成爲Categorical Variable,其有n個值,
Dummy Encoding 會將這個Categorical Variable轉換爲n-1個特徵變量,而OneHot Encoding會轉換爲n個特徵變量。
其中,這種轉換在經濟學或者回歸模型中會存在一個Dummy Variable Trap的問題,使用Dummy Encoder能夠避免這個問題,因爲我這裏面對的是分類問題,沒有過多的調研。
若是你還不理解我借鑑一下某個博客的例子
dummy encoding
啞變量編碼直觀的解釋就是任意的將一個狀態位去除。仍是拿上面的例子來講,咱們用4個狀態位就足夠反應上述5個類別的信息,也就是咱們僅僅使用前四個狀態位 [0,0,0,0] 就能夠表達博士了。只是由於對於一個咱們研究的樣本,他已不是小學生、也不是中學生、也不是大學生、又不是研究生,那麼咱們就能夠默認他是博士。因此,咱們用啞變量編碼能夠將上述5類表示成:
啞變量編碼去除了one-hot編碼內部線性相關的一個。這種簡化不能說到底好很差,這要看使用的場景。下面咱們以一個例子來講明:
假設咱們如今得到了一個模型,這裏自變量知足
(由於特徵是one-hot得到的,全部只有一個狀態位爲1,其餘都爲了0,因此它們加和老是等於1),
故咱們能夠用表示第三個特徵,將其帶入模型中,獲得:
這時,咱們就驚奇的發現和
這兩個參數是等價的!那麼咱們模型的穩定性就成了一個待解決的問題。這個問題這麼解決呢?有三種方法:
(1)使用正則化手段,將參數的選擇上加一個限制,就是選擇參數元素值小的那個做爲最終參數,這樣咱們獲得的參數就惟一了,模型也就穩定了。
(2)把偏置項去掉,這時咱們發現也能夠解決同一個模型參數等價的問題。
由於有了bias項,因此和咱們去掉bias項的模型是徹底不一樣的模型,不存在參數等價的問題。
(3)再加上bias項的前提下,使用啞變量編碼代替one-hot編碼,這時去除了,也就不存在以前一種特徵能夠用其餘特徵表示的問題了。
總結:咱們使用one-hot編碼時,一般咱們的模型不加bias項 或者 加上bias項而後使用正則化手段去約束參數;當咱們使用啞變量編碼時,一般咱們的模型都會加bias項,由於不加bias項會致使固有屬性的丟失。
選擇建議:最好是選擇正則化 + one-hot編碼;啞變量編碼也可使用,不過最好選擇前者。雖然啞變量能夠去除one-hot編碼的冗餘信息,可是由於每一個離散型特徵各個取值的地位都是對等的,隨意取捨未免來的太隨意。
連續值的離散化爲何會提高模型的非線性能力?
簡單的說,使用連續變量的LR模型,模型表示爲公式(1),而使用了one-hot或啞變量編碼後的模型表示爲公式(2)
式中表示連續型特徵,
、
、
分別是離散化後在使用one-hot或啞變量編碼後的若干個特徵表示。這時咱們發現使用連續值的LR模型用一個權值去管理該特徵,而one-hot後有三個權值管理了這個特徵,這樣使得參數管理的更加精細,因此這樣拓展了LR模型的非線性能力。
這樣作除了加強了模型的非線性能力外,還有什麼好處呢?這樣作了咱們至少不用再去對變量進行歸一化,也能夠加速參數的更新速度;再者使得一個很大權值管理一個特徵,拆分紅了許多小的權值管理這個特徵多個表示,這樣作下降了特徵值擾動對模型爲穩定性影響,也下降了異常數據對模型的影響,進而使得模型具備更好的魯棒性。