MindSpore 的数据处理
1.概述
本文主要介绍了昇思 MindSpore 的数据处理功能。

2. 数据的加载

2.1 自定义数据集
MindSpore 可以构造自定义数据加载类或自定义数据集生成函数的方式来生成数据集,然后通过 GeneratorDataset 接口实现自定义方式的数据集加载。
2.1.1 可随机访问数据集
可随机访问数据集是实现了__getitem__和__len__方法的数据集,表示可以通过数字索引直接访问对应位置的数据样本。
from mindspore.dataset import GeneratorDataset
import numpy as np
class RandomAccessDataset:
def __init__(self):
self._data = np.ones((5, 2))
self._label = np.zeros((5, 1))
def __getitem__(self, index):
return self._data[index], self._label[index]
def __len__(self):
return len(self._data)
loader = RandomAccessDataset()
dataset = GeneratorDataset(source=loader, column_names=["data", "label"])
for data in dataset:
print(data)

# list, tuple 是默认实现 __getitem__和__len__
loader = [np.array(0), np.array(1), np.array(2)]
dataset = GeneratorDataset(source=loader, column_names=["data"])
for data in dataset:
print(data)

2.1.2 可迭代数据集
可迭代的数据集是实现了__iter__和__next__方法的数据集,表示可以通过迭代的方式逐步获取数据样本。这种类型的数据集特别适用于随机访问成本太高或者不可行的情况。
class IterableDataset():
def __init__(self, start, end):
self.start = start
self.end = end
def __next__(self):
return next(self.data)
def __iter__(self):
self.data = iter(range(self.start, self.end))
return self
loader = IterableDataset(1, 5)
dataset = GeneratorDataset(source=loader, column_names=["data"])
for d in dataset:
print(d)

2.1.3 生成器
生成器也属于可迭代的数据集类型,其直接依赖Python的生成器类型generator返回数据,直至生成器抛出StopIteration异常。
def my_generator(start, end):
for i in range(start, end):
yield i
dataset = GeneratorDataset(source=lambda: my_generator(3, 6), column_names=["data"])
for d in dataset:
print(d)

2.2 标准格式数据集 MindSpore Record
2.2.1 MindSpore Record 的文件结构
MindSpore Record文件由数据文件和索引文件组成。
其中,数据文件包含文件头、标量数据页和块数据页,用于存储用户归一化后的训练数据。具体用途如下:
-
文件头:MindSpore Record文件的元信息。主要用于存储文件头大小、标量数据页大小、块数据页大小、Schema信息、索引字段、统计信息、文件分区信息、标量数据与块数据对应关系等。
-
标量数据页:主要用于存储整型、字符串、浮点型等标量类型数据,如图像的Label、文件名、长宽等信息。
-
块数据页:主要用于存储二进制串、NumPy数组等数据,如二进制图像文件本身、文本转换后的字典等。
索引文件则包含基于标量数据(如图像Label、图像文件名等)生成的索引信息,便于检索和统计数据集信息。
建议:
- 单个MindSpore Record文件建议小于20G。对于大数据集,建议分片存储为多个MindSpore Record文件。
- 数据文件和索引文件均暂不支持重命名操作。
MindSpore Record数据格式具备以下特征:①实现数据统一存储和访问,使训练时数据读取更加简便。②支持数据聚合存储和高效读取,便于数据管理和移动。③提供高效的数据编解码操作,用户对数据操作无感知。④可以灵活控制数据切分的分区大小,实现分布式数据处理。

2.2.2 代码示例
对于MindSpore暂不支持直接加载的数据集,可以将数据集转换成 MindRecord 格式数据集,然后通过 mindspore.dataset.MindDataset 接口实现数据集加载。
import numpy as np
import os
from mindspore.mindrecord import FileWriter
from mindspore.dataset import MindDataset
if os.path.exists("./test.mindrecord"):
os.remove("./test.mindrecord")
if os.path.exists("./test.mindrecord.db"):
os.remove("./test.mindrecord.db")
writer = FileWriter(file_name="test.mindrecord", shard_num=1, overwrite=True)
schema_json = {"label": {"type": "int32"},
"data": {"type": "int32", "shape": [-1]}}
writer.add_schema(schema_json, "test_schema")
writer.add_index(['label'])
for i in range(4):
data = [{"file_name": str(i) + ".jpg",
"label": i,
"data": np.array([i]*(i+1), dtype=np.int32)}]
writer.write_raw_data(data)
writer.commit()

然后通过 MindDataset 接口读取 MindRecord 格式数据集。
dataset = MindDataset("test.mindrecord", shuffle=False)
for data in dataset:
print(data)

