【学术】独热编码如何在Python中排列数据?

机器学习算法不能直接处理分类数据,分类数据必须转换为数字。这适用于当你处理一个序列分类类型的问题,并计划使用深度学习方法,比如长短期循环神经网络(RNN)时。

在本教程中,你将了解如何将您的输入或输出序列数据转换为一个独热编码(one-hot code),以便在Python中深度学习的序列分类问题中使用。

教程概述

本教程分为四个部分:

1. 独热编码是什么?

2. 手动独热编码

3. 独热编码和scikit-learn

4. 独热编码与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 numpyimport 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, cin enumerate(alphabet))
int_to_char= dict((i, c)for i, cin enumerate(alphabet))
# integer encode input data
integer_encoded= [char_to_int[char]for charin data]
print(integer_encoded)
# one hot encode
onehot_encoded= list()
for valuein 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 numpyimport array
from numpyimport argmax
from sklearn.preprocessingimport LabelEncoder
from sklearn.preprocessingimport 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 numpyimport array
from numpyimport argmax
from keras.utilsimport 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中的序列数据进行编码。

原文发布于微信公众号 - ATYUN订阅号(atyun_com)

原文发表时间:2018-01-10

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏人工智能LeadAI

讨厌算法的程序员 1 | 插入排序

什么是算法 在说插入排序之前,我们了解下《算法导论》对算法的从两种不同角度的定义。 一般性解释: 算法是定义良好的计算过程,它取一个或一组值作为输入,并产生出一...

2777
来自专栏人工智能头条

TensorFlow架构与设计:变量初始化

784
来自专栏机器学习和数学

[编程经验] Tensorflow中的共享变量机制小结

今天说一下tensorflow的变量共享机制,首先为什么会有变量共享机制? 这个还是要扯一下生成对抗网络GAN,我们知道GAN由两个网络组成,一个是生成器网络G...

7083
来自专栏西枫里博客

Python学习笔记三(常用运算符)

2017年年终确定的从2018年开始学习一门新的语言。随着机器学习人工智能的日渐深入,是时候有必要掌握以下Python了。博客今天更新第三篇学习记录,关于Pyt...

762
来自专栏mathor

从暴力递归到动态规划

 动态规划没有那么难,但是很多老师在讲课的过程中讲的并不好,由此写下一篇文章记录学习过程

581
来自专栏猿人谷

圆圈中最后剩下的数字

题目:0,1,...,n-1这n个数字排成一个圆圈,从数字0开始每次从这个圆圈里删除第m个数字。求出这个圆圈里剩下的最后一个数字。 这就是有名的约瑟夫(Jose...

1909
来自专栏云时之间

NLP入门之形式语言与自动机学习(三)

在前边的文章中我们把简单的需要的基础知识简单的列举了一遍,包括简单的集合逻辑,还有图论以及一些的证明方法等等,接下来我们将要开始我们正式的关于形式语言的学习,所...

4258
来自专栏数据结构与算法

09:图像旋转翻转变换

09:图像旋转翻转变换 总时间限制: 1000ms 内存限制: 65536kB描述 给定m行n列的图像各像素点灰度值,对其依次进行一系列操作后,求最终图像。...

4325
来自专栏Golang语言社区

厚土Go学习笔记 | 29. 接口

在go语言中,接口类型是由一组方法定义的集合。 一个类型是否实现了一个接口,就看这个类型是否实现了接口中定义的所有方法。在go语言中,无需特别的指明定义一个接口...

3455
来自专栏逍遥剑客的游戏开发

D3D深度测试和Alpha混合

2395

扫码关注云+社区