【学术】独热编码如何在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 条评论
登录 后参与评论

相关文章

来自专栏小樱的经验随笔

平面上给定n条线段,找出一个点,使这个点到这n条线段的距离和最小。

题目:平面上给定n条线段,找出一个点,使这个点到这n条线段的距离和最小。 源码如下: 1 #include <iostream> 2 #include ...

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

清北集训Day1T3 LYK loves jumping(期望DP)

题目描述 LYK在玩一个魔法游戏,叫做跳跃魔法。 有n个点,每个点有两个属性hi和ti,表示初始高度,和下降高度。也就是说,它初始时高度为hi,一旦LYK踩在这...

2655
来自专栏技术点滴

关于如何评价洗牌质量的猜想

关于如何评价洗牌质量的猜想 洗牌算法是卡牌类游戏中必须使用的算法,本质上说洗牌算法的目的是使某个给定的顺序更加的无序,因此出现了很多种洗牌算法。我们不重点讨论如...

1846
来自专栏程序员互动联盟

【答疑解惑】C语言里面如何计算数据类型取值范围?

先看一个网友的问题: ? 初学者有不少会对数据类型的取值范围有疑问,数据类型的取值范围关系到定义合适的变量,尤其是在进行嵌入式开发时更要清楚。这里有必要介绍一下...

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

1004. 填充矩形 (Standard IO)

题目描述 已知矩形的大小为n×m,现用a×a的正方形填充该矩形。输入三个正整数n,m,a(n,m,a≤10^9),计算至多能填入多少正方形?(正方形可以正好碰到...

3296
来自专栏算法channel

Tensorflow|Tensor, 与Numpy比较,Constant

本教程参考stanford.edu-cs20si 01 Operations分类预览 ? 02 Tensor 1 0-d tensor, or "scala...

3617
来自专栏应兆康的专栏

100个Numpy练习【5】

Numpy是Python做数据分析必须掌握的基础库之一,非常适合刚学习完Numpy基础的同学,完成以下习题可以帮助你更好的掌握这个基础库。

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

洛谷P1317 低洼地

题目描述 一组数,分别表示地平线的高度变化。高度值为整数,相邻高度用直线连接。找出并统计有多少个可能积水的低洼地? 如图:地高变化为 0 1 0 2 1 2 0...

2534
来自专栏TungHsu

这或许是对小白最友好的python入门了吧——9,数字深入体验

先给大家介绍一个函数:range(),这个函数是用来干嘛的呢?很简单,数数的,怎么数呢,我先给大家演示一下: for num in range(1,5): ...

3358
来自专栏C语言及其他语言

【每日一题】1426: [蓝桥杯][历届试题]九宫重排

如下面第一个图的九宫格中,放着 1~8 的数字卡片,还有一个格子空着。与空格子相邻的格子中的卡片可以移动到空格中。经过若干次移动,可以形成第二个图所示的局面...

793

扫描关注云+社区