如何在Python中将索引、切片和重塑用于机器学习的NumPy数组
机器学习数据表示为数组。
在Python中,数据几乎普遍表示为NumPy数组。
如果你是Python的新手,你可能会对一些Python式的数据访问方式感到困惑,例如负索引和数组切片。
在本教程中,你将了解如何在NumPy数组中正确操作和访问数据。
完成本教程后,你将了解:
- 如何将列表数据转换为NumPy数组。
- 如何使用Pythonic索引和切片访问数据。
- 如何调整数据大小以满足某些机器学习API的期望。
我们开始吧。
教程概述
本教程分为4个部分,它们是:
- 从列表到数组。
- 数组索引。
- 数组切片。
- 阵列整形。
1.从列表到数组
通常,我建议使用Pandas甚至NumPy函数从文件加载数据。
有关示例,请参阅帖子:
本节假设你已经通过其他方式加载或生成了数据,现在使用Python列表表示数据。
让我们看看如何将列表中的数据转换为NumPy数组。
一维列表到数组
你可以加载数据或生成数据并将其作为列表进行访问。
可以通过调用NumPy函数array()将一维数据列表转换为数组。
# one dimensional example from numpy import array # list of data data = [11, 22, 33, 44, 55] # array of data data = array(data) print(data) print(type(data))
运行该示例会将一维列表转换为NumPy数组。
[11 22 33 44 55] <class 'numpy.ndarray'>
二维列表到数组
在机器学习中,你更有可能拥有二维数据。
这是一个数据表,其中每行代表一个新观测,每列代表一个新特征。
也许你使用自定义代码生成了数据或加载了数据,现在你就有了一个二维列表。每个二维代表一个新的观察结果。
你可以通过调用array()函数,以与上面相同的方式将列表列表转换为NumPy数组。
# two dimensional example from numpy import array # list of data data = [[11, 22], [33, 44], [55, 66]] # array of data data = array(data) print(data) print(type(data))
运行该示例将显示成功转换的数据。
[[11 22] [33 44] [55 66]] <class 'numpy.ndarray'>
2.数组索引
一旦使用NumPy数组表示数据,就可以使用索引访问它。
让我们看一些通过索引访问数据的示例。
一维索引
通常,索引的工作方式与你在使用其他编程语言(如Java、C#和C++)时所期望的一样。
例如,你可以使用方括号运算符[]来访问元素,该运算符指定要检索的值的零偏移索引。
# simple indexing from numpy import array # define array data = array([11, 22, 33, 44, 55]) # index data print(data[0]) print(data[4])
运行该示例将打印数组中的第一个和最后一个值。
11 55
为数组的界限指定太大的整数将导致错误。
# simple indexing from numpy import array # define array data = array([11, 22, 33, 44, 55]) # index data print(data[5])
运行该示例将打印以下错误:
IndexError: index 5 is out of bounds for axis 0 with size 5
一个关键区别是你可以使用负索引来检索从数组末尾偏移的值。
例如,索引-1表示数组中的最后一项。索引-2返回当前示例中第一个项目的倒数第二个项目,一直返回到-5。
# simple indexing from numpy import array # define array data = array([11, 22, 33, 44, 55]) # index data print(data[-1]) print(data[-5])
运行该示例将打印数组中的最后一项和第一项。
55 11
二维索引
索引二维数据类似于索引一维数据,不同之处在于使用逗号分隔每个维度的索引。
data[0,0]
这与基于C的语言不同,在C语言中,每个维度都使用单独的方括号运算符。
data[0][0]
例如,我们可以按如下方式访问第一行和第一列:
# 2d indexing from numpy import array # define array data = array([[11, 22], [33, 44], [55, 66]]) # index data print(data[0,0])
运行该示例将打印数据集中的第一项。
11
如果我们对第一行中的所有项目感兴趣,则可以将第二维索引留空,例如:
# 2d indexing from numpy import array # define array data = array([[11, 22], [33, 44], [55, 66]]) # index data print(data[0,])
这将打印第一行数据。
[11 22]
3.数组切片
到目前为止,一切顺利;创建和索引数组看起来很熟悉。
现在我们来看数组切片,这是一个会给Python和NumPy数组初学者带来问题的特性。
像列表和NumPy数组这样的结构可以切片。这意味着可以对结构的子序列进行索引和检索。
当指定输入变量和输出变量,或将训练行与测试行分开时,这在机器学习中最有用。
切片是使用冒号运算符“:”指定的,在列前后分别带有“from”和“to”索引。切片从“from”索引延伸,并在“to”索引之前结束一项。
data[from:to]
让我们来做一些例子。
一维切片
你可以通过指定不带索引的切片‘:’来访问数组维度中的所有数据。
# simple slicing from numpy import array # define array data = array([11, 22, 33, 44, 55]) print(data[:])
运行该示例将打印数组中的所有元素。
[11 22 33 44 55]
通过指定从索引0开始到索引1结束的切片,可以对数组的第一项进行切片(在“to”索引之前的一项)。
# simple slicing from numpy import array # define array data = array([11, 22, 33, 44, 55]) print(data[0:1])
运行该示例将返回具有第一个元素的子数组。
[11]
我们也可以在切片中使用负索引。例如,我们可以通过从-2(倒数第二个项目)开始切片,并且不指定“to”索引来对列表中的最后两个项目进行切片;这会将切片带到维度的末尾。
# simple slicing from numpy import array # define array data = array([11, 22, 33, 44, 55]) print(data[-2:])
运行该示例将返回仅包含最后两项的子数组。
[44 55]
二维切片
让我们看看机器学习中最可能使用的两个二维切片示例。
拆分输入和输出要素
将加载的数据拆分为输入变量(X)和输出变量(Y)是很常见的。
我们可以通过将最后一列之前的所有行和所有列切片,然后分别索引最后一列来实现这一点。
对于输入特性,我们可以通过在行索引中指定‘:’并在列索引中指定:-1来选择除最后一行之外的所有行和所有列。
X = [:, :-1]
对于输出列,我们可以使用‘:’再次选择所有行,并通过指定-1(索引)来仅索引最后一列。
y = [:, -1]
将所有这些放在一起,我们可以将3列二维数据集分为输入和输出数据,如下所示:
# split input and output from numpy import array # define array data = array([[11, 22, 33], [44, 55, 66], [77, 88, 99]]) # separate data X, y = data[:, :-1], data[:, -1] print(X) print(y)
运行该示例将打印分隔的x和y元素。请注意,X是二维数组,而Y是一维数组。
[[11 22] [44 55] [77 88]] [33 66 99]
拆分训练行和测试行
将加载的数据集分割成单独的训练集和测试集是很常见的。
这是行的拆分,其中某些部分将用于训练模型,其余部分将用于估计已训练模型的技能。
这将涉及通过在第二个维度索引中指定‘:’来对所有列进行切片。训练数据集将是从开始到拆分点的所有行。
dataset train = data[:split, :]
测试数据集将是从拆分点到维度末尾的所有行。
test = data[split:, :]
将所有这些放在一起,我们可以在人为的拆分点2处拆分数据集。
# split train and test from numpy import array # define array data = array([[11, 22, 33], [44, 55, 66], [77, 88, 99]]) # separate data split = 2 train,test = data[:split,:],data[split:,:] print(train) print(test)
运行该示例将选择前两行用于训练,最后一行用于测试集。
[[11 22 33] [44 55 66]] [[77 88 99]]
4.数组重塑
对数据进行切片后,你可能需要对其进行重塑。
例如,一些库(如scikit-learn)可能需要输出变量(y)中的一维数组被重塑为二维数组,该二维数组由一列及每列对应的结果组成。
一些算法,如Kera中的长短期记忆递归神经网络,需要将输入指定为由样本、时间步长和特征组成的三维数组。
了解如何重塑NumPy数组是非常重要的,这样你的数据就能满足于特定Python库。我们来看看下面这两个例子。
数据形状
NumPy数组具有一个形状属性,该属性返回数组每个维度的长度的元组。
例如:
# array shape from numpy import array # define array data = array([11, 22, 33, 44, 55]) print(data.shape)
运行该示例将打印一个维度的元组。
(5,)
对于二维数组,返回两个长度的元组。
# array shape from numpy import array # list of data data = [[11, 22], [33, 44], [55, 66]] # array of data data = array(data) print(data.shape)
运行此示例将返回一个包含行数和列数的元组。
(3, 2)
你可以在形状维度中使用数组维度的大小,例如指定参数。
可以像访问数组一样访问元组的元素,第0个索引表示行数,第1个索引表示列数。例如:
# array shape from numpy import array # list of data data = [[11, 22], [33, 44], [55, 66]] # array of data data = array(data) print('Rows: %d' % data.shape[0]) print('Cols: %d' % data.shape[1])
运行该示例将访问每个维度的特定大小。
Rows: 3 Cols: 2
将一维阵列重塑为二维阵列
通常需要将一维数组重塑为具有一列和多个数组的二维数组。
NumPy在NumPy数组对象上提供了可用于重塑数据的reshape()函数。
函数的作用是:接受指定数组新形状的单个参数。在将一维数组重塑为具有一列的二维数组的情况下,元组将是作为第一维(data.shape[0])的数组的形状,并且对于第二维是1。
data = data.reshape((data.shape[0], 1))
把所有这些放在一起,我们会得到下面的工作示例。
# reshape 1D array from numpy import array from numpy import reshape # define array data = array([11, 22, 33, 44, 55]) print(data.shape) # reshape data = data.reshape((data.shape[0], 1)) print(data.shape)
运行该示例将打印一维数组的形状,将数组重塑为5行1列,然后打印此新形状。
(5,) (5, 1)
将二维数组重塑为三维数组
对于期望一个或多个时间步长和一个或多个特征的多个样本的算法,通常需要将其中每行代表一个序列的二维数据重塑为三维数组。
Kera深度学习库中的LSTM递归神经网络模型就是一个很好的例子。
可以直接使用重塑函数,指定新维度。这一点在每个序列具有多个时间步长的示例中很清楚,每个时间步长具有一个观测(特征)。
我们可以使用数组的形状属性中的大小来指定样本(行数)和列数(时间点),并将特征数固定为1。
data.reshape((data.shape[0], data.shape[1], 1))
把所有这些放在一起,我们会得到下面的工作示例。
# reshape 2D array from numpy import array # list of data data = [[11, 22], [33, 44], [55, 66]] # array of data data = array(data) print(data.shape) # reshape data = data.reshape((data.shape[0], data.shape[1], 1)) print(data.shape)
运行该示例首先打印二维数组中每个维度的大小,重塑数组的形状,然后汇总新三维数组的形状。
(3, 2) (3, 2, 1)
进一步阅读
如果你想深入了解,本节提供了更多有关该主题的资源。