以下为官方活动的学习笔记兼打卡记录,大部分内容来自活动资料,稍有删改,内含跳转至MindSpore文档的超链接,可作为字典查询。
一、MindSpore基本介绍
MindSpore的执行流程如下图所示:
蓝色方框是MindSpore主体框架,主要提供神经网络在训练、验证过程中相关的基础API功能,另外还会默认提供自动微分、自动并行等功能。
MindSpore Data模块,可以进行数据预处理,包括数据采样、数据迭代、数据格式转换等不同的数据操作。
MindSpore Insight模块对loss曲线、算子执行情况、权重参数变量等调试调优相关的数据进行可视化,方便用户在训练过程中进行调试调优。
AI安全最简单的场景就是从攻防的视角来看,例如,攻击者在训练阶段掺入恶意数据,影响AI模型推理能力,于是MindSpore推出了MindSpore Armour模块,为MindSpore提供AI安全机制。
蓝色方框往上的内容跟算法开发相关的用户更加贴近,包括存放大量的AI算法模型库ModelZoo,提供面向不同领域的开发工具套件MindSpore DevKit,另外还有高阶拓展库MindSpore Extend。
神经网络模型训练完后,可以导出模型或者加载存放在MindSpore Hub中已经训练好的模型。
二、张量 Tensor
张量(Tensor)是MindSpore网络运算中的基本数据结构,与数组和矩阵非常相似,可以看作高维数组。
import numpy as np
import mindspore
from mindspore import ops
from mindspore import Tensor, CSRTensor, COOTensor
2.1 创建张量
创建张量有以下四种方式:
“”“根据数据生成”“”
data = [1, 0, 1, 0]
x_data = Tensor(data)
“”“由numpy数组生成”“”
np_array = np.array(data)
x_np = Tensor(np_array)
“““使用init初始化器构造张量”””
from mindspore.common.initializer import One, Normal
# Initialize a tensor with ones
tensor1 = mindspore.Tensor(shape=(2, 2), dtype=mindspore.float32, init=One())
# Initialize a tensor from normal distribution
tensor2 = mindspore.Tensor(shape=(2, 2), dtype=mindspore.float32, init=Normal())
“““继承另一个张量的属性”””
x_ones = ops.ones_like(x_data)
x_zeros = ops.zeros_like(x_data)
2.2 张量的属性
张量的属性包括形状、数据类型、转置张量、单个元素大小、占用字节数量、维数、元素个数和每一维步长。
-
形状(shape):
Tensor
的shape,是一个tuple。 -
数据类型(dtype):
Tensor
的dtype,是MindSpore的一个数据类型。 -
单个元素大小(itemsize):
Tensor
中每一个元素占用字节数,是一个整数。 -
占用字节数量(nbytes):
Tensor
占用的总字节数,是一个整数。 -
维数(ndim):
Tensor
的秩,也就是len(tensor.shape),是一个整数。 -
元素个数(size):
Tensor
中所有元素的个数,是一个整数。 -
每一维步长(strides):
Tensor
每一维所需要的字节数,是一个tuple。
2.3 张量的索引与切片
Tensor索引与Numpy索引类似,索引从0开始编制,负索引表示按倒序编制,冒号:
和 ...
用于对数据进行切片。
tensor = Tensor(np.array([[0, 1], [2, 3]]).astype(np.float32))
print("First row: {}".format(tensor[0]))
print("value of bottom right corner: {}".format(tensor[1, 1]))
print("Last column: {}".format(tensor[:, -1]))
print("First column: {}".format(tensor[..., 0]))
First row: [0. 1.]
value of bottom right corner: 3.0
Last column: [1. 3.]
First column: [0. 2.]
2.4 张量的运算
- 普通算术运算包括:加(+)、减(-)、乘(*)、除(/)、取模(%)、整除(//)。
- concat将给定维度上的一系列张量连接起来。
- stack则是新增一个维度,在新增的维度上将两个张量合并起来。
- 使用 Tensor.asnumpy() 将Tensor变量转换为NumPy变量。
- 使用
Tensor()
将Numpy变量转换为Tensor变量。
2.5 稀疏张量
MindSpore现在已经支持最常用的CSR
和COO
两种稀疏数据格式,可以实现稀疏张量的高效储存与计算。
CSRTensor
的详细文档,请参考mindspore.CSRTensor。
COOTensor
的详细文档,请参考mindspore.COOTensor。
三、数据集 Dataset
MindSpore提供基于Pipeline的数据引擎,通过数据集(Dataset)和数据变换(Transforms)实现高效的数据预处理。其中Dataset是Pipeline的起始,用于加载原始数据。mindspore.dataset
提供了内置的文本、图像、音频等数据集加载接口,并提供了自定义数据集加载接口。
此外MindSpore的领域开发库也提供了大量的预加载数据集,可以使用API一键下载使用。
import numpy as np
from mindspore.dataset import vision
from mindspore.dataset import MnistDataset, GeneratorDataset
import matplotlib.pyplot as plt
3.1 数据集加载
以Mnist数据集为例,下载好数据集后,使用MnistDataset()
获取数据集对象,shuffle
操作控制是否打乱数据集。
train_dataset = MnistDataset("MNIST_Data/train", shuffle=False)
3.2 数据集迭代
数据集加载后,一般以迭代方式获取数据,然后送入神经网络中进行训练。我们可以用create_tuple_iterator或create_dict_iterator接口创建数据迭代器,迭代访问数据。
访问的数据类型默认为Tensor
;若设置output_numpy=True
,访问的数据类型为Numpy
。
3.3 数据集常用操作
Pipeline的设计理念使得数据集的常用操作采用dataset = dataset.operation()
的异步执行方式,执行操作返回新的Dataset,此时不执行具体操作,而是在Pipeline中加入节点,最终进行迭代时,并行执行整个Pipeline。
下面分别介绍几种常见的数据集操作。
shuffle
数据集随机shuffle
可以消除数据排列造成的分布不均问题。
map
map
操作是数据预处理的关键操作,可以针对数据集指定列(column)添加数据变换(Transforms),将数据变换应用于该列数据的每个元素,并返回包含变换后元素的新数据集。
例如,map
操作可以进行图像的缩放、格式转换、归一化等;进行文本的分词、映射等。
Dataset支持的不同变换类型详见数据变换Transforms。
batch
将数据集打包为固定大小的batch
是在有限硬件资源下使用梯度下降进行模型优化的折中方法,可以保证梯度下降的随机性和优化计算量。
一般我们会设置一个固定的batch size,将连续的数据分为若干批(batch)。
3.4 自定义数据集
mindspore.dataset
模块提供了一些常用的公开数据集和标准格式数据集的加载API。
对于MindSpore暂不支持直接加载的数据集,可以构造自定义数据加载类或自定义数据集生成函数的方式来生成数据集,然后通过GeneratorDataset
接口实现自定义方式的数据集加载。
GeneratorDataset
支持通过可随机访问数据集对象、可迭代数据集对象和生成器(generator)构造自定义数据集,下面分别对其进行介绍。
可随机访问数据集
可随机访问数据集是实现了__getitem__
和__len__
方法的数据集,表示可以通过索引/键直接访问对应位置的数据样本。
例如,当使用dataset[idx]
访问这样的数据集时,可以读取dataset内容中第idx个样本或标签。
可迭代数据集
可迭代的数据集是实现了__iter__
和__next__
方法的数据集,表示可以通过迭代的方式逐步获取数据样本。这种类型的数据集特别适用于随机访问成本太高或者不可行的情况。
例如,当使用iter(dataset)
的形式访问数据集时,可以读取从数据库、远程服务器返回的数据流。
下面构造一个简单迭代器,并将其加载至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)
[Tensor(shape=[], dtype=Int64, value= 1)]
[Tensor(shape=[], dtype=Int64, value= 2)]
[Tensor(shape=[], dtype=Int64, value= 3)]
[Tensor(shape=[], dtype=Int64, value= 4)]
生成器
生成器也属于可迭代的数据集类型,其直接依赖Python的生成器类型generator
返回数据,直至生成器抛出StopIteration
异常。