MindSpore笔记:数据集

这里以MNIST为例

下载数据集

这里有讲


我们需要再下一个库,方便我们下载数据集:

pip install download -i https://pypi.douban.com/simple/

以后用到pip安装时就不多说pypi源了,方便大家直接下载。

# 从开源数据集下载
from download import download

# 定义url地址
url = "https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/notebook/datasets/MNIST_Data.zip"

# 下载并解压
path = download(url, "./", kind="zip", replace=True)

我们还需要一个解析该文件的库,mindspore提供了这个功能:

from mindspore.dataset import MnistDataset

然后:

train_dataset = MnistDataset('MNIST_Data/train')
test_dataset = MnistDataset('MNIST_Data/test')

就可以获得数据集对象了。


压缩文件删除后,直接加载,可以看到其数据类型为MnistDataset。

type(train_dataset)
mindspore.dataset.engine.datasets_vision.MnistDataset

数据集迭代

这里有讲,看看数据集中:


使用 create_tuple_iteratorcreate_dict_iterator 对数据集进行迭代。这里我说明 create_dict_iterator :创建字典迭代:

for data in test_dataset.create_dict_iterator():
    print(f"Shape of image [N, C, H, W]: {data['image'].shape} {data['image'].dtype}")
    print(f"Shape of label: {data['label'].shape} {data['label'].dtype}")
    break
Shape of image [N, C, H, W]: (64, 1, 28, 28) Float32
Shape of label: (64,) Int32

当然我们也可以使用next获取:

dit = next(test_dataset.create_dict_iterator())
print(f"Shape of image [N, C, H, W]: {dit['image'].shape} {dit['image'].dtype}")
print(f"Shape of label: {dit['label'].shape} {dit['label'].dtype}")

我比较喜欢这样,因为就不需要再刻意打一个无意义的for循环。

同时,我们也输出一下我们的图片。

我们需要安装一个库:

pip3 install -i https://pypi.doubanio.com/simple/ matplotlib

先把数据集转换为numpy类型。

import numpy
image = dit['image'].asnumpy()

转换后再用plt库显示图片:

import matplotlib.pyplot as plt
plt.imshow(image) # 显示图片第0张第0维
<matplotlib.image.AxesImage at 0x263d720cf10>


数据集加载后,一般以迭代方式获取数据,然后送入神经网络中进行训练。我们可以用create_tuple_iterator或create_dict_iterator接口创建数据迭代器,迭代访问数据。

访问的数据类型默认为Tensor;若设置output_numpy=True,访问的数据类型为Numpy。

下面定义一个可视化函数,迭代9张图片进行展示。

def visualize(dataset):
    figure = plt.figure(figsize=(4, 4))
    cols, rows = 3, 3

    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()
visualize(train_dataset)

数据集操作

有时候我们是需要对数据集进行操作,如:

shuffle

故事:在一个国度里,国王AK的夫人%%%生下一个孩子Orz,Orz2岁了,应该学习数数了。%%%便教孩子数:

1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 1,2,3,4,5,6,7,8,9,10 1,2,3,4,5,6,7,8,9,10

Orz:

1 , 2... 1,2... 1,2...

%%%:

1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 1,2,3,4,5,6,7,8,9,10 1,2,3,4,5,6,7,8,9,10

Orz:

1 , 2 , 3 , 4 , 5 , 6... 1,2,3,4,5,6... 1,2,3,4,5,6...

几天后,Orz终于会数了:

1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 1,2,3,4,5,6,7,8,9,10 1,2,3,4,5,6,7,8,9,10

AK国王听后很开心,便打乱来考:

1 , 9 , 2 , 6 , 3 , 5 , 7 , 4 , 10 , 8 1,9,2,6,3,5,7,4,10,8 1,9,2,6,3,5,7,4,10,8

Orz:

1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 1,2,3,4,5,6,7,8,9,10 1,2,3,4,5,6,7,8,9,10

AK很生气,于是。。。


好了,故事结束了,其实%%%公主应该打乱来教的,不然Orz以为一定要

1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 1,2,3,4,5,6,7,8,9,10 1,2,3,4,5,6,7,8,9,10

来读。

这如果在深度学习中也是不好,所以我们需要用到 shuffle 来打乱。

shuffle_dataset = train_dataset.shuffle(buffer_size=64)
visualize(shuffle_dataset)