2.3 公共数据集
from download import download
from mindspore.dataset import MnistDataset
url = "https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/" \
"notebook/datasets/MNIST_Data.zip"
path = download(url, "./", kind="zip", replace=True)
train_dataset = MnistDataset("MNIST_Data/train", shuffle=False)
print(type(train_dataset))


3. 数据变换
3.1 数据操作
mindspore.dataset 提供了一系列数据集操作,用户可通过这些操作(如 .shuffle 、 .filter 、 .skip 、 .take 、 .batch 等)实现数据集的混洗、过滤、跳过、批处理组合等功能。
常用数据变换操作包括:
-
.filter(...):通过指定条件,对数据进行过滤,保留满足预期条件的样本。 -
.project(...):对多个数据列进行排序,或删除不需要的数据列。 -
.rename(...):对指定数据列进行重命名,便于标记数据特性。 -
.shuffle(...):划分一个数据缓冲区,对缓冲区内的数据进行混洗。 -
.skip(...):跳过数据集的前n条样本。 -
.take(...):只获取数据集的前n条样本。 -
.map(...):通过自定义方法对每个样本进行变换和增强。 -
.batch(...):对batch_size条数据进行组合。
3.2 数据集组合
数据集组合可以将多个数据集以串联/并联的方式组合起来,形成一个全新的dataset对象。
3.2.1 串联
import mindspore.dataset as ds
# concat same column of two datasets
data = [1, 2, 3]
dataset1 = ds.NumpySlicesDataset(data=data, column_names=["column_1"])
data = [4, 5, 6]
dataset2 = ds.NumpySlicesDataset(data=data, column_names=["column_1"])
dataset = dataset1.concat(dataset2)
for item in dataset.create_dict_iterator():
print("concated dataset", item)

3.2.2 并联
import mindspore.dataset as ds
# zip different columns of two datasets
data = [1, 2, 3]
dataset1 = ds.NumpySlicesDataset(data=data, column_names=["column_1"])
data = [4, 5, 6]
dataset2 = ds.NumpySlicesDataset(data=data, column_names=["column_2"])
dataset = dataset1.zip(dataset2)
for item in dataset.create_dict_iterator():
print("zipped dataset", item)

3.3 数据集切分
将数据集切分成训练集和验证集,分别用于训练和验证过程。
import mindspore.dataset as ds
data = [1, 2, 3, 4, 5, 6]
dataset = ds.NumpySlicesDataset(data=data, column_names=["column_1"], shuffle=False)
train_dataset, eval_dataset = dataset.split([4, 2])
print(">>>> train dataset >>>>")
for item in train_dataset.create_dict_iterator():
print(item)
print(">>>> eval dataset >>>>")
for item in eval_dataset.create_dict_iterator():
print(item)

3.4 数据集保存
import os
import mindspore.dataset as ds
data = [1, 2, 3, 4, 5, 6]
dataset = ds.NumpySlicesDataset(data=data, column_names=["column_1"])
if os.path.exists("./train_dataset.mindrecord"):
os.remove("./train_dataset.mindrecord")
if os.path.exists("./train_dataset.mindrecord.db"):
os.remove("./train_dataset.mindrecord.db")
dataset.save("./train_dataset.mindrecord")

3.5 数据集迭代器
数据集Pipeline定义完成后,一般以迭代方式获取数据,然后送入神经网络中进行训练。可以用 create_tuple_iterator 或 create_dict_iterator 接口创建数据迭代器,并迭代访问数据。
from mindspore.dataset import NumpySlicesDataset
data = ([1, 2, 3, 4, 5, 6, 7, 8], [0, 1, 0, 1, 0, 1, 0, 1])
dataset = NumpySlicesDataset(data=data, column_names=["data", "label"], shuffle=False)
dataset = dataset.map(lambda x: x * 2, input_columns=["data"])
dataset = dataset.batch(2)
for data in dataset.create_tuple_iterator():
print(data)

data = ([1, 2, 3, 4, 5, 6, 7, 8], [0, 1, 0, 1, 0, 1, 0, 1])
dataset = NumpySlicesDataset(data=data, column_names=["data", "label"], shuffle=False)
dataset = dataset.map(lambda x: x * 2, input_columns=["data"])
dataset = dataset.batch(2)
for data in dataset.create_dict_iterator():
print(data)

4. 总结
MindSpore 提供了丰富和有效的数据处理技术,高质量的数据输入会在深度神经网络中发挥积极作用。
- 点赞
- 收藏
- 关注作者
评论(0)