机器学习算法不能直接处理分类数据,分类数据必须转换为数字。这适用于当你处理一个序列分类类型的问题,并计划使用深度学习方法,比如长短期循环神经网络RNN时。
在本教程中,您将了解如何将您的输入或输出序列数据转换为一个独热编码(one-hot code),以便在Python中深度学习的序列分类问题中使用。
教程概述
本教程分为四个部分:
- 独热编码是什么?
- 手动独热编码
- 独热编码和scikit-learn
- 独热编码与Keras
独热编码是什么?
独热编码是将分类变量表示为二进制向量。这首先要求将分类值映射到整数值。它是除了整数1以外其他全都是零值的码制。
独热编码举例
假设我们有一系列的标签,其中有“红色”和“绿色”。我们可以将“红色”的整数值赋值为0和“绿色”的整数值赋值为1。只要我们总是把这些数字赋值成这类标签,那么这就叫做整数编码。一致性很重要,因此我们可以稍后对编码进行转换,并从整数值中获得标签。
接下来,我们可以创建一个二元向量来表示每个整数值。向量的长度为2,为2个可能的整数值。被编码为0的“红色”标签将被表示为二进制向量[1, 0]。反过来,编码为1的“绿色”标签将以二进制向量0表示。
如果我们有序列:
'red', 'red', 'green'
我们可以用整数编码来表示它:
0, 0, 1
独热编码为:
[1, 0]
[1, 0]
[0, 1]
为什么用一个独热编码?
独热编码使分类数据的表示变得更有表现力。许多机器学习算法不能直接使用分类数据。分类必须转换成数字。这对于分类的输入和输出变量来说都是必需的。
我们可以直接使用整数编码,并在需要的地方进行重新编码。这可能适用于类别和整数值之间存在自然顺序关系的问题,比如温度“cold”、“warm”和“hot”这类的标签。在没有顺序关系的情况下,可能会出现一些问题,并且允许这种表现倾向于任何关系,可能会破坏学习解决问题的能力。一个例子可能是标签上的“dog”和“cat”
在这些情况下,我们希望给网络提供更多的表达能力,以便为每个可能的标签值学习一个概率数字。这同时也可以帮助解决网络模型的问题。当一个独热编码用于输出变量时,它可能提供比单个标签更细致的预测。
手动独热编码
在本例中,我们假设有一个字母中的字符的示例字符串(string),但示例序列不包括所有可能的示例。
我们将使用下列字符的输入序列:
hello world
我们假设所有可能输入的“universe(宇宙)”是小写字母的完整字母表,还有“space(空间)”。因此,我们将以此作为一个借口来演示如何滚动我们自己的独热编码。
完整的例子如下文所列:
from numpy import argmax
# define input string
data = 'hello world'
print(data)
# define universe of possible input values
alphabet = 'abcdefghijklmnopqrstuvwxyz '
# 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)
运行该示例首先打印输入string。
所有可能输入的映射都是从char values创建到整数值的。然后,该映射用于对输入string进行编码。我们可以看到,在输入'h'时的第一个字母被编码为7,或者是在可能输入值(字母表)数组中的index 7。
然后将整数编码转换为独热编码。一次完成一个整数编码的字符。一个0值的列表被创建成字母表的长度,这样任何期望的字符都可以被表示出来。
接下来,特定字符的index标记为1。我们可以看到,第一个字母“h”整数编码为7,由一个长度为27的二进制向量和标记为1的7th index表示。
最后,我们对第一个字母的编码进行转换,然后打印结果。我们通过使用NumPy argmax()函数查找具有最大值的二进制向量的index,然后在字符值变整数的反向查找表中来使用整数值。
注释:输出被格式化是为了便于阅读
hello world
[7, 4, 11, 11, 14, 26, 22, 14, 17, 11, 3]
[[0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]
h
既然我们已经了解了如何从头开始滚动自己的独热编码,那么让我们看看如何使用scikit-learn库来自动执行这个映射,在输入序列完全捕获了预期的输入值范围的情况下。
独热编码和scikit-learn
在本例中,我们将假设您有以下3个标签的输出序列:
"cold"
"warm"
"hot"
10个时间步长的示例序列可能是:
cold, cold, warm, cold, hot, hot, warm, cold, warm, hot
这首先需要一个整数编码,比如1、2、3。然后是整数独热编码的整数到一个有3个值的二元向量,比如[1, 0, 0]。序列至少提供了序列中每个可能值的一个例子。因此,我们可以使用自动的方法来定义标签的映射到整数和整数到二进制的向量。
在本例中,我们将使用来自scikit-learn库的编码器,具体来说,创建一个标签的整数编码的
LabelEncoder和用
OneHotEncoder 来创建整数编码值的独热编码。
完整的示例如下所示:
from numpy import array
from numpy import argmax
from sklearn.preprocessing import LabelEncoder
from sklearn.preprocessing import OneHotEncoder
# define example
data = ['cold', 'cold', 'warm', 'cold', 'hot', 'hot', 'warm', 'cold', 'warm', 'hot']
values = array(data)
print(values)
# integer encode
label_encoder = LabelEncoder()
integer_encoded = label_encoder.fit_transform(values)
print(integer_encoded)
# binary encode
onehot_encoder = OneHotEncoder(sparse=False)
integer_encoded = integer_encoded.reshape(len(integer_encoded), 1)
onehot_encoded = onehot_encoder.fit_transform(integer_encoded)
print(onehot_encoded)
# invert first example
inverted = label_encoder.inverse_transform([argmax(onehot_encoded[0, :])])
print(inverted)
运行示例首先打印标签序列。这之后是标签的整数编码,最后是一个独热编码。培训数据包含所有可能示例的集合,因此我们可以依赖于整数和独热编码转换,从而创建一个完整的分类到编码的映射。
默认情况下,OneHotEncoder类将返回更高效的sparse编码。这可能不适用于某些应用程序,例如使用Keras深度学习库。在这种情况下,我们通过设置sparse = False参数来禁用sparse返回类型。
如果我们在这个3-value的独热编码中收到一个预测,我们可以很容易地将变换反转回原始标记。首先,我们可以使用argmax()NumPy函数来定位具有最大值的列的索引。然后可以将其输入到LabelEncoder中,以计算返回到文本标签的逆转换。示例末尾演示了第一个独热编码示例的逆转换返回到标签值“cold”的过程。
再次强调,输入是为了可读性而格式化的。
['cold' 'cold' 'warm' 'cold' 'hot' 'hot' 'warm' 'cold' 'warm' 'hot']
[0 0 2 0 1 1 2 0 2 1]
[[ 1. 0. 0.]
[ 1. 0. 0.]
[ 0. 0. 1.]
[ 1. 0. 0.]
[ 0. 1. 0.]
[ 0. 1. 0.]
[ 0. 0. 1.]
[ 1. 0. 0.]
[ 0. 0. 1.]
[ 0. 1. 0.]]
['cold']
在下一个例子中,我们来看一下如何直接对整数值进行独热编码。
独热编码与Keras
你可能有一个已经被编码成整数的序列。在缩放之后,您可以直接处理整数。另一种方法是,可以直接对整数进行编码。如果这些整数没有真正的顺序关系,并且只是标计的占位符,那么这一点很重要。
Keras库提供了一个名为
to_categorical()的函数,您可以使用独热编码的整数数据。
在这个例子中,我们有4个整数值[0,1,2,3],我们有以下10个数字的输入序列:
data = [1, 3, 2, 0, 3, 2, 2, 1, 0, 1]
该序列具有所有已知值的示例,因此我们可以直接使用
to_categorical()函数。或者,如果序列基于0(从0开始)并且不代表所有可能的值,那么我们可以指定num_classes参数
to_categoryical(num_classes = 4)。
以下列出了此功能的完整示例:
from numpy import array
from numpy import argmax
from keras.utils import to_categorical
# define example
data = [1, 3, 2, 0, 3, 2, 2, 1, 0, 1]
data = array(data)
print(data)
# one hot encode
encoded = to_categorical(data)
print(encoded)
# invert encoding
inverted = argmax(encoded[0])
print(inverted)
运行该示例首先定义并打印输入序列。然后,这些整数被编码为二进制向量,并被打印出来。我们可以看到,第一个整数值1被编码为[0, 1, 0, 0],就像我们期望的那样。然后,我们在序列的第一个值中使用NumPy argmax()函数来反转编码,为第一个整数返回到期望值1。
[1 3 2 0 3 2 2 1 0 1]
[[ 0. 1. 0. 0.]
[ 0. 0. 0. 1.]
[ 0. 0. 1. 0.]
[ 1. 0. 0. 0.]
[ 0. 0. 0. 1.]
[ 0. 0. 1. 0.]
[ 0. 0. 1. 0.]
[ 0. 1. 0. 0.]
[ 1. 0. 0. 0.]
[ 0. 1. 0. 0.]]
1
概要
在本教程中,您发现如何使用Python中独热编码对您的分类序列数据进行深度学习编码。
具体来说,你学到了:
- 什么是整数编码和独热编码,为什么它们在机器学习中是必需的。
- 如何在Python中动手计算一个整数编码和独热编码。
- 如何使用scikit-learn和Keras库来自动对Python中的序列数据进行编码。
注:此文为编译作品,作者 Jason Brownlee,原网址
http://machinelearningmastery.com/how-to-one-hot-encode-sequence-data-in-python/