特征编码one-hot与dummy的区别与联系

在模型的训练过程中,我们会对数据集的连续特征进行离散化操作,如使用简单的LR模型,然后对离散化后的特征进行one-hot编码或哑变量编码。这样通常会使得我们模型具有较强的非线性能力。

one-hot编码

思想:将离散化特征的每一种取值都成是一种状态,若你的这一特征中有N个不同的取值,那么我们就可以将这些特征抽象成N种不同的状态,one-hot编码保证了每一个取值只有一种状态处于“激活态”,也就是说N种状态中只有一个状态值为1,其他状态为0。假设我们以学历为例,现有小雪、中学、大学、硕士、博士五种类别,使用one-hot编码就会得到:

特征编码one-hot与dummy的区别与联系_第1张图片

from numpy import argmax
# define input string
data = ["小学","初中","大学","硕士","博士"]
print(data)
# define universe of possible input values
alphabet = ["幼儿园","小学","初中","高中","大学","硕士","博士","博士后"]
# define a mapping of chars to integers
char_to_int = dict((c, i) for i, c in enumerate(alphabet))
int_to_char = dict((i, c) for i, c in enumerate(alphabet))
#%%
# integer encode input data
integer_encoded = [char_to_int[char] for char in data]
print(integer_encoded)
#%%
# one hot encode
onehot_encoded = list()
for value in integer_encoded:
       letter = [0 for _ in range(len(alphabet))]
       letter[value] = 1
       onehot_encoded.append(letter)
print(onehot_encoded)
#%%
# invert encoding
inverted = int_to_char[argmax(onehot_encoded[0])]
print(inverted)

python中one-hot的用法

from sklearn import preprocessing
array = np.array([[0,0,3],[1,1,0],[0,2,1],[1,0,2]])
print(array)
enc = preprocessing.OneHotEncoder()
enc.fit(array)
print(enc.n_values_) #每个特征对应的最大位数
print(enc.transform([[0,1,3]]).toarray())

array([[0, 0, 3],
       [1, 1, 0],
       [0, 2, 1],
       [1, 0, 2]])
array是一个4行3列的矩阵,每一列对应于一个样本的特征序列,即一个样本有三个特征,4行表示传入了4个样本
[2 3 4]
每个特征对应的位数:观察第一列可知,第一个特征有两个取值0,1;第二个特征有三个取值0,1,2;第三个特征有四个取值0,1,2,3
[[1. 0. 0. 1. 0. 0. 0. 0. 1.]]
故第一个特征的onehot编码是一个两位的0、1串,第二个特征是一个三位0、1串,第三个特征是一个四位的0,1串
from sklearn import preprocessing
data = ["小学","初中","大学","硕士","博士"]
dataf = ["幼儿园","小学","初中","高中","大学","硕士","博士","博士后"]
le = preprocessing.LabelEncoder()
datafm = le.fit_transform(dataf)
datam = le.fit_transform(data)
#%%
onehot = preprocessing.OneHotEncoder()
onehot.fit(datafm.reshape(-1,1))
print(onehot.n_values_)
[8]

datafm
Out[78]: array([5, 4, 0, 7, 3, 6, 1, 2], dtype=int64)

datam
Out[79]: array([3, 0, 2, 4, 1], dtype=int64)
#%%
print(onehot.transform(datam.reshape(-1,1)).toarray())

[[0. 0. 0. 1. 0. 0. 0. 0.]
 [1. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 1. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 1. 0. 0. 0.]
 [0. 1. 0. 0. 0. 0. 0. 0.]]

print(onehot.transform(datafm.reshape(-1,1)).toarray())
[[0. 0. 0. 0. 0. 1. 0. 0.]
 [0. 0. 0. 0. 1. 0. 0. 0.]
 [1. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 1.]
 [0. 0. 0. 1. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 1. 0.]
 [0. 1. 0. 0. 0. 0. 0. 0.]
 [0. 0. 1. 0. 0. 0. 0. 0.]]
print(onehot.transform(datafm.reshape(-1,1)))
  (0, 5)        1.0
  (1, 4)        1.0
  (2, 0)        1.0
  (3, 7)        1.0
  (4, 3)        1.0
  (5, 6)        1.0
  (6, 1)        1.0
  (7, 2)        1.0

在对非数值型特征进行onehot编码时需要先通过LabelEncoder()将分类变量转换成整数形式,然后通过OneHotEncoder()进行编码,否则会报错误如下ValueError: could not convert string to float: '小学'。另外再用OneHotEncoder()进行编码时需为2D array,否则会有如下错误:ValueError: Expected 2D array, got 1D array instead:
array=[3. 0. 2. 4. 1.].
Reshape your data either using array.reshape(-1, 1) if your data has a single feature or array.reshape(1, -1) if it contains a single sample. 

dummy encoding

哑变量编码直观的解释就是任意的将一个状态去除,如学位信息,使用哑变量可以用4个状态就足以反映上述5个类别的信息,也就是我们仅使用前四个状态位就可以表示博士了。因为对于我们的一个研究样本,他如果不是小学生,也不是中学生,大学生、研究生,那他便默认为博士了。所以,用哑变量可以将上述5类表示成:

特征编码one-hot与dummy的区别与联系_第2张图片

data = ["小学","初中","大学","硕士","博士"]
pd.get_dummies(data,prefix="data")

   data_初中  data_博士  data_大学  data_小学  data_硕士
0        0        0        0        1        0
1        1        0        0        0        0
2        0        0        1        0        0
3        0        0        0        0        1
4        0        1        0        0        0

 

你可能感兴趣的:(python)