通常情况下,直接加载的原始数据并不能直接送入神经网络进行训练,此时我们需要对其进行数据预处理。MindSpore提供不同种类的数据变换(Transforms),配合数据处理Pipeline来实现数据预处理。所有的Transforms均可通过
map
方法传入,实现对指定数据列的处理。
本章介绍模块特性较多,本文基本采用官方文档的解释和案例
依赖
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
Common Transforms
Compose
Compose
接收一个数据增强操作序列,然后将其组合成单个数据增强操作。
# Download data from open datasets
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')
Downloading data from https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/notebook/datasets/MNIST_Data.zip (10.3 MB)
file_sizes: 100%|███████████████████████████| 10.8M/10.8M [00:00<00:00, 146MB/s]
Extracting zip file...
Successfully downloaded / unzipped to ./
image, label = next(train_dataset.create_tuple_iterator())
print(image.shape)
(28, 28, 1)
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)
(28, 1, 28)
更多通用Transforms详见mindspore.dataset.transforms。
Vision Transforms
mindspore.dataset.vision
模块提供一系列针对图像数据的Transforms。在Mnist数据处理过程中,使用了Rescale
、Normalize
和HWC2CHW
变换。
Rescale
Rescale
变换用于调整图像像素值的大小,包括两个参数:
- rescale:缩放因子。
- shift:平移因子。
图像的每个像素将根据这两个参数进行调整,输出的像素值为 o u t p u t i = i n p u t i ∗ r e s c a l e + s h i f t output_{i} = input_{i} * rescale + shift outputi=inputi∗rescale+shift。
这里我们先使用numpy随机生成一个像素值在[0, 255]的图像,将其像素值进行缩放。
random_np = np.random.randint(0, 255, (48, 48), np.uint8)
random_image = Image.fromarray(random_np)
print(random_np)
[[ 73 28 224 ... 240 180 2]
[ 29 103 130 ... 136 54 225]
[ 19 30 226 ... 101 89 19]
...
[201 222 125 ... 166 61 25]
[154 21 107 ... 117 47 169]
[224 250 247 ... 167 191 148]]
实例化Transform对象,然后调用对象进行数据处理。
rescale = vision.Rescale(1.0 / 255.0, 0)
rescaled_image = rescale(random_image)
print(rescaled_image)
[[0.28627452 0.10980393 0.87843144 ... 0.94117653 0.7058824 0.00784314]
[0.1137255 0.4039216 0.50980395 ... 0.53333336 0.21176472 0.882353 ]
[0.07450981 0.11764707 0.8862746 ... 0.39607847 0.34901962 0.07450981]
...
[0.78823537 0.8705883 0.4901961 ... 0.6509804 0.2392157 0.09803922]
[0.6039216 0.08235294 0.41960788 ... 0.45882356 0.18431373 0.6627451 ]
[0.87843144 0.9803922 0.9686275 ... 0.654902 0.7490196 0.5803922 ]]
Normalize
Normalize变换用于对输入图像的归一化,包括三个参数:
- mean:图像每个通道的均值。
- std:图像每个通道的标准差。
- is_hwc:bool值,输入图像的格式。True为(height, width, channel),False为(channel, height, width)。
图像的每个通道将根据
mean
和std
进行调整,计算公式为 o u t p u t c = i n p u t c − m e a n c s t d c output_{c} = \frac{input_{c} - mean_{c}}{std_{c}} outputc=stdcinputc−meanc,其中 c c c代表通道索引。
normalize = vision.Normalize(mean=(0.1307,), std=(0.3081,))
normalized_image = normalize(rescaled_image)
print(normalized_image)
[[ 0.50494814 -0.06782239 2.4269116 ... 2.6305635 1.8668692
-0.3987565 ]
[-0.05509416 0.8867953 1.2304575 ... 1.306827 0.2631117
2.4396398 ]
[-0.1823765 -0.04236592 2.452368 ... 0.8613388 0.70859987
-0.1823765 ]
...
[ 2.1341622 2.4014552 1.1668164 ... 1.688674 0.35220936
-0.10600709]
[ 1.5359352 -0.15692005 0.9377082 ... 1.0649905 0.17401403
1.7268586 ]
[ 2.4269116 2.7578456 2.719661 ... 1.7014022 2.0068798
1.4595658 ]]
HWC2CHW
HWC2CHW
变换用于转换图像格式。在不同的硬件设备中可能会对(height, width, channel)或(channel, height, width)两种不同格式有针对性优化。MindSpore设置HWC为默认图像格式,在有CHW格式需求时,可使用该变换进行处理。
hwc_image = np.expand_dims(normalized_image, -1)
hwc2chw = vision.HWC2CHW()
chw_image = hwc2chw(hwc_image)
print(hwc_image.shape, chw_image.shape)
(48, 48, 1) (1, 48, 48)
更多Vision Transforms详见mindspore.dataset.vision。
Text Transforms
mindspore.dataset.text
模块提供一系列针对文本数据的Transforms。与图像数据不同,文本数据需要有分词(Tokenize)、构建词表、Token转Index等操作。这里简单介绍其使用方法。
下面定义三段文本,作为待处理的数据,并使用GeneratorDataset
进行加载。
texts = ['Welcome to Beijing']
test_dataset = GeneratorDataset(texts, 'text')
PythonTokenizer
分词(Tokenize)操作是文本数据的基础处理方法,MindSpore提供多种不同的Tokenizer。这里我们选择基础的
PythonTokenizer
举例,此Tokenizer允许用户自由实现分词策略。随后我们利用map
操作将此分词器应用到输入的文本中,对其进行分词。
def my_tokenizer(content):
return content.split()
test_dataset = test_dataset.map(text.PythonTokenizer(my_tokenizer))
print(next(test_dataset.create_tuple_iterator()))
[Tensor(shape=[3], dtype=String, value= ['Welcome', 'to', 'Beijing'])]
Lookup
Lookup
为词表映射变换,用来将Token转换为Index。在使用Lookup
前,需要构造词表,一般可以加载已有的词表,或使用Vocab
生成词表。这里我们选择使用Vocab.from_dataset
方法从数据集中生成词表。
vocab = text.Vocab.from_dataset(test_dataset)
获得词表后我们可以使用vocab
方法查看词表。
print(vocab.vocab())
{'to': 2, 'Welcome': 1, 'Beijing': 0}
生成词表后,可以配合map
方法进行词表映射变换,将Token转为Index。
test_dataset = test_dataset.map(text.Lookup(vocab))
print(next(test_dataset.create_tuple_iterator()))
[Tensor(shape=[3], dtype=Int32, value= [1, 2, 0])]
更多Text Transforms详见mindspore.dataset.text。
Lambda Transforms
Lambda Transforms可以加载任意定义的Lambda函数,提供足够的灵活度。
案例:将map
的值传入Lambda函数后,迭代数据,对输入数据乘2:
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()))
[[Tensor(shape=[], dtype=Int64, value= 2)], [Tensor(shape=[], dtype=Int64, value= 4)], [Tensor(shape=[], dtype=Int64, value= 6)]]
2024-06-22 09:51:19 Mindstorm