词向量系列之One-Hot编码详解
⽬录
0.前⾔
  在回归,分类,聚类等机器学习算法中,各个特征之间的距离(相似度)计算是⾮常重要的,然⽽常⽤的距离计算都是在欧式空间内计算,例如计算余弦相似性。但是在欧式空间内计算相似性要求数据是连续的,有序的。在很多机器学习的任务中,数据都是离散的,例如星期⼀,星期⼆,···,星期天,⼈的性别有男⼥,祖国有中国,美国,法国等。这些特征值并不是连续的,⽽是离散的,⽆序的。
如果要作为机器学习算法的输⼊,通常我们需要对其进⾏特征数字化。什么是特征数字化呢?例如:
性别特征:["男","⼥"]
祖国特征:["中国","美国,"法国"]
运动特征:["⾜球","篮球","⽻⽑球","乒乓球"]
怎么将上诉特征数字化呢?有个⼈他的特征是 [“男”,“中国”,“乒乓球”],怎么表⽰他呢?
1. 独热编码
  独热编码即 One-Hot Encoding,⼜称⼀位有效编码,其⽅法是使⽤N位状态寄存器来对N个状态进⾏编码,每个状态都由他独⽴的寄存器位,并且在任意时候,其中只有⼀位有效。one-hot向量将类别变量转换为机器学习算法易于利⽤的⼀种形式的过程,这个向量的表⽰为⼀项属性的特征向量,也就是同⼀时间只有⼀个激活点(不为0),这个向量只有⼀个特征是不为0的,其他都是0,特别稀疏。
1.1 独热编码例⼦
例1:
  我们有四个样本,每个样本有三个特征,如图:
特征1特征2特征3样本1143
样本2232
样本3122
样本4211
上诉样本特征1有两种可能的取值,若代表性别,⽐如1代表男性2代表⼥性,特征2有4种,可以代表另⼀种特征,同样的特征3也可以有他的含义。
独热编码保证每个样本中的单个特征只有1位数字为1,其余全部为0,编码后表⽰为:
特征1特征2特征3样本1011000100
样本2100100010
样本3010010010
样本4100001001
对每个特征都使⽤独热编码表⽰,特征有2种取值就⽤两位表⽰,4种取值就⽤4位表⽰
对于前⾔中的例⼦,可以将特征与具体的特征对应:
性别特征:[“男”,“⼥”] (这⾥只有两个特征,所以 N=2):
男 => 10
⼥ => 01
祖国特征:[“中国”,"美国,“法国”](N=3):
中国 => 100
美国 => 010
法国 => 001
运动特征:[“⾜球”,“篮球”,“⽻⽑球”,“乒乓球”](N=4):
⾜球 => 1000
篮球 => 0100
⽻⽑球 => 0010
乒乓球 => 0001
所以,当⼀个样本为 [“男”,“中国”,“乒乓球”] 的时候,完整的特征数字化的结果为:
[1,0,1,0,0,0,0,0,1]
前两位代表性别,中间三位代表国家,后四位代表运动。
1.2 独热编码的优点
能够处理机器学习算法不好处理的离散特征值。
在⼀定程度上增加了特征的维度,⽐如性别本⾝是⼀个特征,经过one hot编码以后,就变成了男或⼥两个特征。
将离散特征的取值扩展到了欧式空间,离散特征的某个取值就对应欧式空间的某个点。将离散型特征使⽤one-hot编码,可以会让特征之间的距离计算更加合理。
1.3 独热编码的缺点
如果原本的标签编码是有序的,那么one-hot编码就会丢失顺序信息。
如果特征值的数⽬特别多,就会产⽣⼤量冗余的稀疏矩阵
维度(单词)间的关系没有得到体现,每个单词都是⼀个维度,彼此相互独⽴,然⽽每个单词彼此⽆关这个特点明显不符合现实情况。
⼤量的单词都是有关的。⽐如:
语义:girl和woman虽然⽤在不同年龄上,但指的都是⼥性。
复数:word和words仅仅是复数和单数的差别。
时态:buy和bought表达的都是“买”,但发⽣的时间不同。
所以⽤one hot representation的编码⽅式,上⾯的特性都没有被考虑到。
1.4 独热编码适⽤的情况
One Hot Encoding⽤来解决类别数据的离散值问题,如果特征是离散的,并且不⽤One Hot Encoding就可以很合理的计算出距离,那么就没必要进⾏One Hot Encoding。
有些基于树的算法在处理变量时,并不是基于向量空间度量,数值只是类别符号,即没有偏序关系,所以不⽤One Hot Encoding,树模型不太需要One Hot Encoding,对于决策树来说,没有特征⼤⼩的概念,只有特征处于哪个部分的概念,One Hot Encoding的本质是增加树的深度。如GBDT处理⾼维稀疏矩阵的时候效果并不好,即使是低维的稀疏矩阵也未必⽐SVM好。
2. 独热编码的实现
2.1 python简单实现one-hot编码
import numpy as np
samples =['I like playing basketball','I played football yesterday morning']
token_index ={}
for sample in samples:
for word in sample.split():
if word not in token_index:
token_index[word]=len(token_index)+1
max_length =10
results = np.zeros(shape=(len(samples),
max_length,
max(token_index.values())+1))
for i, sample in enumerate(samples):
for j, word in list(enumerate(sample.split()))[:max_length]:
print(j)
index = (word)
results[i, j, index]=1
print(results)
2.2 sklearn
通过sklearn的OneHotEncoder()来得到独热编码,但是只适⽤于数值型的数据。OneHotEncoder()的 feature_indices_ 可以知道哪⼏列对应哪个原来的特征。
使⽤ numpy.hstack() 将多次结果拼接起来得到变换后的结果
问题:不能直接编码字符串类型数据(LabelEncoder() + OneHotEncoder() 可实现,但需数据格式转换)
from sklearn import preprocessing
enc = OneHotEncoder()
enc.fit([[0,0,3],[1,1,0],[0,2,1],[1,0,2]])
print("enc.n_values_ is:",enc.n_values_)
print("enc.feature_indices_ is:",enc.feature_indices_)
ansform([[0,1,1]]).toarray())
ansform([[1,1,1]]).toarray())
ansform([[1,2,1]]).toarray())
输出的结果:
enc.n_values_ is:[234]
enc.feature_indices_ is:[0259]#特征坐标
[[1.0.0.1.0.0.1.0.0.]]
[[0.1.0.1.0.0.1.0.0.]]
enc.n_values_ is :每个特征值的特征数⽬,第⼀个特征数⽬是2,第⼆个特征数⽬是3,第三个特征数⽬是4。
enc.feature_indices_ is :表明每个特征在one-hot向量中的坐标范围,0-2 是第⼀个特征,2-5就是第⼆个特征,5-9是第三个特征。后⾯三个就是把特征值转换为 one-hot编码,我们可以对⽐结果看看one-hot差别。
2.3 Keras
from import Tokenizer
samples =['I like playing basketball','I played football yesterday morning']
tokenizer = Tokenizer(num_words=1000)
tokenizer.fit_on_texts(samples)
sequences = s_to_sequences(samples)
one_hot_results = _to_matrix(samples, mode="binary")
word_index = tokenizer.word_index
print('Found %s unique tokens.'%len(word_index))
2.4 tensorflow
官⽅⽂档:
<_hot(
indices,
depth,
on_value=None,
off_value=None,
axis=None,
dtype=None,
name=None
)
Returns a one-hot tensor(返回⼀个one_hot张量).
The locations represented by indices in indices take value on_value,while all other locations take value off_value.
(由indices指定的位置将被on_value填充,其他位置被off_value填充).
on_value and off_value must have matching data types. If dtype is also provided, they must be the same data type as specified by dtype.
(on_value和off_value必须具有相同的数据类型).
If on_value is not provided, it will default to the value 1with type dtype.
If off_value is not provided, it will default to the value 0with type dtype.
If the input indices is rank N, the output will have rank N+1. The new axis is created at dimension axis (default: the new axis is appended at the end). (如果indices是N维张量,那么函数输出将是N+1维张量,默认在最后⼀维添加新的维度).
If indices is a scalar the output shape will be a vector of length depth.
(如果indices是⼀个标量,函数输出将是⼀个长度为depth的向量)
If indices is a vector of length features, the output shape will be:
features x depth if axis ==-1.
(如果indices是⼀个长度为features的向量,则默认输出⼀个features*depth形状的张量)
depth x features if axis ==0.
(如果indices是⼀个长度为features的向量,axis=0,则输出⼀个depth*features形状的张量)
If indices is a matrix (batch)with shape [batch, features], the output shape will be:
batch x features x depth if axis ==-1
(如果indices是⼀个形状为[batch, features]的矩阵,axis=-1(默认),则输出⼀个batch * features * depth形状的张量)
batch x depth x features if axis ==1
(如果indices是⼀个形状为[batch, features]的矩阵,axis=1,则输出⼀个batch * depth * features形状的张量)
depth x batch x features if axis ==0
(如果indices是⼀个形状为[batch, features]的矩阵,axis=0,则输出⼀个depth * batch * features形状的张量)
实现:
indices =[0,1,2]#输⼊数据(是个向量)需要编码的索引是[0,1,2]
depth =3
<_hot(indices, depth)# output: [3 x 3]
# [[1., 0., 0.],
#  [0., 1., 0.],
#  [0., 0., 1.]]
indices =[0,2,-1,1]#输⼊数据(是个向量)的需要编码的索引是[0,2,-1,1]
depth =3
index复数
<_hot(indices, depth,
on_value=5.0, off_value=0.0,
axis=-1)# output: [4 x 3]
# [[5.0, 0.0, 0.0],  # one_hot(0)  对位置0处的数据进⾏one_hot编码
#  [0.0, 0.0, 5.0],  # one_hot(2)  对位置2处的数据进⾏one_hot编码
#  [0.0, 0.0, 0.0],  # one_hot(-1) 对位置-1处的数据进⾏one_hot编码
#  [0.0, 5.0, 0.0]]  # one_hot(1)  对位置1处的数据进⾏one_hot编码
indices =[[0,2],[1,-1]]#输⼊数据是个矩阵
depth =3
<_hot(indices, depth,
on_value=1.0, off_value=0.0,
axis=-1)# output: [2 x 2 x 3]
# [[[1.0, 0.0, 0.0],  # one_hot(0)  对位置(0,0)处的数据进⾏one_hot编码
#  [0.0, 0.0, 1.0]],  # one_hot(2)  对位置(0,2)处的数据进⾏one_hot编码
#  [[0.0, 1.0, 0.0],  # one_hot(1)  对位置(1,1)处的数据进⾏one_hot编码
#  [0.0, 0.0, 0.0]]]  # one_hot(-1) 对位置(1,-1)处的数据进⾏one_hot编码
3 NLP中的独热表⽰
独热表⽰以往在NLP中很流⾏,但是随着TF-IDF以及词向量的出现,已经渐渐变得不再适⽤了,主要的缺点:
不考虑词与词之间的顺序(⽂本中词的顺序信息也是很重要的);
2
假设词与词相互独⽴,每个词之间的距离都是。(在⼤多数情况下,词与词是相互影响的);
它得到的 特征是离散稀疏的,词表多少个单词,向量的维度就是多少。 (这个问题最严重)。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。