机器学习数据表示为阵列。
在Python中,数据几乎被普遍表示为Numpy阵列。
可能会因访问数据的一些Pythonic方法(例如负索引和数组切片)感到困惑。
在本教程中,您将发现如何在Numpy阵列中正确操纵和访问数据。
完成本教程后,您将知道:
1 如何将列表数据转换为Numpy数组。
2 如何使用Pythonic索引和切片访问数据。
3 如何调整数据以满足某些机器学习API的期望。
教程概述
本教程分为4个部分;他们是:
1.从列表到数组
2.数组索引
3.阵列切片
4.阵列重塑
1.从列表到数组
一般来说,我建议使用Pandas甚至NumPy函数从文件加载数据。
本节假设您已经通过其他方式加载或生成了数据,并且现在使用Python列表表示数据。
让我们看看如何将列表中的数据转换为NumPy数组。
一维列表到数组
您可以加载数据或生成数据,并以列表的形式访问数据。
可以通过调用array()NumPy函数将一维数据列表转换为数组。
#one dimensional array
from numpy import array
# list of fdata
data = [11,22,33,44,55]
# array of data
data = array(data)
print(data)
print(type(data))
[11 22 33 44 55]
<class 'numpy.ndarray'>
列表到数组的二维列表
在机器学习中,你更有可能拥有二维数据。
这是一个数据表,其中每一行代表一个新的观察结果,每一列代表一个新的特征。
也许您使用自定义代码生成了数据或加载了数据,现在您有了一个列表的列表。每个列表代表一个新的观察结果。
您可以通过调用array()函数,以与上面相同的方式将列表列表转换为NumPy数组。
# two dimensiaonal example
from numpy import array
#list of data
data = [[11,22], [33,44], [55,66]]
# array of data
data = array(data)
print(data)
print(data.shape)
print(type(data))
[[11 22]
[33 44]
[55 66]]
(3, 2)
<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[1:4])
print(data[4])
11
[22 33 44]
55
如果整数对于数组的边界来说太大,则会导致错误。
# simple indexing
from numpy import array
# define array
data = array([11, 22, 33, 44, 55])
# index data
print(data[5])
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
Cell In[4], line 6
4 data = array([11, 22, 33, 44, 55])
5 # index data
----> 6 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([[10,20,30],[40,50,60],[70,80,90]])
#index data
print(data[0,0])
10
如果我们对第一行中的所有项都感兴趣,我们可以将第二维索引留空,例如:
这将打印第一行数据。
#2d indexing
from numpy import array
#define array
data = array([[10,20,30],[40,50,60],[70,80,90]])
#index data
print(data[0,])
[10 20 30]
The Kernel crashed while executing code in the current cell or a previous cell.
Please review the code in the cell(s) to identify a possible cause of the failure.
Click <a href='https://aka.ms/vscodeJupyterKernelCrash'>here</a> for more info.
View Jupyter <a href='command:jupyter.viewOutput'>log</a> for further details.
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[:])
print(data[0:1])
[11 22 33 44 55]
[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 列 2D 数据集分为输入和输出数据,如下所示:
运行该示例将打印分离的 X 和 y 元素。请注意,X 是二维数组,y 是一维数组。
from numpy import array
data = array([[1,2,3], [4,5,6], [7,8,9]])
# separate data
X = data[:, :-1]
y = data[:, -1]
print(X)
print(y)
[[1 2]
[4 5]
[7 8]]
[3 6 9]
分割训练和测试行
将加载的数据集拆分为单独的训练集和测试集是很常见的。
这是行的分割,其中一部分将用于训练模型,其余部分将用于估计训练模型的技能。
这将涉及通过在第二个维度索引中指定“:”来切片所有列。训练数据集将是从开始到分割点的所有行。
dataset
train = data[:split, :]
测试数据集将是从分割点开始到维度末尾的所有行。
test = data[split:, :]
将所有这些放在一起,我们可以在人为的分割点 2 处分割数据集。
运行该示例将选择前两行用于训练,最后一行用于测试集。
#split train and test
from numpy import array
data = array([[1,2,3], [4,5,6], [7,8,9]])
split = 2
# separate data
train, test = data[:split, :], data[split:, :]
print(train)
print(test)
[[1 2 3]
[4 5 6]]
[[7 8 9]]
4. 数组重塑
分割数据后,您可能需要重新调整数据的形状。
例如,某些库(例如 scikit-learn)可能要求将输出变量 (y) 的一维数组整形为包含一列和每行结果的二维数组。
一些算法,例如 Keras 中的长短期记忆循环神经网络,需要将输入指定为由样本、时间步长和特征组成的三维数组。
了解如何重塑 NumPy 数组以使数据满足特定 Python 库的期望非常重要。我们将看看这两个例子。
数据形状
NumPy 数组具有一个 shape 属性,该属性返回数组每个维度的长度的元组。
#array shape
from numpy import array
# define array
data = array([11,22,33,44,55])
print(data.shape)
(5,)
对于二维数组,返回具有两个长度的元组。
from numpy import array
data = array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print(data.shape)
(3, 3)
您可以在形状维度中使用数组维度的大小,例如指定参数。
元组的元素可以像数组一样访问,第 0 个索引表示行数,第 1 个索引表示列数。例如:
from numpy import array
data = array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print("rows: %d" % data.shape[0])
print("columns: %d" % data.shape[1])
rows: 3
columns: 3
将一维数组重塑为二维数组
通常需要将一维数组重塑为一列多行的二维数组。
NumPy 在 NumPy 数组对象上提供 reshape() 函数,可用于重塑数据。
reshape() 函数采用单个参数来指定数组的新形状。在将一维数组重塑为具有一列的二维数组的情况下,元组将是数组的形状(data.shape[0])作为第一维 和 1 作为第二维。
data = data.reshape((data.shape[0], 1))
# reshape 1d array
from numpy import array
from numpy import reshape
data = [11, 22, 33, 44, 55, 66]
data = array(data)
print(data.shape)
#reshape
data = data.reshape((data.shape[0], 1))
print(data.shape)
(6,)
(6, 1)
运行该示例会打印一维数组的形状,将数组重新调整为 5 行 1 列,然后打印这个新形状。
将 2D 阵列重塑为 3D 阵列
对于需要一个或多个时间步长和一个或多个特征的多个样本的算法,通常需要将每行表示一个序列的二维数据重塑为三维数组。
Keras 深度学习库中的 LSTM 循环神经网络模型就是一个很好的例子。
可以直接使用 reshape 函数,指定新的维度。通过一个示例可以清楚地看出这一点,其中每个序列都有多个时间步长,每个时间步长有一个观察(特征)。
我们可以使用数组的 shape 属性中的大小来指定样本(行)和列(时间步长)的数量,并将特征数量固定为 1。
data.reshape((data.shape[0], data.shape[1], 1))
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)
总结
了解了如何使用 Python 访问和重塑 NumPy 数组中的数据。
1.如何将列表数据转换为 NumPy 数组
2.如何使用 Pythonic 索引和切片访问数据。
3.如何调整数据大小以满足某些机器学习 API 的期望