dataset模块之通用数据处理

从本篇文章开始,我们将进入dataset模块的另外一大功能区——数据处理。dataset模块中的数据处理主要分为四个部分,通用数据处理,图像数据处理与增强,文本数据处理与增强和轻量化数据处理。我会给大家分享前三个部分的内容。第四个部分应用的前提是资源条件允许下,所以它的应用范围相比于前三个部分比较小,我也就不为大家介绍了。

接下来进入本篇文章的正文——通用数据处理。数据是深度学习的基础,良好的数据输入可以对整个深度神经网络训练起到非常积极的作用。在训练前对已加载的数据集进行数据处理,可以解决诸如数据量过大、样本分布不均等问题,从而获得更加优化的数据输入。MindSpore的各个数据集类(Cifar10Dataset,MnistDataset等)都为用户内置了很多数据集处理算子,包括我们今天要讲的(shuffle,map,batch等)。当然我们也可以加载一些比较简单的,由我们自己定义的数据集,然后对它使用数据处理算子,这样可以更加直观的感受到算子的作用。

MindSpore目前支持的常用的通用数据集处理算子如下表所示:

数据处理算子算子说明
shuffle 对数据集进行混洗,随机打乱数据顺序。
map 提供自定义函数或算子,作用于数据集的指定列数据。
batch 对数据集进行分批,可以减少训练轮次,加速训练过程。
repeat 对数据集进行重复,达到扩充数据量的目的。
zip 将两个数据集进行列拼接,合并为一个数据集。
concat 将两个数据集进行行拼接,合并为一个数据集。

表格来自MindSpore官方

shuffle

对数据集进行混肴,随机打乱数据顺序。改方法的参数为buffer_size,buffer_size越大意味着混肴程度越大,同时时间,计算所消耗内存等也会越来越大。

image.png

上图代表着最简单的混肴,数据集某一列的原始顺序为1,2,3,经过shuffle后,该列的顺序变为了2,1,3。

下面的例子是构建一个固定的numpy数据集,展示其数据结果,然后对其进行混肴,最后展示混肴的结果。

import numpy as np
import mindspore.dataset as ds

features, labels = np.array([[1, 2], [3, 4], [5, 6], [7, 8]]), np.array([[1], [2], [3], [4]])

# data元组为dataset数据集的主要元素
data = (features, labels)

# data由两组元素构成,所以参数column_names设置为两个元素的列表,分别对应features和labels
# 注意:必须要先手动设置shuffle参数为False,因为NumpySlicesDataset的默认shuffle参数为True
dataset = ds.NumpySlicesDataset(data, column_names=["col1", "col2"], shuffle=False)

for np_array_data in dataset:
    print(np_array_data[0], np_array_data[1])

print()
# 设置buffer_size的大小
dataset = dataset.shuffle(buffer_size=2)

for np_array_data in dataset:
    print(np_array_data[0], np_array_data[1])

运行结果如下所示:

image.png

map

将指定的函数或算子作用于数据集的指定列数据,实现数据映射操作。用户可以自定义映射函数,也可以直接使用c_transformspy_transforms中的算子针对图像、文本数据进行数据增强。一般情况下,我们使用它去处理深度学习的数据集(针对计算机视觉)都是采样内置的图像处理算子(Resize, RandomCrop等),因为这些内置算子的效率一般都比较高,而且可以满足我们大部分的需要。

image.png

下面的样例中构建了一个简单的函数,然后将这个函数给映射到shuffle例子中的dataset数据集中,最后再对比展示映射前后的数据结果变化。这里主要是为了让大家知道map可以将相关函数(算子)作用到数据集上,待读者实际需要某些特定算子时,可以前往API查看其用法,并使用map将其映射到数据集上。

import numpy as np
import mindspore.dataset as ds

features, labels = np.array([[1, 2], [3, 4], [5, 6], [7, 8]]), np.array([[1], [2], [3], [4]])

data = (features, labels)

dataset = ds.NumpySlicesDataset(data, column_names=["col1", "col2"], shuffle=False)

for np_array_data in dataset:
    print(np_array_data[0], np_array_data[1])

print()

def mapfunc(x):
    return x * x
# 参数operations为需要作用再数据集上的函数或者算子,input_columns为operations需要
# 作用的列的名称,再NumpySlicesDataset中已经将列名声明为["col1", "col2"],这里我们
# 将operations作用在col2列上
dataset = dataset.map(operations=mapfunc, input_columns=["col2"])

for np_array_data in dataset:
    print(np_array_data[0], np_array_data[1])

运行结果如下所示:

image.png

batch

将数据集分批,分别输入到训练系统中进行训练,可以减少训练轮次,达到加速训练过程的目的(一次训练一个batch,batch的默认值为1)。

image.png

上图代表着最简单的batch方法,原始数据的处理顺序为(1),(2),(3),(4),对数据集采取batch方法后的处理顺序为(1,2),(3,4)。

import numpy as np
import mindspore.dataset as ds

features, labels = np.array([[1, 2], [3, 4], [5, 6], [7, 8]]), np.array([[1], [2], [3], [4]])

data = (features, labels)

dataset = ds.NumpySlicesDataset(data, column_names=["col1", "col2"], shuffle=False)

for np_array_data in dataset:
    print(np_array_data[0], np_array_data[1])

print()

# 参数batch_size表示将batch_size个样本元素绑定成一个batch
dataset = dataset.batch(batch_size=2)
for np_array_data in dataset:
    print(np_array_data[0], np_array_data[1])

运行结果如下所示:

image.png

可以看到上图中使用batch方法后的数据集中的单个样本元素有点奇怪,不过这是正常的,因为我们的数据(矩阵)的形状没有选择好。深度学习中的所有单个样本数据实质上都是一个多维的数组。所谓的batch方法将若干个样本形成一个批次的数据,它在本质上也就是将这若干个样本的多维数组合在一起形成一个维度更高的多维数组。这样去想的话,上图中的结果也是符合batch方法定义的。

repeat

对数据集进行重复以达到扩充数据集的目的。

image.png

注意:repeatbatch操作的顺序会影响训练batch的数量,建议将repeat置于batch之后。(batch方法作用在数据集上,实际上会减少数据集中的样本数(将batch_size个样本组成一个样本))。

以下样例将对shuffle中的dataset数据集重复两次,并在最后展示了重复后的数据集效果。

import numpy as np
import mindspore.dataset as ds

features, labels = np.array([[1, 2], [3, 4], [5, 6], [7, 8]]), np.array([[1], [2], [3], [4]])

data = (features, labels)

dataset = ds.NumpySlicesDataset(data, column_names=["col1", "col2"], shuffle=False)

for np_array_data in dataset:
    print(np_array_data[0], np_array_data[1])

print()

# 参数2代表复制1次,若参数为1,代表着数据集不变
dataset = dataset.repeat(2)
for np_array_data in dataset:
    print(np_array_data[0], np_array_data[1])

运行结果如下:

image.png

对于通用数据集处理还有两个比较常见的zip,concat。其中zip方法是将两个数据集进行列拼接,合并为一个数据集,注意:1. 如果两个数据集的列名相同,则不会合并,请注意列的命名。2. 如果两个数据集的行数不同,合并后的行数将和较小行数保持一致。concat方法是将两个数据集进行拼接,合并为一个数据集。注意:输入数据集中的列名,列数据类型和列数据的排列应相同。由于平常我使用这两个方法的次数较少,在这里我就不为大家实际演示它们了,需要使用它们的读者可前往官方链接查看实例。

posted @ 2021-12-27 16:39  MS小白  阅读(157)  评论(0)    收藏  举报