就可以发现和原来不一样了。

这里有一个很费解的东西。什么是 buffer_size ?

首先呢,我们有一些数据 a。

  1. 我们从 a 中取出前 buffer_size 条数据到 buffer 中。

  2. 从 buffer 中随机取出一条

  3. 放入输出,这时 buffer 就空了一个是吧?

  4. 从 a 中再取出第一个填空

  5. 重复2条,直至 a 中没有数据

那么buffer_size的取值就十分重要,如果取了一些错误值,shuffle可能会没有任何效果。

batch

一个人背一包重10kg的东西上山,怎样最省力?

打车

嗯嗯,我们不说这个,答案是 一包一包拿。

同样,我们不可能一下把10kg搬上山,我们可以往返10次,每次拿10kg。这样可以减轻你的负担。

在训练时,我们也不能一下把上万的数据一次训练完(超能力除外),这时候就需要batch打包了。

我们通过 batch(batch_size) 把数据打包为batch_size个包。

train_dataset = train_dataset.batch(batch_size=32)

batch后的数据增加一维,大小为 batch_size 。

image, label = next(train_dataset.create_tuple_iterator())
print(image.shape, image.dtype)
(32, 28, 28, 1) Float32

map

map 操作是数据预处理的关键操作,可以针对数据集指定列(column)添加数据变换(Transforms),将数据变换应用于该列数据的每个元素,并返回包含变换后元素的新数据集。

from mindspore.dataset import vision

image, label = next(train_dataset.create_tuple_iterator())
print(image.shape, image.dtype)
(28, 28, 1) UInt8
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)
(28, 28, 1) Float32

更多变换详见下一篇

自定义数据集

当我们拥有一些数据时,我们可以自定义一个数据集。可以通过构造自定义数据集类或自定义数据集生成函数的方式来生成数据集,然后通过 GeneratorDataset 接口实现自定义方式的数据集加载。

GeneratorDataset 支持通过可迭代对象、迭代器和生成函数构造自定义数据集,下面分别对其进行详解。

array

dataset = GeneratorDataset(source=np.array([[1, 0, 2, 4]]), column_names=["col"])

可迭代对象

Python中可以使用 for 循环遍历出所有元素的,都可以称为可迭代对象(Iterable),我们可以通过实现 __getitem__ 方法来构造可迭代对象,并将其加载至 GeneratorDataset

# 可迭代对象
class Iterable:
    def __init__(self):
        self._data = np.random.sample((5, 2))
        self._label = np.random.sample((5, 1))

    def __getitem__(self, index):
        return self._data[index], self._label[index]

    def __len__(self):
        return len(self._data)

data = Iterable()
dataset = GeneratorDataset(source=data, column_names=["data", "label"])

迭代器

Python中内置有 __iter____next__ 方法的对象,称为迭代器(Iterator)。下面构造一个简单迭代器,并将其加载至 GeneratorDataset

# 迭代器
class Iterator:
    def __init__(self):
        self._index = 0
        self._data = np.random.sample((5, 2))
        self._label = np.random.sample((5, 1))

    def __next__(self):
        if self._index >= len(self._data):
            raise StopIteration
        else:
            item = (self._data[self._index], self._label[self._index])
            self._index += 1
            return item

    def __iter__(self):
        self._index = 0
        return self

    def __len__(self):
        return len(self._data)
data = Iterator()
dataset = GeneratorDataset(source=data, column_names=["data", "label"])

为什么还要加一层[ ]?

请看 np.array([[1, 0, 2, 4]]np.random.sample((5, 2)) 的结果。他们都是:

[[num1, num2, ...]]

我们发现外面加上了[],这是为什么呢?回想一下我们怎么迭代数据集的,是吧?取第一项。我们可以作此验证:

tmp = np.array([[1,2,3,4,5]])

for i in tmp:
    print(i)
[1 2 3 4 5]

我们可以发现这正合我意,那如果不加[]呢?

tmp = np.array([1,2,3,4,5])

for i in tmp:
    print(i)
1
2
3
4
5

我们发现它变成了一项一项单独的数据,这不是我们想要的,所以我们还要加一层[]防止把数据分开了。

另外

运行上面代码可能会出现警告,别担心,这只是Windows端的多线程的兼容问题了。Mindspore是并行的。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值