机器学习入门系列①|为机器学习索引、切片和重塑NumPy数组
如果你是Python新手,可能会对一些Python式的数据访问方式感到困惑,例如负索引和数组切片。本教程将带了解如何在NumPy数组中正确操作和访问数据。(如有错漏请大家指正)
完成本教程后,你可以掌握:1、如何将列表数据转换为NumPy数组;2、如何使用Pythonic索引和切片访问数据;3、如何调整数据大小以满足某些机器学习API的期望等知识点。
本教程分为4部分:
从列表到数组
数组索引
数组切片
数组重塑
废话不多说,搬好小板凳,拿好笔记本,开始认真学习!

1. 从列表到数组
一般来说,建议使用Pandas甚至NumPy函数从文件加载数据。
先来学习如何在Python中加载机器学习数据
机器学习数据最常见的格式是CSV文件。有多种方法可以在Python中加载CSV文件。这里给大家简单介绍几种在Python中加载机器学习数据的不同方法。
加载 CSV 数据时的注意事项
从 CSV 文件加载机器学习数据时有许多注意事项。
可以参考这个文档内容:
https://tools.ietf.org/html/rfc4180
CSV文件标题
你的数据有文件头吗?如果有,这有助于自动为每列数据分配名称。如果没有,需要手动命名文件头。
无论哪种方式,都应该在加载数据时明确指定CSV文件是否具有文件头。
注释
CSV文件中的注释由行首的散列 (“#”) 表示。
如果文件中有注释,根据用于加载数据的方法,需要指明是否需要注释以及需要表示注释行的字符。
分隔符
在字段中分隔值的标准分隔符是逗号 (“,”) 字符。
文件可以使用不同的分隔符,如制表符 (“\t”),在这种情况下,必须明确指定它。
引号
有时字段值可以有空格。在这些CSV文件中,经常引用这些值。
默认引号字符是双引号“\”。可以使用其他字符,并且您必须指定文件中使用的引号字符。
机器学习数据加载方法
每个方法都是独立的。
所以可以将其复制并粘贴到别的项目中并立即使用。
使用Python标准库加载CSV
Python API提供了模块CSV和可用于加载CSV文件的函数reader()。
加载后,将CSV数据转换为NumPy数组并将其用于机器学习。
可以将Pima Indians数据集下载到本地使用。
下载链接:
https://raw.githubusercontent.com/jbrownlee/Datasets/master/pima-indians-diabetes.data.csv
所有字段都是数字,没有标题行。运行下面的方法将加载CSV文件并将其转换为NumPy数组。
该示例加载了一个对象,该对象可以迭代数据的每一行,并且可以轻松地转换为NumPy数组。运行示例print出数组的值。
有关csv.reader()函数的更多信息,请参阅Python API文档中的CSV文件读取和写入(文档见文章底部链接)。
使用NumPy加载CSV文件
可使用NumPy和numpy.loadtxt()函数加载CSV数据。
此函数假定没有标题行并且所有数据都具有相同的格式。下面的示例假设文pima-indians-diabetes.data.csv位于当前的工作目录中。
运行该示例会将文件加载为numpy.ndarray并print数据的值(形状):
可以修改此示例以直接从URL加载相同的数据集,如下所示:
注意:示例使用的是Python3。
同样,运行该示例会生成相同的数据结果值。
有关numpy.loadtxt()函数的更多信息,请参阅API文档(numpy的1.10版传送门见文章底部)。
使用Pandas加载CSV文件
可以使用Pandas和pandas.read_csv()函数加载CSV数据。
这个函数非常灵活,也许是我推荐的加载机器学习数据的方法。该函数返回一个pandas.DataFrame,您可以立即开始汇总和绘图。
下面的示例假设“pima-indians-diabetes.data.csv ”文件位于当前工作目录中。
请注意,在此示例中,我们明确指定了DataFrame的每个属性的名称。运行示例显示数据的值(形状):
我们还可以修改此示例以直接从URL加载CSV数据。
同样,运行该示例会下载CSV文件,对其进行解析并显示加载的DataFrame的形状。
要了解有关pandas.read_csv()函数的更多信息,参考API文档(文档传送门在文章底部)。
掌握以上键入并粘贴的方法,熟悉在Python中加载机器学习数据的不同方式,接下来让我们继续学习将列表中的数据转换为NumPy数组。

一维列表转数组
加载数据或生成数据以列表的形式访问。
通过调用NumPy函数array()将一维数据列表转换为数组。
运行该示例会将一维列表转换为NumPy数组。
Two-Dimensional List of Lists to Array
在机器学习中,我们会碰到二维数据。
一个数据表,其中每一行代表一个new observation,每一列代表一个new feature。
通过生成数据或使用自定义代码加载它,现在您有了一个列表的列表(list of lists)。每个列表代表一个新的观察结果。
通过调用array()函数,以与上述相同的方式将列表的列表转换为NumPy数组。(感觉自己在说绕口令)
运行示例显示数据已成功转换。
2. 数组索引
一旦使用NumPy数组表示数据,就可以使用索引访问它。
来看通过索引访问数据的示例:
一维索引
通常,索引的工作方式与其他编程语言(如Java、C#和C++)的经验一样。
我们可以使用方括号[ ]运算符访问元素,指定要检索的值的零偏移索引。
运行该示例将打印数组中的第一个和最后一个值。
为数组边界指定太大的整数会导致错误。
运行该示例会打印以下错误:
这里可以使用负索引来检索从数组末尾偏移的值。
例如,索引-1指的是数组中的最后一项。对于当前示例中的第一项,索引-2将返回倒数第二项,一直返回到-5。
运行该示例将打印数组中的最后一项和第一项。
二维索引
索引二维数据与索引一维数据类似,只是用逗号分隔每个维度的索引。
例如,我们可以按如下方式访问第一行和第一列:
运行该示例将打印数据集中的第一项。
如果对第一行中的所有项感兴趣,可以将第二个维度索引留空,例如:
这将打印第一行数据。
3. 数组切片
数组切片是对Python和NumPy数组的初学者造成问题的一个知识点。
可以对列表和NumPy数组等结构进行切片。这意味着可以索引和检索结构的子序列。
当指定输入变量和输出变量或从测试行中拆分训练行时,数组切片就会在机器学习中成为最有用的。
切片是使用冒号运算符 ':' 指定的,在列之前和之后分别带有 ' from ' 和 ' to ' 索引。切片从 'from' 索引延伸并在 'to' 索引之前结束一项。
让我们来看看一些例子:
一维切片
您可以通过指定不带索引的切片 ':' 来访问数组维度中的所有数据。
运行该示例将打印数组中的所有元素。
可以通过指定从索引0开始到索引1结束的切片('to' 索引之前的一项)来对数组的第一项进行切片。
运行该示例将返回一个包含第一个元素的子数组。
我们也可以在切片中使用负索引。例如,我们可以通过从 -2(倒数第二个项目)开始切片而不指定“to”索引来对列表中的最后两个项目进行切片;将切片带到维度的末尾。
运行该示例将返回一个仅包含最后两项的子数组。
二维切片
让我们看一下最有可能在机器学习中使用的二维切片的两个示例。
拆分输入和输出功能
通常将加载的数据拆分为输入变量 (X) 和输出变量 (y)。
我们可以通过切片所有行和所有列来做到这一点,但在最后一列之前,然后单独索引最后一列。
对于输入特征,我们可以通过 ':' 在行索引中指定,:-1在列索引中指定,选择除最后一行之外的所有行和所有列。
对于输出列,我们可以使用 ':' 再次选择所有行,并通过-1指定索引来索引最后一列。
将所有这些放在一起,我们可以将一个3列的2D数据集分成输入和输出数据,如下所示:
运行示例打印分离的X和y元素。请注意,X是一个二维组,而y是一个一维数组。
拆分训练和测试行
将加载的数据集拆分为单独的训练集和测试集是很常见的。
这是行的拆分,其中一些部分将用于训练模型,其余部分将用于估计训练模型的技能。
这将涉及通过在第二个维度索引中':'来指定对所有列进行切片。训练数据集将是从开始到分割点的所有行。
测试数据集将是从分割点开始到维度末尾的所有行。
将所有这些放在一起,我们可以在人为的指定2个分割点来分割数据集。
运行示例选择前两行进行训练,最后一行选择测试集。
4. 数组整形
对数据进行切片后,需要对其进行整形。
例如,一些库,例如scikit-learn,可能需要将输出变量 (y) 的一维数组成形为二维数组,其中包含一列和每行的结果。
一些算法,如Keras中的Long Short-Term Memory循环神经网络,需要将输入指定为由样本、时间步长和特征组成的三维数组。
重要的是要知道如何重塑NumPy数组,以便数据满足特定 Python库的需求。看下面这两个例子。
数据形状
NumPy数组有一个shape属性,该属性返回数组每个维度长度的元组。
例如:
运行示例打印一维的元组。
为二维数组返回具有两个长度的元组。
运行该示例将返回一个包含行数和列数的元组。
还可以在形状维度中使用数组维度的大小,例如指定参数。
元组的元素可以像数组一样访问,第0个索引表示行数,第1个索引表示列数。例如:
运行示例访问每个维度的特定大小。
将一维数组重塑为二维数组
通常需要将一维数组重塑为一列多行的二维数组。
NumPy在NumPy数组对象上提供了reshape()函数,可用于对数据进行整形。
reshape()函数采用一个参数来指定数组的新形状。在将一维数组重塑为具有一列的二维数组的情况下,元组将是数组的形状作为第一维 (data.shape[0]) 和1作为第二维。
将所有这些放在一起,看示例:
运行该示例打印一维数组的形状,将数组重塑为5行和1列,然后打印这个新形状。
重塑2D到3D阵列
对于需要一个或多个时间步长和一个或多个特征的多个样本的算法,通常需要将其中每一行代表一个序列的二维数据重塑为一个三维数组。
一个很好的例子是Keras深度学习库中的LSTM循环神经网络模型(参考文档在文章底部)。
reshape()函数可以直接使用,指定新的维度。这在一个例子中很明显,其中每个序列都有多个时间步,每个时间步都有一个观察(特征)。
我们可以使用数组上shape属性中的大小来指定样本(行)和列(时间步长)的数量,并将特征数量固定为 1。
将所有这些放在一起,来看示例:
运行示例首先打印2D数组中每个维度的大小,重新调整数组的形状,然后总结新3D数组的形状。
终于写完了!你们看懂了吗?跟着敲敲代码吧!里面有一些涉及的知识点文档链接,学姐也放在下面了。
本文整理自:
https://machinelearningmastery.com/index-slice-reshape-numpy-arrays-machine-learning-python/
https://machinelearningmastery.com/load-machine-learning-data-python/
(本文来源于网络,如有侵权请联系删除。可通过链接访问原文参与讨论)
LSTM循环神经网络模型:
https://keras.io/layers/recurrent/#lstm
Python API文档:
https://docs.python.org/2/library/csv.html
