• [活动体验] MindSpore———Ascend910与GPU推理
    MindIR是MindSpore的统一模型文件,同时存储了网络结构和权重参数值,定义了可扩展的图结构以及算子的IR表示,消除了不同后端的模型差异,一般用于跨硬件平台执行推理任务。Checkpoint是训练参数,采用了Protocol Buffers格式,所以说学会各种东西的推理原理是很重要的,同样的我们要学使用checkpoint格式文件单卡推理如果我们有做好的模型我们可以用本地模型推理,我们可以通过load_checkpoint和load_param_into_net接口从本地加载模型与参数,传入验证数据集后使用model.eval即可进行模型验证,使用model.predict可进行模型推理。在这里我们下载MindSpore Hub中已经预训练好的LeNet和MINIST数据集进行推理演示:!mkdir -p ./datasets/MNIST_Data/test!wget -NP ./datasets/MNIST_Data/test https://mindspore-website.obs.myhuaweicloud.com/notebook/datasets/mnist/t10k-labels-idx1-ubyte!wget -NP ./datasets/MNIST_Data/test https://mindspore-website.obs.myhuaweicloud.com/notebook/datasets/mnist/t10k-images-idx3-ubyte!mkdir -p ./checkpoint!wget -NP ./checkpoint https://download.mindspore.cn/model_zoo/r1.1/lenet_ascend_v111_offical_cv_mnist_bs32_acc98/lenet_ascend_v111_offical_cv_mnist_bs32_acc98.ckpt配置运行所需信息,进行推理的数据处理:代码如下:import osimport argparsefrom mindspore import contextimport mindspore.dataset as dsimport mindspore.dataset.transforms.c_transforms as Cimport mindspore.dataset.vision.c_transforms as CVfrom mindspore.dataset.vision import Interfrom mindspore import dtype as mstypecontext.set_context(mode=context.GRAPH_MODE, device_target="GPU")def create_dataset(data_path, batch_size=32, repeat_size=1,                   num_parallel_workers=1):    # 定义数据集    mnist_ds = ds.MnistDataset(data_path)    resize_height, resize_width = 32, 32    rescale = 1.0 / 255.0    shift = 0.0    rescale_nml = 1 / 0.3081    shift_nml = -1 * 0.1307 / 0.3081    # 定义所需要操作的map映射    resize_op = CV.Resize((resize_height, resize_width), interpolation=Inter.LINEAR)    rescale_nml_op = CV.Rescale(rescale_nml, shift_nml)    rescale_op = CV.Rescale(rescale, shift)    hwc2chw_op = CV.HWC2CHW()    type_cast_op = C.TypeCast(mstype.int32)    # 使用map映射函数,将数据操作应用到数据集    mnist_ds = mnist_ds.map(operations=type_cast_op, input_columns="label", num_parallel_workers=num_parallel_workers)    mnist_ds = mnist_ds.map(operations=resize_op, input_columns="image", num_parallel_workers=num_parallel_workers)    mnist_ds = mnist_ds.map(operations=rescale_op, input_columns="image", num_parallel_workers=num_parallel_workers)    mnist_ds = mnist_ds.map(operations=rescale_nml_op, input_columns="image", num_parallel_workers=num_parallel_workers)    mnist_ds = mnist_ds.map(operations=hwc2chw_op, input_columns="image", num_parallel_workers=num_parallel_workers)    # 进行shuffle、batch操作    buffer_size = 10000    mnist_ds = mnist_ds.shuffle(buffer_size=buffer_size)    mnist_ds = mnist_ds.batch(batch_size, drop_remainder=True)    return mnist_ds创建LeNet模型:代码如下:import mindspore.nn as nnfrom mindspore.common.initializer import Normalclass LeNet5(nn.Cell):    """    Lenet网络结构    """    def __init__(self, num_class=10, num_channel=1):        super(LeNet5, self).__init__()        # 定义所需要的运算        self.conv1 = nn.Conv2d(num_channel, 6, 5, pad_mode='valid')        self.conv2 = nn.Conv2d(6, 16, 5, pad_mode='valid')        self.fc1 = nn.Dense(16 * 5 * 5, 120, weight_init=Normal(0.02))        self.fc2 = nn.Dense(120, 84, weight_init=Normal(0.02))        self.fc3 = nn.Dense(84, num_class, weight_init=Normal(0.02))        self.relu = nn.ReLU()        self.max_pool2d = nn.MaxPool2d(kernel_size=2, stride=2)        self.flatten = nn.Flatten()    def construct(self, x):        # 使用定义好的运算构建前向网络        x = self.conv1(x)        x = self.relu(x)        x = self.max_pool2d(x)        x = self.conv2(x)        x = self.relu(x)        x = self.max_pool2d(x)        x = self.flatten(x)        x = self.fc1(x)        x = self.relu(x)        x = self.fc2(x)        x = self.relu(x)        x = self.fc3(x)        return x# 实例化网络net = LeNet5()在推理进行前,需要使用load_checkpoint和load_param_into_net接口从本地加载模型与参数。这样一来就可以使用本地模型完成后面的推理过程。代码如下:from mindspore import load_checkpoint, load_param_into_netckpt_file_name = "./checkpoint/lenet_ascend_v111_offical_cv_mnist_bs32_acc98.ckpt"param_dict = load_checkpoint(ckpt_file_name)load_param_into_net(net, param_dict)设置损失函数与优化器,并调用model接口创建对象:代码如下:import numpy as npfrom mindspore.nn import Accuracyfrom mindspore import Model, Tensornet_loss = nn.SoftmaxCrossEntropyWithLogits(sparse=True, reduction="mean")net_opt = nn.Momentum(net.trainable_params(), learning_rate=0.01, momentum=0.9)model = Model(net, net_loss, net_opt, metrics={"Accuracy": Accuracy()})下面调用model.eval接口执行验证过程:mnist_path = "./datasets/MNIST_Data/test"ds_eval = create_dataset(mnist_path)acc = model.eval(ds_eval, dataset_sink_mode=False)print("============== {} ==============".format(acc))运行结果如下:调用model.predict接口执行验证过程,这里选取数据集中的一张图片进行预测:ds_eval = ds_eval.create_dict_iterator()data = next(ds_eval)# images为测试图片,labels为测试图片的实际分类images = data["image"].asnumpy()labels = data["label"].asnumpy()# 使用函数model.predict预测image对应分类output = model.predict(Tensor(data['image']))predicted = np.argmax(output.asnumpy(), axis=1)# 输出预测分类与实际分类print(f'Predicted: "{predicted[0]}", Actual: "{labels[0]}"')运行结果入下:
  • [活动体验] MindSpore笔记———模型参数保存和加载
    分布式训练进行模型参数的保存之前,需要先按照Ascend分布式训练,CPU分布训练配置分布式环境变量和集合通信库。涵盖的分布式训练模式包括自动并行(Auto Parallel)与数据并行(Data Parallel)。参数的保存和加载都有很多种形式,分以下几种:自动并行模式(Auto Parallel)下模型参数的保存和加载与非分布式训练的模型参数保存和加载用法相同,以Ascend分布式训练为例,只需在Ascend训练网络步骤中的test_train_cifar方法中添加配置CheckpointConfig和ModelCheckpoint,即可实现模型参数的保存。需要注意的是,并行模式下需要对每张卡上运行的脚本指定不同的checkpoint保存路径,防止读写文件时发生冲突,具体代码如下:from mindspore.train.callback import ModelCheckpoint, CheckpointConfigdef test_train_cifar(epoch_size=10):    context.set_auto_parallel_context(parallel_mode=ParallelMode.AUTO_PARALLEL, gradients_mean=True)    loss_cb = LossMonitor()    dataset = create_dataset(data_path)    batch_size = 32    num_classes = 10    net = resnet50(batch_size, num_classes)    loss = SoftmaxCrossEntropyExpand(sparse=True)    opt = Momentum(filter(lambda x: x.requires_grad, net.get_parameters()), 0.01, 0.9)    ckpt_config = CheckpointConfig()    ckpt_callback = ModelCheckpoint(prefix='auto_parallel', directory="./ckpt_" + str(get_rank()) + "/", config=ckpt_config)    model = Model(net, loss_fn=loss, optimizer=opt)    model.train(epoch_size, dataset, callbacks=[loss_cb, ckpt_callback], dataset_sink_mode=True)整理并且保存后,checkpoint文件后,我们还可以可以很容易加载模型参数进行推理或再训练场景,如用于再训练场景可使用如下代码加载模型:from mindspore import load_checkpoint, load_param_into_netnet = resnet50(batch_size=32, num_classes=10)# The parameter for load_checkpoint is a .ckpt file which has been successfully savedparam_dict = load_checkpoint('...')load_param_into_net(net, param_dict)数据并行模式(Data Parallel)checkpoint的使用方法和自动并行模式(Auto Parallel)一样,只需要将test_train_cifar中:context.set_auto_parallel_context(parallel_mode=ParallelMode.AUTO_PARALLEL, gradients_mean=True)改为:context.set_auto_parallel_context(parallel_mode=ParallelMode.DATA_PARALLEL, gradients_mean=True)即可。
  • [活动体验]  MindSpore学习———动态图与静态图(Graph and PyNative)
    图片的形式主要分为两种形式,也是基本常用的两种。Graph模式:静态图模式或者图模式,将神经网络模型编译成一整张图,然后下发执行。该模式利用图优化等技术提高运行性能,同时有助于规模部署和跨平台运行。PyNative模式:动态图模式,将神经网络中的各个算子逐一下发执行,方便用户编写和调试神经网络模型。两种模式字啊一定情况下可以相互转换,但不能随意切换需要有辅助的东西。二者的主要区别也十分的明显。使用场景:Graph模式需要一开始就构建好网络结构,然后框架做整图优化和执行,比较适合网络固定没有变化,且需要高性能的场景。而PyNative模式逐行执行算子,支持单独求梯度。网络执行:Graph模式和PyNative模式在执行相同的网络和算子时,精度效果是一致的。由于Graph模式运用了图优化、计算图整图下沉等技术,Graph模式执行网络的性能和效率更高。代码调试:在脚本开发和网络流程调试中,推荐使用PyNative模式进行调试。在PyNative模式下,可以方便地设置断点,获取网络执行的中间结果,也可以通过pdb的方式对网络进行调试。而Graph模式无法设置断点,只能先指定算子进行打印,然后在网络执行完成后查看输出结果。有了这些区别我们就可以灵活的运用这两种模式。转换代码如下:import numpy as npimport mindspore.nn as nnfrom mindspore import context, Tensor, ParameterTuple, ms_functionimport mindspore.ops as opsfrom mindspore import dtype as mstypefrom mindspore.common.initializer import Normalfrom mindspore.nn import Dense, WithLossCell, SoftmaxCrossEntropyWithLogits, Momentum# 设定为Graph模式,也可替换为PYNATIVE_MODEcontext.set_context(mode=context.GRAPH_MODE, device_target="Ascend")执行单算子代码如下:# 打印Conv2d算子的输出conv = nn.Conv2d(3, 4, 3, bias_init='zeros')input_data = Tensor(np.ones([1, 3, 5, 5]).astype(np.float32))output = conv(input_data)print(output.asnumpy())运行结果如下:执行普通函数将若干算子组合成一个函数,然后直接通过函数调用的方式执行这些算子,并打印相关结果,如下例所示。代码如下:def add_func(x, y):    z = ops.add(x, y)    z = ops.add(z, x)    return zx = Tensor(np.ones([3, 3], dtype=np.float32))y = Tensor(np.ones([3, 3], dtype=np.float32))output = add_func(x, y)print(output.asnumpy())结果如下:PyNative模式说明性能优化正如文章开头所说,Graph模式适合高性能的场景,但PyNative模式中也提供了性能优化的手段。MindSpore提供了Staging功能,该功能可以在PyNative模式下将Python函数或者Python类的方法编译成计算图,通过图优化等技术提高运行速度,是一种混合运行机制。Staging功能的使用通过ms_function装饰器达成,该装饰器会将模块编译成计算图,在给定输入之后,以图的形式下发执行。如下例所示:# 导入ms_functionfrom mindspore import ms_function# 仍设定为PyNative模式context.set_context(mode=context.PYNATIVE_MODE, device_target="Ascend")add = ops.Add()# 使用装饰器编译计算图@ms_functiondef add_fn(x, y):    res = add(x, y)    return resx = Tensor(np.ones([4, 4]).astype(np.float32))y = Tensor(np.ones([4, 4]).astype(np.float32))z = add_fn(x, y)print(z.asnumpy())运行结果如下:在加装了ms_function装饰器的函数中,如果包含不需要进行参数训练的算子(如pooling、add等算子),则这些算子可以在被装饰的函数中直接调用,如上例所示。如果被装饰的函数中包含了需要进行参数训练的算子(如Convolution、BatchNorm等算子),则这些算子必须在被装饰的函数之外完成实例化操作。代码如下:# Conv2d实例化操作conv_obj = nn.Conv2d(in_channels=3, out_channels=4, kernel_size=3, stride=2, padding=0)conv_obj.init_parameters_data()@ms_functiondef conv_fn(x):    res = conv_obj(x)    return resinput_data = np.random.randn(2, 3, 6, 6).astype(np.float32)z = conv_fn(Tensor(input_data))print(z.asnumpy())运行代码如下:
  • [活动体验] MindSpore记录———使用字符级循环神经网络分类名称
    循环神经网络(Recurrent Neural Network, RNN)该类网络是以序列(sequence)数据为输入,在序列的演进方向进行递归(recursion)且所有节点(循环单元)按链式连接的递归神经网络(recursive neural network),常用于NLP领域当中来解决序列化数据的建模问题。准备数据数据集是来自18种语言的数千种姓氏,点击这里下载数据,并将其提取到当前目录。数据集目录结构为data/names,目录中包含 18 个文本文件,名称为[Language].txt。 每个文件包含一系列名称,每行一个名称。数据大多数是罗马化的,需要将其从Unicode转换为ASCII。可在Jupyter Notebook中执行以下代码完成数据集的下载,并将数据集解压完成。数据处理导入:from io import openimport globimport osimport unicodedataimport string定义find_files函数,查找符合通配符要求的文件。代码如下:def find_files(path):    return glob.glob(path)print(find_files('data/names/*.txt'))创建网络创建的RNN网络只有i2o和i2h两个线性层,它们在输入input和隐藏状态hidden下运行,在线性层i2o的输出之后是LogSoftmax层。其中,网络结构如图所示。代码如下:from mindspore import nn, opsclass RNN(nn.Cell):    def __init__(self, input_size, hidden_size, output_size):        super(RNN, self).__init__()        self.hidden_size = hidden_size        self.i2h = nn.Dense(input_size + hidden_size, hidden_size)        self.i2o = nn.Dense(input_size + hidden_size, output_size)        self.softmax = nn.LogSoftmax(axis=1)    def construct(self, input, hidden):        op = ops.Concat(axis=1)        combined = op((input, hidden))        hidden = self.i2h(combined)        output = self.i2o(combined)        output = self.softmax(output)        return output, hidden    def initHidden(self):        return Tensor(np.zeros((1, self.hidden_size)),mstype.float32)n_hidden = 128rnn = RNN(n_letters, n_hidden, n_categories)我们要要运行此网络,我们需要输入代表当前字母的one-hot向量,以及上一个字母输出的隐藏状态(将隐藏状态初始化为0)。此网络将输出属于每种语言的概率和下一个字母需要输入的隐藏状态。代码如下:input = letter_to_tensor('A')hidden = Tensor(np.zeros((1, n_hidden)), mstype.float32)output, next_hidden = rnn(input, hidden) 为了提高效率,避免在每一步中都创建一个新向量,同时采取切片操作。input = line_to_tensor('Albert')hidden = Tensor(np.zeros((1, n_hidden)), mstype.float32)output, next_hidden = rnn(input[0], hidden)print(output)运行结果如下:中每个数字都代表了分类的可能性。
  • [活动体验] MindSpore学习笔记15———Ascend910与GPU推理
    MindIR是MindSpore的统一模型文件,同时存储了网络结构和权重参数值,定义了可扩展的图结构以及算子的IR表示,消除了不同后端的模型差异,一般用于跨硬件平台执行推理任务。Checkpoint是训练参数,采用了Protocol Buffers格式,所以说学会各种东西的推理原理是很重要的,同样的我们要学使用checkpoint格式文件单卡推理如果我们有做好的模型我们可以用本地模型推理,我们可以通过load_checkpoint和load_param_into_net接口从本地加载模型与参数,传入验证数据集后使用model.eval即可进行模型验证,使用model.predict可进行模型推理。在这里我们下载MindSpore Hub中已经预训练好的LeNet和MINIST数据集进行推理演示:!mkdir -p ./datasets/MNIST_Data/test!wget -NP ./datasets/MNIST_Data/test https://mindspore-website.obs.myhuaweicloud.com/notebook/datasets/mnist/t10k-labels-idx1-ubyte!wget -NP ./datasets/MNIST_Data/test https://mindspore-website.obs.myhuaweicloud.com/notebook/datasets/mnist/t10k-images-idx3-ubyte!mkdir -p ./checkpoint!wget -NP ./checkpoint https://download.mindspore.cn/model_zoo/r1.1/lenet_ascend_v111_offical_cv_mnist_bs32_acc98/lenet_ascend_v111_offical_cv_mnist_bs32_acc98.ckpt配置运行所需信息,进行推理的数据处理:代码如下:import osimport argparsefrom mindspore import contextimport mindspore.dataset as dsimport mindspore.dataset.transforms.c_transforms as Cimport mindspore.dataset.vision.c_transforms as CVfrom mindspore.dataset.vision import Interfrom mindspore import dtype as mstypecontext.set_context(mode=context.GRAPH_MODE, device_target="GPU")def create_dataset(data_path, batch_size=32, repeat_size=1,                   num_parallel_workers=1):    # 定义数据集    mnist_ds = ds.MnistDataset(data_path)    resize_height, resize_width = 32, 32    rescale = 1.0 / 255.0    shift = 0.0    rescale_nml = 1 / 0.3081    shift_nml = -1 * 0.1307 / 0.3081    # 定义所需要操作的map映射    resize_op = CV.Resize((resize_height, resize_width), interpolation=Inter.LINEAR)    rescale_nml_op = CV.Rescale(rescale_nml, shift_nml)    rescale_op = CV.Rescale(rescale, shift)    hwc2chw_op = CV.HWC2CHW()    type_cast_op = C.TypeCast(mstype.int32)    # 使用map映射函数,将数据操作应用到数据集    mnist_ds = mnist_ds.map(operations=type_cast_op, input_columns="label", num_parallel_workers=num_parallel_workers)    mnist_ds = mnist_ds.map(operations=resize_op, input_columns="image", num_parallel_workers=num_parallel_workers)    mnist_ds = mnist_ds.map(operations=rescale_op, input_columns="image", num_parallel_workers=num_parallel_workers)    mnist_ds = mnist_ds.map(operations=rescale_nml_op, input_columns="image", num_parallel_workers=num_parallel_workers)    mnist_ds = mnist_ds.map(operations=hwc2chw_op, input_columns="image", num_parallel_workers=num_parallel_workers)    # 进行shuffle、batch操作    buffer_size = 10000    mnist_ds = mnist_ds.shuffle(buffer_size=buffer_size)    mnist_ds = mnist_ds.batch(batch_size, drop_remainder=True)    return mnist_ds创建LeNet模型:代码如下:import mindspore.nn as nnfrom mindspore.common.initializer import Normalclass LeNet5(nn.Cell):    """    Lenet网络结构    """    def __init__(self, num_class=10, num_channel=1):        super(LeNet5, self).__init__()        # 定义所需要的运算        self.conv1 = nn.Conv2d(num_channel, 6, 5, pad_mode='valid')        self.conv2 = nn.Conv2d(6, 16, 5, pad_mode='valid')        self.fc1 = nn.Dense(16 * 5 * 5, 120, weight_init=Normal(0.02))        self.fc2 = nn.Dense(120, 84, weight_init=Normal(0.02))        self.fc3 = nn.Dense(84, num_class, weight_init=Normal(0.02))        self.relu = nn.ReLU()        self.max_pool2d = nn.MaxPool2d(kernel_size=2, stride=2)        self.flatten = nn.Flatten()    def construct(self, x):        # 使用定义好的运算构建前向网络        x = self.conv1(x)        x = self.relu(x)        x = self.max_pool2d(x)        x = self.conv2(x)        x = self.relu(x)        x = self.max_pool2d(x)        x = self.flatten(x)        x = self.fc1(x)        x = self.relu(x)        x = self.fc2(x)        x = self.relu(x)        x = self.fc3(x)        return x# 实例化网络net = LeNet5()在推理进行前,需要使用load_checkpoint和load_param_into_net接口从本地加载模型与参数。这样一来就可以使用本地模型完成后面的推理过程。代码如下:from mindspore import load_checkpoint, load_param_into_netckpt_file_name = "./checkpoint/lenet_ascend_v111_offical_cv_mnist_bs32_acc98.ckpt"param_dict = load_checkpoint(ckpt_file_name)load_param_into_net(net, param_dict)设置损失函数与优化器,并调用model接口创建对象:代码如下:import numpy as npfrom mindspore.nn import Accuracyfrom mindspore import Model, Tensornet_loss = nn.SoftmaxCrossEntropyWithLogits(sparse=True, reduction="mean")net_opt = nn.Momentum(net.trainable_params(), learning_rate=0.01, momentum=0.9)model = Model(net, net_loss, net_opt, metrics={"Accuracy": Accuracy()})下面调用model.eval接口执行验证过程:mnist_path = "./datasets/MNIST_Data/test"ds_eval = create_dataset(mnist_path)acc = model.eval(ds_eval, dataset_sink_mode=False)print("============== {} ==============".format(acc))运行结果如下:调用model.predict接口执行验证过程,这里选取数据集中的一张图片进行预测:ds_eval = ds_eval.create_dict_iterator()data = next(ds_eval)# images为测试图片,labels为测试图片的实际分类images = data["image"].asnumpy()labels = data["label"].asnumpy()# 使用函数model.predict预测image对应分类output = model.predict(Tensor(data['image']))predicted = np.argmax(output.asnumpy(), axis=1)# 输出预测分类与实际分类print(f'Predicted: "{predicted[0]}", Actual: "{labels[0]}"')运行结果入下:
  • [活动体验] mindspore-lite 转换tflite图像分类模型
    1.下载tflite模型https://www.tensorflow.org/lite/guide/hosted_models因为要用mslite的量化,需要下tflite的浮点模型而不是tflite量化的模型。比如https://storage.googleapis.com/download.tensorflow.org/models/tflite/model_zoo/upload_20180427/inception_v3_2018_04_27.tgz下载后解压,得到tflite,pb等文件。注意tflite的模型图像尺寸不同,有的是224,有的是299。2.制作校准集mslite量化工具不能自行预处理图像,因而不能给jpeg的图像,需要转成二进制浮点数据,且图像数据排布是n,h,w,c。数组是行优先(c/c++)。这里用pytorch进行预处理:变形,裁剪,归一化。tflite模型的归一化都是0.5。https://git.cyh.ac.cn/cyh/mindsporelite-image-classification/src/master/np.py这里顺便把验证集也做成二进制的,方便推理时用。这里用的imagenet数据集是按类分文件夹的。3.转换模型,量化模型以inception v3为例,转换浮点模型和量化模型# floatconverter_lite --fmk=TFLITE --modelFile=inception_v3.tflite --outputFile=inception_v3.float# quantconverter_lite --fmk=TFLITE --modelFile=inception_v3.tflite         --outputFile=inception_v3.quant         --quantType=PostTraining --configFile=config/kl_nobias.cfg --quantWeightChannel=0配置文件image_path=/data/calib_data_c_299batch_count=100method_x=KLthread_num=4bias_correction=false转换完成得到inception_v3.float.ms和inception_v3.quant.ms两个模型。4.编写推理程序mslite似乎没有python的api,只有c++和java(Android)的。这里用c++写一个简单的推理。数据预处理也不在c++里写了。数据加载和推理按理可以用并发流水之类加速的,这里也不写了。但多线程还是得写一下,要不cpu推理50000张很慢。https://git.cyh.ac.cn/cyh/mindsporelite-image-classification/src/master/infer.cc编译命令g++ infer.cc -I. -Llib -lmindspore-lite -lpthread -o classification -O35.运行推理./classification msmodels/inception_v3.float.ms 50000 40 /data/val_data_c/%05d.bin这里valpath是一个c格式化字符串6.精度结果tflite-fp32 tflite模型官方标称的精度mslite-fp32 使用mslite转换的浮点模型的精度量化的模型:kl+bias correctionklmax+bias correctionmax从上面来看,biascorrection不是稳定提升kl也没有明显优势
  • [活动体验] MindSpore模型推理
    如果想在应用中使用自定义的MindSpore Lite模型,需要告知推理器模型所在的位置。推理器加载模型的方式有以下三种:加载本地模型。加载远程模型。混合加载本地和远程模型。加载模型方式一:加载并初始化本地模型。加载模型。Assets目录MLCustomLocalModel localModel = new MLCustomLocalModel.Factory("yourmodelname").setAssetPathFile("assetpathname").create();自定义目录    MLCustomLocalModel localModel = new MLCustomLocalModel.Factory("yourmodelname").setLocalFullPathFile("sdfullpathname").create();根据模型创建推理器。final MLModelExecutorSettings settings = new MLModelExecutorSettings.Factory(localModel).create();final MLModelExecutor modelExecutor = MLModelExecutor.getInstance(settings);// 调用模型推理,实现细节见下节模型推理;Bitmap待处理的图片。executorImpl(modelExecutor, bitmap);方式二:加载并初始化远程模型。加载远程模型时需先判断远程模型是否已经下载完成:final MLCustomRemoteModel remoteModel =new MLCustomRemoteModel.Factory("yourmodelname").create();MLLocalModelManager.getInstance().isModelExist(remoteModel).addOnSuccessListener(new OnSuccessListener<Boolean>() {@Overridepublic void onSuccess(Boolean isDownload) {if (isDownload) {final MLModelExecutorSettings settings =10.                             new MLModelExecutorSettings.Factory(remoteModel).create();11.                     final MLModelExecutor modelExecutor = MLModelExecutor.getInstance(settings);12.                     executorImpl(modelExecutor, bitmap);13.                 }14.             }15.         })16.         .addOnFailureListener(new OnFailureListener() {17.             @Override18.             public void onFailure(Exception e) {19.                 // 异常处理。20.             }21.         });方式三:混合加载本地和远程模型。推荐使用这种方式,此方法可以确保当远程模型未下载时加载本地模型。localModel = new MLCustomLocalModel.Factory("localModelName").setAssetPathFile("assetpathname").create();remoteModel =new MLCustomRemoteModel.Factory("yourremotemodelname").create();MLLocalModelManager.getInstance()// 判断远程模型是否存在。.isModelExist(remoteModel).addOnSuccessListener(new OnSuccessListener<Boolean>() {@Override10.             public void onSuccess(Boolean isDownloaded) {11.                 MLModelExecutorSettings settings;12.                 // 如果远程模型存在,优先加载本地已有的远程模型,否则加载本地已有的本地模型。13.                 if (isDownloaded) {14.                     settings = new MLModelExecutorSettings.Factory(remoteModel).create();15.                 } else {16.                     settings = new MLModelExecutorSettings.Factory(localModel).create();17.                 }18.                 final MLModelExecutor modelExecutor = MLModelExecutor.getInstance(settings);19.                 executorImpl(modelExecutor, bitmap);20.             }21.         })22.         .addOnFailureListener(new OnFailureListener() {23.             @Override24.             public void onFailure(Exception e) {25.                 // 异常处理。26.             }27.         });模型推理器进行推理本章示例中的“executorImpl”方法为模型推理的详细流程,声明如下:void executorImpl(final MLModelExecutor modelExecutor, Bitmap bitmap)以下示例会借助“executorImpl”方法详细演示推理器调用的自定义模型推理的整个过程,此方法内主要包含如下关键处理流程:设置输入输出格式。需要知道模型的输入输出格式。通过MLModelInputOutputSettings.Factory把输入输出格式设置到模型推理器。比如,一个图片分类模型的输入格式为一个float类型的1x224x224x3数组(表示只推理一张大小为224x224的三通道 (RGB)图片),输出格式为一个长度为1001的float型列表(每个值表示该图片经模型推理后1001个类别中各类别的可能性)。对于此模型,请按照以下方式设置输入输出格式:inOutSettings = new MLModelInputOutputSettings.Factory().setInputFormat(0, MLModelDataType.FLOAT32, new int[] {1, 224, 224, 3}).setOutputFormat(0, MLModelDataType.FLOAT32, new int[] {1, 1001}).create();把图片数据输入到推理器。注意当前版本MindSpore生成的模型使用的数据格式与tflite类型的模型使用的数据格式相同,均为NHWC,caffe类型的模型使用的数据格式为NCHW。若需要将模型由caffe转换到MindSpore,请设置为NHWC格式。如下NHWC示例:1*224*224*3表示一张(batch N),大小为224(height H)*224(width W),3通道(channels C)的图片。private void executorImpl(final MLModelExecutor modelExecutor, Bitmap bitmap){// 准备输入数据。final Bitmap inputBitmap = Bitmap.createScaledBitmap(srcBitmap, 224, 224, true);final float[][][][] input = new float[1][224][224][3];for (int i = 0; i < 224; i++) {for (int j = 0; j < 224; j++) {int pixel = inputBitmap.getPixel(i, j);input[batchNum][j][i][0] = (Color.red(pixel) - 127) / 128.0f;input[batchNum][j][i][1] = (Color.green(pixel) - 127) / 128.0f;10.             input[batchNum][j][i][2] = (Color.blue(pixel) - 127) / 128.0f;11.         }12.     }13.     MLModelInputs inputs = null;14.     try {15.         inputs = new MLModelInputs.Factory().add(input).create();16.         // 若模型需要多路输入,需要多次调用add()以便图片数据能够一次输入到推理器。17.     } catch (MLException e) {18.         // 处理输入数据格式化异常。19.     }20.21. // 执行推理。可以通过“addOnSuccessListener”来监听推理成功,在“onSuccess”回调中处理推理成功。同时,可以通过“addOnFailureListener”来监听推理失败,在“onFailure”中处理推理失败。22.     modelExecutor.exec(inputs, inOutSettings).addOnSuccessListener(new OnSuccessListener<MLModelOutputs>() {23.         @Override24.         public void onSuccess(MLModelOutputs mlModelOutputs) {25.             float[][] output = mlModelOutputs.getOutput(0);26.                 // 这里推理的返回结果在output数组里,可以进一步处理。27.                 }28.         }).addOnFailureListener(new OnFailureListener() {29.         @Override30.         public void onFailure(Exception e) {31.             // 推理异常。32.         }33.     });34. }
  • [活动体验] MindSpore模型的加载与保存
    上一篇文章是一个非常基础的线性神经网络模型,用于拟合一个给定的函数。因为这里我们是基于线性的模型,因此当我们需要去拟合一个更加高阶的函数的话,需要手动的处理,比如这里我们使用的平方函数。总结起来该模型可以抽象为:f(x)=ax2+bf(x)=ax2+b而这里产生训练集时,我们是加了一个随机的噪声,也就是:D(x)=ax2+b+noise代码如下:from mindspore import contextcontext.set_context(mode=context.GRAPH_MODE, device_target="GPU")import numpy as npfrom mindspore import dataset as dsfrom mindspore import nn, Tensor, Modelimport timefrom mindspore.train.callback import Callback, LossMonitor, ModelCheckpointdef get_data(num, a=2.0, b=3.0):    for _ in range(num):        x = np.random.uniform(-1.0, 1.0)        noise = np.random.normal(0, 0.03)        z = a * x ** 2 + b + noise        # 返回数据的时候就返回数据的平方        yield np.array([x**2]).astype(np.float32), np.array([z]).astype(np.float32)def create_dataset(num_data, batch_size=16, repeat_size=1):    input_data = ds.GeneratorDataset(list(get_data(num_data)), column_names=['x','z'])    input_data = input_data.batch(batch_size)    input_data = input_data.repeat(repeat_size)    return input_datadata_number = 1600 # 一共产生1600组数据batch_number = 16 # 分为16组分别进行优化repeat_number = 2 # 重复2次,可以取到更低的损失函数值ds_train = create_dataset(data_number, batch_size=batch_number, repeat_size=repeat_number)class LinearNet(nn.Cell):    def __init__(self):        super(LinearNet, self).__init__()        self.fc = nn.Dense(1, 1, 0.02, 0.02)    def construct(self, x):        x = self.fc(x)        return xnet = LinearNet()model_params = net.trainable_params()print ('Param Shape is: {}'.format(len(model_params)))for net_param in net.trainable_params():    print(net_param, net_param.asnumpy())net_loss = nn.loss.MSELoss()# 设定优化算法,常用的是Momentum和ADAMoptim = nn.Momentum(net.trainable_params(), learning_rate=0.005, momentum=0.9)model = Model(net, net_loss, optim)ckpt_cb = ModelCheckpoint()epoch = 1# 设定每8个batch训练完成后就播报一次,这里一共播报25次model.train(epoch, ds_train, callbacks=[LossMonitor(16), ckpt_cb], dataset_sink_mode=False)for net_param in net.trainable_params():    print(net_param, net_param.asnumpy())结果:可以看到,数据集的原因以及噪声的原因,导致结果有点不尽如人意。具体的误差还得通过测试集来进行验证:开始加载这些文件中所给出的模型,用于测试集的验证。模型加载from mindspore import contextcontext.set_context(mode=context.GRAPH_MODE, device_target="GPU")import mindspore.dataset as dsfrom mindspore import load_checkpoint, load_param_into_netfrom mindspore import nn, Tensor, Modelimport numpy as npclass LinearNet(nn.Cell):    def __init__(self):        super(LinearNet, self).__init__()        self.fc = nn.Dense(1,1,0.02,0.02)    def construct(self, x):        print ('x:', x)        x = self.fc(x)        print ('z:', x)        return xnet = LinearNet()param_dict = load_checkpoint("CKP-1_200.ckpt")load_param_into_net(net, param_dict)net_loss = nn.loss.MSELoss()model = Model(net, net_loss, metrics={"accuracy"})data = {'x':np.array([[0.01],[0.25],[1],[4],[9]]).astype(np.float32),        'z':np.array([3.02,3.5,5,11,21]).astype(np.float32)}dataset = ds.NumpySlicesDataset(data=data)dataset = dataset.batch(1)acc = model.eval(dataset, dataset_sink_mode=False)我们只是定义了一个非常简单的测试集,在实际场景中往往测试集也是非常大量的数据。结果误差 可以接受,成功
  • [活动体验] MindSpore线性网络拟合非线性函数实践
    前几天写了一篇线性函数的文章,现在半夜睡不着,再写一篇非线性的文章聊以解闷。我们先考虑一个最简单的非线性函数的场景:y=ax^2+b需要注意:如果要用线性神经网络来拟合非线性的函数,那么在给出参数的时候就要给出非线性的入参示例代码如下:from mindspore import contextcontext.set_context(mode=context.GRAPH_MODE, device_target="CPU")import numpy as npfrom mindspore import dataset as dsfrom mindspore import nn, Tensor, Modelimport timefrom mindspore.train.callback import Callback, LossMonitordef get_data(num, a=2.0, b=3.0):    for _ in range(num):        x = np.random.uniform(-1.0, 1.0)        noise = np.random.normal(0, 0.03)        z = a * x ** 2 + b + noise        # 返回数据的时候就返回数据的平方        yield np.array([x**2]).astype(np.float32), np.array([z]).astype(np.float32)def create_dataset(num_data, batch_size=16, repeat_size=1):    input_data = ds.GeneratorDataset(list(get_data(num_data)), column_names=['x','z'])    input_data = input_data.batch(batch_size)    input_data = input_data.repeat(repeat_size)    return input_datadata_number = 1600 # 一共产生1600组数据batch_number = 16 # 分为16组分别进行优化repeat_number = 2 # 重复2次,可以取到更低的损失函数值ds_train = create_dataset(data_number, batch_size=batch_number, repeat_size=repeat_number)dict_datasets = next(ds_train.create_dict_iterator())class LinearNet(nn.Cell):    def __init__(self):        super(LinearNet, self).__init__()        self.fc = nn.Dense(1, 1, 0.02, 0.02)    def construct(self, x):        x = self.fc(x)        return xnet = LinearNet()model_params = net.trainable_params()print ('Param Shape is: {}'.format(len(model_params)))for net_param in net.trainable_params():    print(net_param, net_param.asnumpy())net_loss = nn.loss.MSELoss()# 设定优化算法,常用的是Momentum和ADAMoptim = nn.Momentum(net.trainable_params(), learning_rate=0.005, momentum=0.9)model = Model(net, net_loss, optim)epoch = 1# 设定每8个batch训练完成后就播报一次,这里一共播报25次model.train(epoch, ds_train, callbacks=[LossMonitor(8)], dataset_sink_mode=False)for net_param in net.trainable_params():    print(net_param, net_param.asnumpy())效果如下:最后优化的结果为f(x)=1.8488435x+3.0522664f(x)=1.8488435x+3.0522664,可以看到距离我们所预期的f(x)=2x+3f(x)=2x+3已经是非常接近的,因为训练轮次太少,可能会对数据产生一定的影响。下面开始需要思考的东西:z(x,y)=ax^2+by^3+c代码:from mindspore import contextcontext.set_context(mode=context.GRAPH_MODE, device_target="CPU")import numpy as npfrom mindspore import dataset as dsfrom mindspore import nn, Tensor, Modelimport timefrom mindspore.train.callback import Callback, LossMonitordef get_data(num, a=2.0, b=3.0, c=5.0):    for _ in range(num):        x = np.random.uniform(-1.0, 1.0)        y = np.random.uniform(-1.0, 1.0)        noise = np.random.normal(0, 0.03)        z = a * x ** 2 + b * y ** 3 + c + noise        # 返回参数的时候压缩在一个数组内        yield np.array([x**2,y**3]).astype(np.float32), np.array([z]).astype(np.float32)def create_dataset(num_data, batch_size=16, repeat_size=1):    input_data = ds.GeneratorDataset(list(get_data(num_data)), column_names=['x','z'])    input_data = input_data.batch(batch_size)    input_data = input_data.repeat(repeat_size)    return input_datadata_number = 1600batch_number = 16repeat_number = 2ds_train = create_dataset(data_number, batch_size=batch_number, repeat_size=repeat_number)dict_datasets = next(ds_train.create_dict_iterator())class LinearNet(nn.Cell):    def __init__(self):        super(LinearNet, self).__init__()        # 神经网络的input和output维度设置为2,1        self.fc = nn.Dense(2, 1, 0.02, 0.02)    def construct(self, x):        x = self.fc(x)        return xnet = LinearNet()model_params = net.trainable_params()print ('Param Shape is: {}'.format(len(model_params)))for net_param in net.trainable_params():    print(net_param, net_param.asnumpy())net_loss = nn.loss.MSELoss()optim = nn.Momentum(net.trainable_params(), learning_rate=0.005, momentum=0.9)model = Model(net, net_loss, optim)epoch = 1model.train(epoch, ds_train, callbacks=[LossMonitor(8)], dataset_sink_mode=False)for net_param in net.trainable_params():    print(net_param, net_param.asnumpy())结果:这里得到的结果z(x,y)=1.9629341x2+2.9065483y3+5.004186z(x,y)=1.9629341x2+2.9065483y3+5.004186跟我们所预期的结果z(x,y)=2x2+3y3+5z(x,y)=2x2+3y3+5也是非常接近的。同样由于训练轮次的问题,结果稍受影响。问题不算太大,成功。
  • [活动体验] MindSpore模型优化与调参
    1.超参数 (超参)超参数是在开始学习过程之前设置值的参数,而不是通过训练得到的参数数据。通常情况下,需要对超参数进行优化,给学习机选择一组最优超参数,以提高学习的性能和效果。般会定义以下用于训练的超参:训练轮次(epoch):训练时遍历数据集的次数。批次大小(batch size):数据集进行分批读取训练,设定每个批次数据的大小。学习率(learning rate):设定 为中间值2.损失函数(loss function):损失函数用来评价模型的预测值和真实值不一样的程度,一般有:      0-1损失函数(zero-one loss)      绝对值损失函数      log对数损失函数      指数损失函数      Hinge 损失函数      交叉熵损失函数      以绝对误差损失函数为例,给定输出值和目标值,计算损失值,使用方法如下:import numpy as npimport mindspore.nn as nnfrom mindspore import Tensorloss = nn.L1Loss()output_data = Tensor(np.array([[1, 2, 3], [2, 3, 4]]).astype(np.float32))target_data = Tensor(np.array([[0, 2, 5], [3, 1, 1]]).astype(np.float32))print(loss(output_data, target_data))可以得到以下结果:3.优化器优化器就是在深度学习反向传播过程中,指引目标函数的各个参数往正确的方向更新合适的大小,使得更新后的各个参数让损失函数值不断逼近全局最小。我们需要构建一个优化器 对象,这个对象能够保持当前参数状态并基于计算得到的梯度进行参数更新。我们需要给它一个包含可需要优化的参数(必须是Variable对象)的迭代器from mindspore import nnoptim = nn.SGD(params=net.trainable_params(), learning_rate=0.1, weight_decay=0.0)
  • [活动体验] MindSpore学习笔记14———模型参数保存和加载
    分布式训练进行模型参数的保存之前,需要先按照Ascend分布式训练,CPU分布训练配置分布式环境变量和集合通信库。涵盖的分布式训练模式包括自动并行(Auto Parallel)与数据并行(Data Parallel)。参数的保存和加载都有很多种形式,分以下几种:自动并行模式(Auto Parallel)下模型参数的保存和加载与非分布式训练的模型参数保存和加载用法相同,以Ascend分布式训练为例,只需在Ascend训练网络步骤中的test_train_cifar方法中添加配置CheckpointConfig和ModelCheckpoint,即可实现模型参数的保存。需要注意的是,并行模式下需要对每张卡上运行的脚本指定不同的checkpoint保存路径,防止读写文件时发生冲突,具体代码如下:from mindspore.train.callback import ModelCheckpoint, CheckpointConfigdef test_train_cifar(epoch_size=10):    context.set_auto_parallel_context(parallel_mode=ParallelMode.AUTO_PARALLEL, gradients_mean=True)    loss_cb = LossMonitor()    dataset = create_dataset(data_path)    batch_size = 32    num_classes = 10    net = resnet50(batch_size, num_classes)    loss = SoftmaxCrossEntropyExpand(sparse=True)    opt = Momentum(filter(lambda x: x.requires_grad, net.get_parameters()), 0.01, 0.9)    ckpt_config = CheckpointConfig()    ckpt_callback = ModelCheckpoint(prefix='auto_parallel', directory="./ckpt_" + str(get_rank()) + "/", config=ckpt_config)    model = Model(net, loss_fn=loss, optimizer=opt)    model.train(epoch_size, dataset, callbacks=[loss_cb, ckpt_callback], dataset_sink_mode=True)整理并且保存后,checkpoint文件后,我们还可以可以很容易加载模型参数进行推理或再训练场景,如用于再训练场景可使用如下代码加载模型:from mindspore import load_checkpoint, load_param_into_netnet = resnet50(batch_size=32, num_classes=10)# The parameter for load_checkpoint is a .ckpt file which has been successfully savedparam_dict = load_checkpoint('...')load_param_into_net(net, param_dict)数据并行模式(Data Parallel)checkpoint的使用方法和自动并行模式(Auto Parallel)一样,只需要将test_train_cifar中:context.set_auto_parallel_context(parallel_mode=ParallelMode.AUTO_PARALLEL, gradients_mean=True)改为:context.set_auto_parallel_context(parallel_mode=ParallelMode.DATA_PARALLEL, gradients_mean=True)即可。
  • [活动体验] MindSpore学习笔记13———动态图与静态图(Graph and PyNative)
    图片的形式主要分为两种形式,也是基本常用的两种。Graph模式:静态图模式或者图模式,将神经网络模型编译成一整张图,然后下发执行。该模式利用图优化等技术提高运行性能,同时有助于规模部署和跨平台运行。PyNative模式:动态图模式,将神经网络中的各个算子逐一下发执行,方便用户编写和调试神经网络模型。两种模式字啊一定情况下可以相互转换,但不能随意切换需要有辅助的东西。二者的主要区别也十分的明显。使用场景:Graph模式需要一开始就构建好网络结构,然后框架做整图优化和执行,比较适合网络固定没有变化,且需要高性能的场景。而PyNative模式逐行执行算子,支持单独求梯度。网络执行:Graph模式和PyNative模式在执行相同的网络和算子时,精度效果是一致的。由于Graph模式运用了图优化、计算图整图下沉等技术,Graph模式执行网络的性能和效率更高。代码调试:在脚本开发和网络流程调试中,推荐使用PyNative模式进行调试。在PyNative模式下,可以方便地设置断点,获取网络执行的中间结果,也可以通过pdb的方式对网络进行调试。而Graph模式无法设置断点,只能先指定算子进行打印,然后在网络执行完成后查看输出结果。有了这些区别我们就可以灵活的运用这两种模式。转换代码如下:import numpy as npimport mindspore.nn as nnfrom mindspore import context, Tensor, ParameterTuple, ms_functionimport mindspore.ops as opsfrom mindspore import dtype as mstypefrom mindspore.common.initializer import Normalfrom mindspore.nn import Dense, WithLossCell, SoftmaxCrossEntropyWithLogits, Momentum# 设定为Graph模式,也可替换为PYNATIVE_MODEcontext.set_context(mode=context.GRAPH_MODE, device_target="Ascend")执行单算子代码如下:# 打印Conv2d算子的输出conv = nn.Conv2d(3, 4, 3, bias_init='zeros')input_data = Tensor(np.ones([1, 3, 5, 5]).astype(np.float32))output = conv(input_data)print(output.asnumpy())运行结果如下:执行普通函数将若干算子组合成一个函数,然后直接通过函数调用的方式执行这些算子,并打印相关结果,如下例所示。代码如下:def add_func(x, y):    z = ops.add(x, y)    z = ops.add(z, x)    return zx = Tensor(np.ones([3, 3], dtype=np.float32))y = Tensor(np.ones([3, 3], dtype=np.float32))output = add_func(x, y)print(output.asnumpy())结果如下:PyNative模式说明性能优化正如文章开头所说,Graph模式适合高性能的场景,但PyNative模式中也提供了性能优化的手段。MindSpore提供了Staging功能,该功能可以在PyNative模式下将Python函数或者Python类的方法编译成计算图,通过图优化等技术提高运行速度,是一种混合运行机制。Staging功能的使用通过ms_function装饰器达成,该装饰器会将模块编译成计算图,在给定输入之后,以图的形式下发执行。如下例所示:# 导入ms_functionfrom mindspore import ms_function# 仍设定为PyNative模式context.set_context(mode=context.PYNATIVE_MODE, device_target="Ascend")add = ops.Add()# 使用装饰器编译计算图@ms_functiondef add_fn(x, y):    res = add(x, y)    return resx = Tensor(np.ones([4, 4]).astype(np.float32))y = Tensor(np.ones([4, 4]).astype(np.float32))z = add_fn(x, y)print(z.asnumpy())运行结果如下:在加装了ms_function装饰器的函数中,如果包含不需要进行参数训练的算子(如pooling、add等算子),则这些算子可以在被装饰的函数中直接调用,如上例所示。如果被装饰的函数中包含了需要进行参数训练的算子(如Convolution、BatchNorm等算子),则这些算子必须在被装饰的函数之外完成实例化操作。代码如下:# Conv2d实例化操作conv_obj = nn.Conv2d(in_channels=3, out_channels=4, kernel_size=3, stride=2, padding=0)conv_obj.init_parameters_data()@ms_functiondef conv_fn(x):    res = conv_obj(x)    return resinput_data = np.random.randn(2, 3, 6, 6).astype(np.float32)z = conv_fn(Tensor(input_data))print(z.asnumpy())运行代码如下:
  • [活动体验] MindSpore学习笔记12———使用字符级循环神经网络分类名称
    循环神经网络(Recurrent Neural Network, RNN)该类网络是以序列(sequence)数据为输入,在序列的演进方向进行递归(recursion)且所有节点(循环单元)按链式连接的递归神经网络(recursive neural network),常用于NLP领域当中来解决序列化数据的建模问题。准备数据数据集是来自18种语言的数千种姓氏,点击这里下载数据,并将其提取到当前目录。数据集目录结构为data/names,目录中包含 18 个文本文件,名称为[Language].txt。 每个文件包含一系列名称,每行一个名称。数据大多数是罗马化的,需要将其从Unicode转换为ASCII。可在Jupyter Notebook中执行以下代码完成数据集的下载,并将数据集解压完成。数据处理导入:from io import openimport globimport osimport unicodedataimport string定义find_files函数,查找符合通配符要求的文件。代码如下:def find_files(path):    return glob.glob(path)print(find_files('data/names/*.txt'))创建网络创建的RNN网络只有i2o和i2h两个线性层,它们在输入input和隐藏状态hidden下运行,在线性层i2o的输出之后是LogSoftmax层。其中,网络结构如图所示。代码如下:from mindspore import nn, opsclass RNN(nn.Cell):    def __init__(self, input_size, hidden_size, output_size):        super(RNN, self).__init__()        self.hidden_size = hidden_size        self.i2h = nn.Dense(input_size + hidden_size, hidden_size)        self.i2o = nn.Dense(input_size + hidden_size, output_size)        self.softmax = nn.LogSoftmax(axis=1)    def construct(self, input, hidden):        op = ops.Concat(axis=1)        combined = op((input, hidden))        hidden = self.i2h(combined)        output = self.i2o(combined)        output = self.softmax(output)        return output, hidden    def initHidden(self):        return Tensor(np.zeros((1, self.hidden_size)),mstype.float32)n_hidden = 128rnn = RNN(n_letters, n_hidden, n_categories)我们要要运行此网络,我们需要输入代表当前字母的one-hot向量,以及上一个字母输出的隐藏状态(将隐藏状态初始化为0)。此网络将输出属于每种语言的概率和下一个字母需要输入的隐藏状态。代码如下:input = letter_to_tensor('A')hidden = Tensor(np.zeros((1, n_hidden)), mstype.float32)output, next_hidden = rnn(input, hidden) 为了提高效率,避免在每一步中都创建一个新向量,因此将使用line_to_tensor而不是letter_to_tensor,同时采取切片操作。input = line_to_tensor('Albert')hidden = Tensor(np.zeros((1, n_hidden)), mstype.float32)output, next_hidden = rnn(input[0], hidden)print(output)运行结果如下:中每个数字都代表了分类的可能性。
  • [活动体验] MindSpore自动微分-----升华之路
    经过前两篇的基础学习,现在应该对所用的数学知识有了些许的概念,下面进行正式的学习。MindSpore计算一阶导数方法:mindspore.ops.GradOperation (get_all=False, get_by_list=False, sens_param=False)其中get_all为False时,只会对第一个输入求导,为True时,会对所有输入求导;get_by_list为False时,不会对权重求导,为True时,会对权重求导;sens_param对网络的输出值做缩放以改变最终梯度.首先导入需要的模块和接口:import numpy as npimport mindspore.nn as nnimport mindspore.ops as opsfrom mindspore import Tensorfrom mindspore import ParameterTuple, Parameterfrom mindspore import dtype as mstype对输入求一阶导如果需要对输入进行求导,首先需要定义一个需要求导的网络,以一个由MatMul算子构成的网络(,)=∗∗f(x,y)=z∗x∗y为例。定义网络结构:class Net(nn.Cell):    def __init__(self):        super(Net, self).__init__()        self.matmul = ops.MatMul()        self.z = Parameter(Tensor(np.array([1.0], np.float32)), name='z')    def construct(self, x, y):        x = x * self.z        out = self.matmul(x, y)        return out接着定义求导网络,__init__函数中定义需要求导的网络self.net和ops.GradOperation,construct函数中对self.net进行求导。求导网络:class GradNetWrtX(nn.Cell):    def __init__(self, net):        super(GradNetWrtX, self).__init__()        self.net = net        self.grad_op = ops.GradOperation()    def construct(self, x, y):        gradient_function = self.grad_op(self.net)        return gradient_function(x, y)定义输入并打印:x = Tensor([[0.8, 0.6, 0.2], [1.8, 1.3, 1.1]], dtype=mstype.float32)y = Tensor([[0.11, 3.3, 1.1], [1.1, 0.2, 1.4], [1.1, 2.2, 0.3]], dtype=mstype.float32)output = GradNetWrtX(Net())(x, y)print(output)结果:对权重求一阶导弱如果需要对权重进行求导,将ops.GradOperation中的get_by_list设置为True:则GradNetWrtX结构为:class GradNetWrtX(nn.Cell):    def __init__(self, net):        super(GradNetWrtX, self).__init__()        self.net = net        self.params = ParameterTuple(net.trainable_params())        self.grad_op = ops.GradOperation(get_by_list=True)    def construct(self, x, y):        gradient_function = self.grad_op(self.net, self.params)        return gradient_function(x, y)运行并打印:output = GradNetWrtX(Net())(x, y)print(output)若需要对某些权重不进行求导,则在定义求导网络时,对相应的权重中requires_grad设置为False!!!!!!self.z = Parameter(Tensor(np.array([1.0], np.float32)), name='z', requires_grad=False)梯度值缩放可以通过sens_param参数对网络的输出值做缩放以改变最终梯度。首先将ops.GradOperation中的sens_param设置为True,并确定缩放指数,其维度与输出维度保持一致。缩放指数self.grad_wrt_output可以记作如下形式:self.grad_wrt_output = Tensor([[s1, s2, s3], [s4, s5, s6]])则GradNetWrtX结构为:class GradNetWrtX(nn.Cell):    def __init__(self, net):        super(GradNetWrtX, self).__init__()        self.net = net        self.grad_op = ops.GradOperation(sens_param=True)        self.grad_wrt_output = Tensor([[0.1, 0.6, 0.2], [0.8, 1.3, 1.1]], dtype=mstype.float32)    def construct(self, x, y):        gradient_function = self.grad_op(self.net)        return gradient_function(x, y, self.grad_wrt_output)output = GradNetWrtX(Net())(x, y)print(output)停止计算梯度我们可以使用stop_gradient来禁止网络内的算子对梯度的影响import numpy as npimport mindspore.nn as nnimport mindspore.ops as opsfrom mindspore import Tensorfrom mindspore import ParameterTuple, Parameterfrom mindspore import dtype as mstypefrom mindspore.ops import stop_gradientclass Net(nn.Cell):    def __init__(self):        super(Net, self).__init__()        self.matmul = ops.MatMul()    def construct(self, x, y):        out1 = self.matmul(x, y)        out2 = self.matmul(x, y)        out2 = stop_gradient(out2)        out = out1 + out2        return outclass GradNetWrtX(nn.Cell):    def __init__(self, net):        super(GradNetWrtX, self).__init__()        self.net = net        self.grad_op = ops.GradOperation()    def construct(self, x, y):        gradient_function = self.grad_op(self.net)        return gradient_function(x, y)x = Tensor([[0.8, 0.6, 0.2], [1.8, 1.3, 1.1]], dtype=mstype.float32)y = Tensor([[0.11, 3.3, 1.1], [1.1, 0.2, 1.4], [1.1, 2.2, 0.3]], dtype=mstype.float32)output = GradNetWrtX(Net())(x, y)print(output)在这里我们对out2设置了stop_gradient, 所以out2没有对梯度计算有任何的贡献。 如果我们删除out2 = stop_gradient(out2),那么输出值会变为:output = GradNetWrtX(Net())(x, y)print(output)在我们不对out2设置stop_gradient后, out2和out1会对梯度产生相同的影响。 
  • [活动体验] Mindspore自动微分之梯度下降-------升华之路
    最优化问题最优化问题是求解函数极值的问题,包括极大值和极小值。微积分为我们求函数的极值提供了一个统一的思路:找函数的导数等于0的点,因为在极值点处,导数必定为0。只要函数的可导的,我们就可以用这个万能的方法解决问题。在机器学习之类的实际应用中,我们一般将最优化问题统一表述为求解函数的极小值问题,即:其中: x称为优化变量,f称为目标函数。极大值问题可以转换成极小值问题来求解,只需要将目标函数加上负号即可:有些时候会对优化变量x有约束,包括等式约束和不等式约束,它们定义了优化变量的可行域,即满足约束条件的点构成的集合。这里我们先不考虑带约束条件的问题。一个优化问题的全局极小值是指对于可行域里所有的 x有:,即全局极小值点处的函数值不大于任意一点处的函数值。局部极小值定义为存在一个邻域,对于在邻域内:并且在可行域内的所有 x,有:.此时我们的目标是找到全局极小值。有些函数可能有多个局部极小值点,因此即使找到了导数等于0 的所有点,还需要比较这些点处的函数值。导数与梯度梯度是导数对多元函数的推广,它是多元函数对各个自变量偏导数形成的向量。多元函数的梯度定义为: ∇被称为梯度算子,作用于多元函数,得到一个向量。需要注意的是:梯度为0 只是函数取极值的必要条件而不是充分条件,即梯度为0 的点可能不是极值点。至于是极大值还是极小值,要看二阶导数(Hessian 矩阵),这是由函数的二阶偏导数构成的矩阵。这分为下面几种情况:如果Hessian 矩阵正定,函数有极小值;如果Hessian 矩阵负定,函数有极大值;如果Hessian 矩阵不定,则需要进一步讨论;这和一元函数的结果类似,Hessian 矩阵可以看做是一元函数的二阶导数对多元函数的推广。一元函数的极值判别法为,假设在某点处导数等于0,则:如果二阶导数大于0,函数有极小值;如果二阶导数小于0,函数有极大值;如果二阶导数等于0,情况不定;推导过程首先我们来看一元函数的泰勒展开,以便于更好的理解多元函数的泰勒展开。如果一个一元函数n阶可导,它的泰勒展开公式为: 如果在某一点处导数值大于0(+),则函数在此处是增函数,加大x的值(+)函数值会增加,减小 x的值(-)函数会减小。相反的,如果在某一点处导数值小于0(-),则函数是减函数,增加x的值(+)函数值会减小,减小x 的值(-)函数会增加。因此我们可以得出一个结论:如果x的变化很小,并且变化值与导数值反号,则函数值下降。对于一元函数,x的变化只有两个方向,要么朝左,要么朝右。面我们把这一结论推广到多元函数的情况。多元函数f(x)在x点处的泰勒展开为: 注意此处忽略了二次及更高的项。其中:一次项是梯度向量与自变量增量的内积,等价于一元函数的.函数的增量与自变量的增量,函数梯度的关系可以表示为: 如果足够小,在x的某一邻域内,则我们可以忽略二次及以上的项,有: 如果保证:即函数值递减. 因为向量的模一定大于等于0,如果:,即选择合适的增量,就能保证函数值下降,要达到这一目的,只要保证梯度和的夹角的余弦值小于等于0 就可以了。因为,因此当向量的模大小一定时,,即在梯度相反的方向函数值下降的最快。函数的下降值为:只要梯度不为 0,往梯度的反方向走函数值一定是下降的。从初始点开始,使用如下迭代公式: 只要没有到达梯度为 0 的点,则函数值会沿着序列递减,最终会收敛到梯度为 0 的点,这就是梯度下降法。迭代终止的条件是函数的梯度值为 0(实际实现时是接近于 0),此时认为已经达到极值点。注意我们找到的是梯度为 0 的点,这不一定就是极值点。梯度下降法只需要计算函数在某些点处的梯度,实现简单,计算量小。学习率设置为多少,也是实现时需要考虑的问题。最简单的,我们可以将学习率设置为一个很小的正数,如 0.001。另外,可以采用更复杂的策略,在迭代的过程中动态的调整学习率的值。比如前 1 万次迭代为0.001,接下来1 万次迭代时设置为 0.0001。