机器学习使用的数据结构并不总是类似于标准计算中使用的结构。如果你想要高效的机器学习,你需要首先处理你的数据。
开篇
处理数据是程序员日常工作的一个重要部分。通常情况下,数据被组织成数组和对象,从外部存储在SQL或基于文档的数据库中,或者被编码在文本或二进制文件中。机器学习是关于数据的,当使用大量的数据时,效果最好。因此,数据和数据处理在设计和构建机器学习管道中起着核心作用。然而,数据格式往往与类和对象有很大的不同,而且使用的是向量、矩阵和张量等术语。在这篇文章中,我们解释了为什么机器学习需要一个高效的数据管道和数据格式。我们解释了从标量到n维张量的基本数据结构,并给出了处理不同数据类型的例子。
在附带的工作手册中给出了实际的代码例子。在下面的笔记本中,你可以找到关于Python中数据处理的实际片段。
为什么数据结构在ML中存在不同
当我们谈论机器学习的数据时,我们指的是用于建立和测试模型的训练数据。机器学习数据结构的设计目标与经典编程的不同。通常情况下,原始数据包括存储在本地磁盘或云桶中的表格数据、图像或视频、文本或音频。机器学习框架不能直接消费这些数据,因为这些数据通常是经过编码的(例如,以JPG或MP4的形式),包含额外的信息,不能被有效地处理。在机器学习中,性能非常重要,训练数据在训练期间被一个模型推断了成百上千次。机器学习应用程序是由(多个)GPU通过高性能的内部网络和管道同步数据进行训练和使用的。所有这些都需要一个优化的数据格式,可以处理不同类型的数据。
ML数据结构的设计目标
- 适用于高性能的处理和计算
- 在不同的GPU和机器之间进行有效的同步
- 灵活处理不同类型的数据
幸运的是,大多数复杂的任务都由机器学习框架处理,如Tensorflow或PyTorch。尽管如此,为了设计高效的数据管道,了解以下基本原理是很重要的。
标量、向量和矩阵
在我们灵活的数据格式中,我们尽可能简单地从单一元素开始:标量。标量指的是单个数据点;例如,一个RGB像素中的蓝色量或一个字母或单词的标记表示。在Java或Python等编程语言中,标量是单一的整数、双数或布尔运算。
当从标量建立一个列表,并且该列表有一个固定的顺序(定向)时,它被称为向量。向量在经典编程中非常常见,经常被当作图元、数组或列表使用。用一个向量,我们已经可以表示一个完整的RGB像素(红、绿、蓝的值)或一个句子(每个单词或单词的一部分用一个整数标记表示)。
在下一步,我们通过将多个向量堆叠成一个矩阵来增加第二个维度。矩阵是二维的,可与表格相比,由行和列组成。通过这种方式,我们可以有效地存储灰度图像,一个文本的多个文件,或一个多通道的音频文件。
在GPU上处理矩阵是非常高效的,而且计算矩阵背后的数学是经过充分研究的(尽管强化模型最近才发现更高效的乘法算法)。矩阵是现代机器学习中任何数据结构的基础。
张量和它们的属性
一个张量描述了一个n维的数据阵列。通常,所谓的等级或轴的数量指的是维度。一个等级为0的张量是一个标量,一个等级为1的张量是一个矢量,而矩阵指的是一个等级为2的张量。
N维张量是机器学习应用的理想选择,因为它们通过快速查找提供对数据的快速访问,无需解码或进一步处理。由于众所周知的矩阵数学,用张量计算是非常有效的,可以训练需要计算数百万和数十亿参数的深度学习模型。许多张量操作,如加法、减法、Hadamard变换、点乘等,都在标准的机器学习库中有效实现。
以张量格式存储数据伴随着明显的时间/内存权衡,这在计算机科学中并不少见。存储经过编码和压缩的数据可以将所需的磁盘空间减少到最小。要访问这些数据,必须对其进行解码和解压,这需要计算的努力。对于单个文件来说,这大多是无关紧要的,快速传输和低存储要求的优势超过了访问时间。然而,在训练深度学习模型时,数据被频繁访问,机器学习模型的基本算法(如图像分析的卷积)不能在编码数据上操作。
一张编码良好的320 x 213像素的JPG图像只需要大约13 KB的存储空间,而相同图像数据的float32张量则需要大约798 KB的内存,增加了6100%。
在JPG中,320 x 213的彩色像素只需要13KB的存储空间
相同的图像数据存储在320 x 213 x 3 float32张量中,重量为798 KB。
为了结合两者的优势,我们设计了特殊的数据加载器模块来预处理数据,以优化张量格式的使用。
另外还有一些优化措施,如批处理和稀疏数据格式,以处理大量的数据。尽管如此,(训练)深度学习模型的硬件要求仍然很高。
为你的数据管道做出决定
考虑到上述关于专门数据结构的见解,让我们看看在设计数据管道时必须做出的决定。
首先,即使在开始开发任何机器学习模型之前,也要确保将任何相关的数据结构化和可访问地存储。对于图像数据,这通常意味着一些云存储,并在文件上附加额外的元数据或存储在一个单独的数据库中。对于我们的数据加载器来说,重要的是要有一个相关文件及其附加标签的结构化列表。这个元数据将被用来下载和预处理文件。 请记住,在某些时候,可能会有多台机器并行地处理相同的数据集,所以它们都需要并行访问。对于训练程序,我们希望在训练机器上直接缓存数据,以避免高交易时间和成本,因为我们经常访问数据。即使你不打算训练机器学习模型(还没有),考虑存储相关的数据和可能的标签可能对以后的监督学习有用,这可能是值得的。
在下一步,我们将数据转换为有用的张量格式。张量等级取决于使用的数据类型(见工作簿中的例子),更令人惊讶的是,取决于问题的定义。重要的是要定义模型是否应该解释独立于其他数据(例如一个句子),或者数据的哪些部分是相互关联的。一个批次通常由一些独立的样本组成。批量大小是灵活的,可以在推理/测试时减少到单个样本。张量的类型也取决于数据类型和归一化方法(像素可以表示为0到255的整数或0到1的浮点数)。
对于较小的问题,也许可以将完整的数据集加载到内存中(张量格式),并在这个数据源上进行训练,这样做的好处是在训练过程中数据加载速度快,CPU负载低。然而,对于大多数实际问题来说,这是不可能的,因为即使是标准的数据集也很容易超过数百GB。对于这些情况,异步数据加载器可以作为一个线程在CPU上工作,并在内存中准备数据。这是一个连续的过程,所以即使内存总量小于完整的数据集,它也能工作。
数据集决定:
- 结构化格式
- 无障碍存储
- 标签和元数据
- 张量格式(等级、批量大小、类型、归一化)。
- 将数据从磁盘加载到内存中,并行化
标量、向量、矩阵,尤其是张量,是任何机器学习数据集的基本构件。训练一个模型首先要建立一个相关的数据集和数据处理管道。这篇文章提供了一个优化数据结构的概述,并解释了张量格式的一些相关方面。希望所讨论的设计数据管道的决定可以作为对机器学习中的数据处理这一主题进行更详细了解的起点。