# 打卡
目录
Dateset:Pipeline 的起始
mindspore.dataset — MindSpore master 文档
MindSpore Dataset 是所有数据集的基类,提供了数据处理方法来帮助用户很简便地定义数据预处理Pipeline,并以最高效(多进程/多线程)的方式处理数据集中的样本。 可用于数据集加载、迭代、操作。
具体步骤
- 加载数据集:1)用 *Dataset 类来加载已支持的数据集;2)通过 UDF Loader + GeneratorDataset 实现Python层自定义数据集的加载。//
mindspore.dataset
提供的接口仅支持解压后的数据文件,可用download
库下载数据集并解压。 - 数据集操作:通过数据集对象方法 .shuffle / .filter / .skip / .split / .take / … 来实现数据集的进一步混洗、过滤、跳过、最多获取条数等操作。
- 数据集样本增强操作:将数据增强操作 (vision类 , nlp类 , audio类 ) 添加到map操作中执行,数据预处理过程中可以定义多个map操作,用于执行不同增强操作,数据增强操作也可以是 用户自定义增强的 PyFunc ;
- 批:用 .batch 操作将多个样本组织成batch,也可以通过batch的参数 per_batch_map 来自定义batch逻辑;
- 迭代器:通过数据集对象方法 create_tuple_iterator或create_dict_iterator 接口来创建迭代器, 可以将预处理完成的数据循环输出。
数据处理 Pipeline
- 内置开源数据集分为视觉、文本、音频类。
- 内置数据格式分为标准格式、用户自定义等。
- 内置其他数据集处理接口,如采样器模块、全局配置模块等。
例如,视觉类(Cifar10Dataset、Cifar100Dataset、FashionMnistDataset、Food101Dataset、KITTIDataset、MnistDataset、QMnistDataset、VOCDataset、WIDERFaceDataset 等),文本类(AGNewsDataset、CLUEDataset、DBpediaDataset、IMDBDataset、SQuADDataset、TextFileDataset、WikiTextDataset、YahooAnswersDataset、YelpReviewDataset 等),音频类(CMUArcticDataset、GTZANDataset、LibriTTSDataset、LJSpeechDataset、SpeechCommandsDataset、TedliumDataset、YesNoDataset 等)。
例如,标准格式(CSVDataset、MindDataset、OBSMindDataset、TFRecordDataset ),用户自定义格式(GeneratorDataset、NumpySlicesDataset、PaddedDataset、RandomDataset)
- map操作可以针对数据集指定列(column)添加数据变换(Transforms),将数据变换应用于该列数据的每个元素,并返回包含变换后元素的新数据集。
- batch操作可以将数据集打包为固定大小的
batch,
是在有限硬件资源下使用梯度下降进行模型优化的折中方法,可以保证梯度下降的随机性和优化计算量。
代码例子
内置数据集的情况
import numpy as np
from mindspore.dataset import vision
from mindspore.dataset import MnistDataset, GeneratorDataset
import matplotlib.pyplot as plt
from download import download
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))
def visualize(dataset):
figure = plt.figure(figsize=(4, 4))
cols, rows = 4, 3
plt.subplots_adjust(wspace=0.5, hspace=0.5)
for idx, (image, label) in enumerate(dataset.create_tuple_iterator()):
figure.add_subplot(rows, cols, idx + 1)
plt.title(int(label))
plt.axis("off")
plt.imshow(image.asnumpy().squeeze(), cmap="gray")
if idx == cols * rows - 1:
break
plt.show()
### shuffle
train_dataset = train_dataset.shuffle(buffer_size=64)
visualize(train_dataset)
### 迭代访问
image, label = next(train_dataset.create_tuple_iterator())
print(image.shape, image.dtype, label)
plt.imshow(image.asnumpy().squeeze(), cmap="gray")
### 数据缩放处理map
train_dataset = train_dataset.map(vision.Rescale(1.0 / 255.0, 0), input_columns='image')
image, label = next(train_dataset.create_tuple_iterator())
print(image.shape, image.dtype, label)
plt.imshow(image.asnumpy().squeeze(), cmap="gray")
### batch打包数据
train_dataset = train_dataset.batch(batch_size=32)
image, label = next(train_dataset.create_tuple_iterator())
print(image.shape, image.dtype) ## 32个打包图片
自定义数据集的情况
下面自定义的可随机访问数据集是实现了 `__getitem__` 和 `__len__` 方法的数据集,表示可以通过索引/键直接访问对应位置的数据样本。
import numpy as np
from mindspore.dataset import vision
from mindspore.dataset import MnistDataset, GeneratorDataset
import matplotlib.pyplot as plt
# Random-accessible object as input source
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 are also supported.
loader = [np.array(0), np.array(1), np.array(2)]
dataset = GeneratorDataset(source=loader, column_names=["data"])
for data in dataset:
print(data)
可迭代的数据集
可迭代的数据集是实现了__iter__
和__next__
方法的数据集,表示可以通过迭代的方式逐步获取数据样本。这种类型的数据集特别适用于随机访问成本太高或者不可行的情况。
from mindspore.dataset import vision
from mindspore.dataset import GeneratorDataset
# Iterator as input source
class IterableDataset():
def __init__(self, start, end):
'''init the class object to hold the data'''
self.start = start
self.end = end
def __next__(self):
'''iter one data and return'''
return next(self.data)
def __iter__(self):
'''reset the iter'''
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)
生成器
生成器也属于可迭代的数据集类型,其直接依赖Python的生成器类型generator
返回数据,直至生成器抛出StopIteration
异常。
from mindspore.dataset import vision
from mindspore.dataset import GeneratorDataset
# Generator
def my_generator(start, end):
for i in range(start, end):
yield i
# since a generator instance can be only iterated once, we need to wrap it by lambda to generate multiple instances
dataset = GeneratorDataset(source=lambda: my_generator(3, 6), column_names=["data"])
for d in dataset:
print(d)
Transforms:数据预处理
mindspore.dataset.transforms — MindSpore master 文档
在数据送入模型网络训练前进行的数据预处理操作。
MindSpore Dataset支持的不同变换类型的数据变换,配合数据处理Pipeline来实现数据预处理。所有的Transforms均可通过 map 方法传入,实现对指定数据列的处理。
代码例子
通用变换Compose
Compose
接收一个数据增强操作序列,然后将其组合成单个数据增强操作。
下面代码的Compose包括了三个vision视觉
变换过程, vision.Rescale、 vision.Normalize、vision.HWC2CHW。
- Rescale 变换作用分别:用于调整图像像素值的大小,图像的每个像素将根据这rescale缩放因子、shift平移因子两个参数进行调整。输出的像素值为 output_{i} = input_{i} * rescale + shift 。
- Normalize变换用于对输入图像的归一化。图像的每个通道将根据
mean
和std
进行调整,output_c = (input_c - mean_c) / std_c,其中 c 代表通道索引。 HWC2CHW
变换用于转换图像格式。在不同的硬件设备中可能会对(height, width, channel)或(channel, height, width)两种不同格式有针对性优化。MindSpore设置 HWC 为默认图像格式,在有CHW格式需求时,可使用该变换进行处理。
import numpy as np
from PIL import Image
from download import download
from mindspore.dataset import transforms, vision, text
from mindspore.dataset import GeneratorDataset, MnistDataset
import matplotlib.pyplot as plt
train_dataset = MnistDataset('MNIST_Data/train')
image, label = next(train_dataset.create_tuple_iterator())
print(image.shape)
composed = transforms.Compose(
[
vision.Rescale(1.0 / 255.0, 0),
vision.Normalize(mean=(0.1307,), std=(0.3081,)),
vision.HWC2CHW()
]
)
train_dataset = train_dataset.map(composed, 'image')
image, label = next(train_dataset.create_tuple_iterator())
print(image.shape)
plt.imshow(image.asnumpy().squeeze(), cmap="gray")
文本变换 Text
mindspore.dataset.transforms — MindSpore master 文档
针对文本数据的Transforms 与图像数据不同,文本数据需要有分词(Tokenize)、构建词表、Token转Index等操作。
- MindSpore提供多种不同的Tokenizer,以
PythonTokenizer
举例,它允许用户自由实现分词策略。 Lookup
为词表映射变换,用来将Token转换为Index。需要先构造词表,这里Vocab.from_dataset
方法从数据集中生成词表。
from mindspore.dataset import transforms, vision, text
from mindspore.dataset import GeneratorDataset,
def my_tokenizer(content):
## 空格分词
return content.split()
texts = ['Welcome to Beijing']
test_dataset = GeneratorDataset(texts, 'text')
test_dataset = test_dataset.map(text.PythonTokenizer(my_tokenizer))
print(next(test_dataset.create_tuple_iterator()))
### 词表构造
vocab = text.Vocab.from_dataset(test_dataset)
print(vocab.vocab()) ## 用vocab方法查看词表。
### 词表映射变换
test_dataset = test_dataset.map(text.Lookup(vocab))
print(next(test_dataset.create_tuple_iterator()))
Lambda变换
Lambda函数是一种不需要名字、由一个单独表达式组成的匿名函数,表达式会在调用时被求值。
from mindspore.dataset import transforms, vision, text
from mindspore.dataset import GeneratorDataset
test_dataset = GeneratorDataset([1, 2, 3], 'data', shuffle=False)
test_dataset = test_dataset.map(lambda x: x * 2)
print(list(test_dataset.create_tuple_iterator()))
def func(x):
return x * x + 2
test_dataset = test_dataset.map(lambda x: func(x))
print(list(test_dataset.create_tuple_iterator()))