概要
在 sklearn 包中,OneHotEncoder 函數非常實用,它可以實現將分類特征的每個元素轉化為一個可以用來計算的值。本篇詳細講解該函數的用法,也可以參考官網 sklearn.preprocessing.OneHotEncoder。
解析
該函數在 sklearn.preprocessing
類中,格式為:
OneHotEncoder(n_values=’auto’, categorical_features=’all’, dtype=<class ‘numpy.float64’>, sparse=True, handle_unknown=’error’)
為了方便理解,我們先看下面一個例子:
# -*- coding: utf-8 -*-
from sklearn.preprocessing import OneHotEncoder
enc = OneHotEncoder()
enc.fit([[0, 0, 3],
[1, 1, 0],
[0, 2, 1],
[1, 0, 2]])
ans = enc.transform([[0, 1, 3]]).toarray() # 如果不加 toarray() 的話,輸出的是稀疏的存儲格式,即索引加值的形式,也可以通過參數指定 sparse = False 來達到同樣的效果
print(ans) # 輸出 [[ 1. 0. 0. 1. 0. 0. 0. 0. 1.]]
下面解釋輸出結果的意思。對於輸入數組,這依舊是把每一行當作一個樣本,每一列當作一個特征,
- 我們先來看第一個特征,即第一列 \([0, 1, 0, 1]\),也就是說它有兩個取值 0 或者 1,那么 one-hot 就會使用兩位來表示這個特征,\([1,0]\) 表示 0, \([0,1]\) 表示 1,在上例輸出結果中的前兩位 \([1,0...]\) 也就是表示該特征為 0
- 第二個特征,第二列 \([0,1,2,0]\),它有三種值,那么 one-hot 就會使用三位來表示這個特征,\([1,0,0]\) 表示 0, \([0,1,0]\) 表示 1,\([0,0,1]\) 表示 2,在上例輸出結果中的第三位到第六位 \([...0,1,0,0...]\) 也就是表示該特征為 1
- 第二個特征,第三列 \([3,0,1,2]\),它有四種值,那么 one-hot 就會使用四位來表示這個特征,\([1,0,0,0]\) 表示 0, \([0,1,0,0]\) 表示 1,\([0,0,1,0]\) 表示 2,\([0,0,0,1]\) 表示 3,在上例輸出結果中的最后四位 \([...0,0,0,1]\) 也就是表示該特征為 3
好了,到此相信我們已經很明白它的意思了。值得注意的是,雖然訓練樣本中的數值僅僅代表類別,但是也必須使用數值格式的數據,如果使用字符串格式的數據會報錯。
下面解釋一下函數中參數的意思,
n_values=’auto’
,表示每個特征使用幾維的數值由數據集自動推斷,即幾種類別就使用幾位來表示。當然也可以自己指定,看下面這個例子:
# -*- coding: utf-8 -*-
from sklearn.preprocessing import OneHotEncoder
enc = OneHotEncoder(n_values = [2, 3, 4])
enc.fit([[0, 0, 3],
[1, 1, 0]])
ans = enc.transform([[0, 2, 3]]).toarray()
print(ans) # 輸出 [[ 1. 0. 0. 0. 1. 0. 0. 0. 1.]]
注意到訓練樣本中第二個特征列沒有類別 2,但是結果中依然將類別 2 給編碼了出來,這就是自己指定維數的作用了(我們使用 3 位來表示第二個特征,自然包括了類別 2),第三列特征同樣如此。這也告誡我們,如果訓練樣本中有丟失的分類特征值,我們就必須顯示地設置參數 n_values
了,這樣防止編碼出錯。
categorical_features = 'all'
,這個參數指定了對哪些特征進行編碼,默認對所有類別都進行編碼。也可以自己指定選擇哪些特征,通過索引或者 bool 值來指定,看下例:
# -*- coding: utf-8 -*-
from sklearn.preprocessing import OneHotEncoder
enc = OneHotEncoder(categorical_features = [0,2]) # 等價於 [True, False, True]
enc.fit([[0, 0, 3],
[1, 1, 0],
[0, 2, 1],
[1, 0, 2]])
ans = enc.transform([[0, 2, 3]]).toarray()
print(ans) # 輸出 [[ 1. 0. 0. 0. 0. 1. 2.]]
輸出結果中前兩位 \([1,0]\) 表示 0,中間四位 \([0,0,0,1]\) 表示對第三個特征 3 編碼,第二個特征 2 沒有進行編碼,就放在最后一位。
dtype=<class ‘numpy.float64’>
表示編碼數值格式,默認是浮點型。
sparse=True
表示編碼的格式,默認為 True,即為稀疏的格式,指定 False 則就不用 toarray() 了
handle_unknown=’error’
,其值可以指定為 "error" 或者 "ignore",即如果碰到未知的類別,是返回一個錯誤還是忽略它。
方法 transform(X)
就是對 \(X\) 進行編碼了。在實際應用中,我們更常用方法 fit_transform()
,也就是一步到位,看下例:
# -*- coding: utf-8 -*-
from sklearn.preprocessing import OneHotEncoder
enc = OneHotEncoder(sparse = False)
ans = enc.fit_transform([[0, 0, 3],
[1, 1, 0],
[0, 2, 1],
[1, 0, 2]])
print(ans) # 輸出 [[ 1. 0. 1. ..., 0. 0. 1.]
# [ 0. 1. 0. ..., 0. 0. 0.]
# [ 1. 0. 0. ..., 1. 0. 0.]
# [ 0. 1. 1. ..., 0. 1. 0.]]