https://www.mindspore.cn/tutorials/zh-CN/stable/beginner/quick_start.html

一、MindSpore框架初识:背景、设计理念与核心优势

当我们谈论人工智能框架的时候,TensorFlow、PyTorch早已为人熟知,但在国产AI框架崛起的浪潮中,华为推出的昇思MindSpore正凭借其独特的设计理念,成为越来越多开发者入门AI开发的新选择。作为零基础入门AI开发的学习者,选择一款上手容易、功能完善且适配国内开发环境的框架,能帮我们少走很多弯路。本文我们就从基础认知开始,一步步带你用MindSpore完成手写数字识别项目。

1.1 MindSpore的诞生背景

MindSpore是华为在2020年正式开源的全场景AI计算框架,全称是“昇思MindSpore”,名称中的“昇思”寓意着“启发智能”,它的诞生和华为在人工智能、芯片领域的长期布局密不可分:一方面华为自研了昇腾AI系列芯片,需要一款深度适配芯片性能、充分发挥硬件算力的AI框架;另一方面,国产AI框架的发展也能帮助国内开发者打破海外框架的生态壁垒,降低AI开发门槛,推动人工智能技术在各个行业的落地。

经过多年迭代,如今MindSpore已经发展到2.x版本,覆盖了从训练到推理、从端侧(手机、嵌入式设备)到云侧(数据中心服务器)的全场景开发需求,在自动微分、动态图执行、大模型开发等领域都有突出的优势,同时对中文开发者提供了非常友好的文档和社区支持,非常适合零基础学习者入门。

MindSpore遵循Apache 2.0开源协议,完全免费开源,任何个人和企业都可以免费使用甚至商用,没有任何版权风险。

1.2 核心设计理念:AI开发为什么更简单?

MindSpore最核心的设计理念可以概括为三点:全场景协同、自动微分、原生支持动态图,这三点设计其实都是围绕着“降低开发门槛,提升开发效率”来做的:

全场景统一架构:MindSpore实现了一套框架可以同时支持云、边、端不同硬件环境的开发和部署。我们在电脑上开发训练好的模型,不需要大规模修改代码,就可以直接部署到手机、昇腾开发板这些端侧设备上运行,大大降低了跨场景部署的难度。

自动微分:深度学习模型的训练本质就是“反向传播求梯度更新参数”,手动求导对于复杂模型几乎不可能,早期框架需要开发者手动推导梯度,非常繁琐。MindSpore实现了业界领先的自动微分机制,不管模型多复杂,框架可以自动帮你计算梯度,开发者只需要定义好前向计算的网络结构,不需要关心反向传播怎么实现。

动静态图结合:动态图方便调试,代码运行结果可以立即看到,非常适合开发调试;静态图执行效率更高,适合训练完成后的部署推理。MindSpore原生支持动态图默认执行,开发调试的时候像写普通Python代码一样逐行运行调试,需要提升性能的时候只需要加一行装饰器代码就能转换成静态图执行,不需要大规模修改代码,兼顾了开发便利性和运行性能。

1.3 MindSpore的核心技术特点

对比其他框架,MindSpore对初学者友好的技术特点主要有这些:

语法贴近原生Python:MindSpore的API设计非常贴近Python原生语法习惯,如果你已经会Python基础,学习MindSpore的基础语法几乎没有额外的学习成本,不需要适应太多奇怪的框架特殊写法。

自动并行能力:如果你后续接触更大规模的模型训练,MindSpore提供了原生的自动并行能力,只需要简单配置就能利用多卡多设备进行分布式训练,不需要开发者自己写大量分布式并行相关的代码。

完善的预置能力:MindSpore内置了大量常用的数据集、预训练模型、数据增强算子,常见的CV(计算机视觉)、NLP(自然语言处理)任务都可以直接调用预置组件快速实现,不需要从零造轮子。

昇腾芯片深度优化:如果你用华为昇腾芯片训练推理,MindSpore可以充分发挥昇腾芯片的算力性能,比其他框架能获得更好的运行效率。就算你用普通的CPU或者NVIDIA GPU,MindSpore也能完美支持,开发阶段用普通电脑也能学习运行入门项目。

活跃的中文社区:官方提供了非常详细的中文文档和大量入门教程,遇到问题在社区可以很方便找到中文解决方案,对国内零基础学习者非常友好。

二、从零开始:MindSpore环境安装与基础概念

在写项目代码之前,我们先把环境安装好,再梳理清楚MindSpore的核心基础概念,为后续项目开发打好基础。本文的代码都基于MindSpore 2.2版本,你只要会用Python的pip工具,就可以完成安装。

2.1 环境安装步骤

MindSpore支持Windows、Linux、MacOS操作系统,支持CPU、GPU、昇腾NPU不同硬件环境,这里我们分不同情况给大家说明安装步骤:

前置要求:你的电脑已经安装好Python 3.7~3.11版本(MindSpore 2.x目前支持这几个版本,最新版本的兼容性可以查看官方文档),并且已经配置好pip环境。

情况1:安装CPU版本(适合入门学习,无GPU也能用)

如果你只是入门学习,没有NVIDIA GPU或者昇腾NPU,直接安装CPU版本就可以运行我们的手写数字识别项目,只是训练速度会慢一点,完全不影响学习。

打开命令行终端,直接执行pip安装命令:

pip install mindspore -i https://pypi.tuna.tsinghua.edu.cn/simple

国内用户加上清华源的镜像地址可以大大提升下载速度。

情况2:安装NVIDIA GPU版本

如果你电脑有NVIDIA显卡,并且已经安装好对应版本的CUDA和cuDNN,可以安装GPU版本获得更快的训练速度:

CUDA 11.1/11.6版本:

pip install mindspore-gpu -i https://pypi.tuna.tsinghua.edu.cn/simple

安装完成之后我们可以验证一下是否安装成功,打开Python交互环境,执行下面的代码:

import mindspore print(mindspore.version)

如果能正常输出版本号,说明安装成功了。如果提示找不到模块,检查一下你的Python环境和pip是不是对应,重新安装即可。

2.2 核心基础概念梳理

在开始写代码之前,我们先把MindSpore里最常用的几个核心概念说清楚,避免大家学习的时候混淆:

1. 张量(Tensor)

张量是MindSpore中最基础的数据结构,不管是输入数据、模型参数,中间计算结果都是用张量来存储的。你可以把张量简单理解为“多维数组”:0维张量就是一个单独的数字(标量),1维张量就是Python里的列表(一维数组),2维张量就是矩阵,以此类推,N维就是N维数组。

MindSpore的张量和NumPy数组非常像,可以很方便的互相转换,支持各种数学运算,同时它会自动适配不同的硬件环境,帮你管理内存/显存,不需要开发者手动处理。

创建张量非常简单:

import mindspore from mindspore import Tensor import numpy as np

从Python列表创建张量

a = Tensor([1, 2, 3])

从NumPy数组创建张量

b = Tensor(np.array([[1, 2], [3, 4]]), dtype=mindspore.float32) # 指定数据类型

2. 数据类型(dtype)

和Python一样,张量也有不同的数据类型,常用的比如mindspore.int32(32位整数)、mindspore.float32(32位浮点数,深度学习最常用)、mindspore.bool\_(布尔类型),创建张量的时候可以指定,不指定会自动根据输入推断。

3. 模块(Cell)

在MindSpore里,所有的神经网络模型、网络层都是继承自nn.Cell类,Cell是MindSpore对神经网络组件的抽象封装。我们搭建模型的时候,就是把一个个小的Cell(比如卷积层、激活层、全连接层)组装成一个更大的Cell,也就是我们最终的完整模型。

举个最简单的例子,一个两层的全连接网络就是:

from mindspore import nn class MyNet(nn.Cell): def init(self): super().init() # 必须调用父类的初始化方法 self.fc1 = nn.Dense(784, 256) # 第一层全连接,输入784维,输出256维 self.relu = nn.ReLU() # ReLU激活函数 self.fc2 = nn.Dense(256, 10) # 第二层全连接,输出10类 def construct(self, x): # 必须实现construct方法,这是前向传播的计算逻辑 x = self.fc1(x) x = self.relu(x) x = self.fc2(x) return x

这个就是MindSpore定义模型的标准写法:继承nn.Cell,在__init__里面定义我们用到的所有网络层组件,然后在construct方法里面定义前向计算的流程,输入是x,一步步计算得到最终输出,返回即可。

这里要注意,很多初学者会把construct写成__call__,其实不用,Cell已经帮我们做好了封装,我们只要实现construct就可以了,这个是MindSpore的约定。

4. 损失函数(Loss Function)和优化器(Optimizer)

损失函数用来衡量我们模型预测结果和真实标签之间的差距,损失越小说明模型预测越准。优化器的作用就是根据损失函数计算出来的梯度,更新模型的参数,让损失不断变小,这个过程就是我们说的“模型训练”。

MindSpore把损失函数放在mindspore.nn模块里,优化器放在mindspore.nn.optim模块里,分类任务常用交叉熵损失,优化器常用的比如SGD、Adam,我们后面项目里会用到。

5. 自动微分与梯度计算

前面我们说过MindSpore的自动微分很强大,我们只要定义好前向计算,框架自动帮我们计算梯度。MindSpore提供了value_and_grad函数,可以自动帮我们生成计算损失和梯度的函数,非常方便。

简单来说,训练的流程就是:

输入数据,前向计算得到模型预测

计算损失(预测和真实标签的误差)

自动计算损失对模型所有参数的梯度

优化器根据梯度更新模型参数

重复这个过程,直到损失足够小

MindSpore已经把这些流程都做了很好的封装,我们只需要配置好,框架自动帮我们完成,我们只需要关注模型结构本身就可以了。

2.3 常用基础语法演示

我们先来看几个最常用的操作,让大家感受一下MindSpore的语法有多简洁:

张量运算,和NumPy几乎一样:

import mindspore from mindspore import Tensor

a = Tensor([1, 2, 3], mindspore.float32) b = Tensor([4, 5, 6], mindspore.float32) print(a + b) # 输出 [5. 7. 9.] print(a * b) # 输出 [4. 10. 18.] print(a.shape) # 输出 (3,) 查看张量形状

模型调用:我们定义好模型之后,直接就可以像调用普通函数一样调用:

net = MyNet() input_x = Tensor(np.random.randn(1, 784), mindspore.float32) # 1张输入,784维 output = net(input_x) # 直接调用模型得到输出 print(output.shape) # 输出 (1, 10),10个类别的预测概率

转换成静态图提升性能:如果我们想把动态图转换成静态图提升运行速度,只需要加一个@jit装饰器:

from mindspore import jit

@jit def forward(x): return net(x)

output = forward(input_x) # 这个就是静态图执行,速度更快

就是这么简单,完全不需要修改代码逻辑,对初学者非常友好。

三、项目实战:手写数字识别完整实现

讲完基础概念,我们正式进入项目实战。手写数字识别是AI入门的“Hello World”项目,任务目标是:给一张28×28像素的手写数字图片(0~9),我们训练一个模型,让模型能识别出这张图片写的是哪个数字。我们一步步拆解实现,每一步都给你带详细注释的代码和讲解。

3.1 项目介绍与数据集说明

我们用到的数据集是MNIST手写数字数据集,这是机器学习领域最经典的入门数据集,它包含了60000张训练图片和10000张测试图片,所有图片都是归一化处理过的28×28像素的灰度图,每个像素的取值范围是0~1(0代表背景黑色,1代表前景白色),每个图片对应一个0~9的数字标签。

MindSpore已经把MNIST数据集内置到了mindspore.dataset模块里,我们不需要自己手动下载解压,一行代码就能自动下载加载数据集,非常方便。

3.2 环境导入与全局配置

我们先把项目用到的所有模块导入,然后做一些基础配置:

导入需要用到的模块

import numpy as np import matplotlib.pyplot as plt # 用来可视化图片,看数据效果

import mindspore from mindspore import Dataset, nn, Tensor, context from mindspore.dataset import vision, transforms # 数据预处理工具 from mindspore.train import Model, CheckpointConfig, ModelCheckpoint, LossMonitor # 训练工具

配置运行环境,这里我们用动态图模式,CPU运行,如果用GPU改成device_target="GPU"即可

context.set_context(mode=context.GRAPH_MODE, device_target="CPU")

这里mode也可以设置成context.PYNATIVE_MODE是动态图模式,GRAPH_MODE是静态图,静态图性能更好,入门推荐用静态图就行

代码说明:

context.set_context用来配置全局运行环境,mode指定运行模式,device_target指定我们用什么硬件,CPU/GPU/Ascend(昇腾NPU)三个选项,根据你自己的环境修改即可,我们入门用CPU完全没问题。

我们这里直接用MindSpore提供的Model高阶API来做训练,它已经把训练循环、日志打印这些都封装好了,我们不需要自己写循环,非常简洁。

3.3 数据加载与预处理

接下来我们加载MNIST数据集,并且做必要的预处理。深度学习训练一般是分批(batch)输入数据,我们这里设置每一批(batch size)输入32张图片做训练。

下载并加载MNIST数据集,MindSpore会自动下载到当前目录,不需要手动操作

from mindspore.dataset import MnistDataset

分别加载训练集和测试集,参数是数据集存放的路径

train_dataset = MnistDataset("./mnist", usage="train") # usage="train"代表训练集 test_dataset = MnistDataset("./mnist", usage="test") # usage="test"代表测试集

定义数据预处理流程

MNIST原始图片是28×28的灰度图,像素范围0~255,我们需要转换成模型需要的格式

transformer = transforms.Compose([ vision.Rescale(1.0 / 255.0, 0), # 将像素值从0~255缩放到0~1之间,方便模型训练 vision.HWC2CHW(), # 转换图片维度格式:原始是(高,宽,通道)转换成(通道,高,宽),MindSpore默认通道在前的格式 transforms.TypeCast(mindspore.float32) # 把数据转换成float32类型 ])

对数据集应用预处理,然后分批打包

处理训练集

train_dataset = train_dataset.map(operations=transformer, input_columns=["image"]) train_dataset = train_dataset.batch(batch_size=32, drop_remainder=True) # 每32张一个batch,最后不够一个batch的丢掉

处理测试集

test_dataset = test_dataset.map(operations=transformer, input_columns=["image"]) test_dataset = test_dataset.batch(batch_size=32, drop_remainder=False) # 测试集不需要丢最后一个batch

我们来解释一下这里容易混淆的点:

为什么要做Rescale?因为原始图片每个像素是0~255的整数,神经网络训练用0~1范围的数据更容易收敛,所以做归一化缩放。

为什么要做HWC2CHW?不同框架对图片维度的格式约定不一样,OpenCV和PIL默认是HWC(高度、宽度、通道数),MindSpore做卷积运算默认是CHW(通道数、高度、宽度),所以这里要转一下格式,不然会报错。

input_columns=["image"]:因为MNIST数据集里每个样本包含两个字段,一个是image(图片数据),一个是label(标签),我们的预处理只需要对图片做处理,所以指定只处理image字段。

我们可以可视化一张图片看看数据集加载对不对:

取出一个batch的数据,看第一张图片

for batch in train_dataset.create_tuple_iterator(): images, labels = batch print("图片batch形状:", images.shape) # 应该是 (32, 1, 28, 28) 32张,1个灰度通道,28×28大小 print("第一张标签:", labels[0]) # 把图片转成numpy,调整维度用来显示 img = images[0].asnumpy().squeeze() # 去掉通道维度,变成28×28 plt.imshow(img, cmap="gray") plt.title("label: {}".format(labels[0].asnumpy())) plt.show() break

运行之后可以看到图片和对应的标签,说明我们数据加载预处理没有问题。

3.4 模型搭建

我们这里做手写数字识别,不需要太复杂的模型,用一个简单的卷积神经网络就可以达到非常高的准确率,卷积神经网络是目前处理图像任务最常用的结构,我们来一步步定义模型:

class MnistNet(nn.Cell): def init(self, num_classes=10): """ 初始化模型结构 num_classes: 分类类别数量,我们是0~9十个数字,所以是10类 """ super(MnistNet, self).init() # 定义网络层:两个卷积层 + 两个池化层 + 两个全连接层 # 卷积层:输入通道1(灰度图只有一个通道),输出通道16,卷积核大小5×5 self.conv1 = nn.Conv2d(1, 16, kernel_size=5, stride=1, padding=0) # 池化层:池化窗口2×2,步长2 self.max_pool1 = nn.MaxPool2d(kernel_size=2, stride=2) # 第二个卷积层:输入通道16,输出通道32,卷积核5×5 self.conv2 = nn.Conv2d(16, 32, kernel_size=5, stride=1, padding=0) self.max_pool2 = nn.MaxPool2d(kernel_size=2, stride=2) # ReLU激活函数,给网络增加非线性能力,没有激活函数网络只能做线性变换,表达能力不够 self.relu = nn.ReLU() # 全连接层,把卷积提取的特征映射到10个输出类别,这里计算一下输入维度:原始28×28,经过两次卷积池化之后是4×4×32=512 self.fc1 = nn.Dense(4432, 120) self.fc2 = nn.Dense(120, num_classes) # 最后输出10类

实例化我们的模型

net = MnistNet(num_classes=10)

这个模型虽然简单,但是该有的结构都有,我们来梳理一下容易让初学者混淆的点:

卷积层nn.Conv2d参数含义:第一个参数是输入通道数,第二个是输出通道数,kernel_size是卷积核大小,stride是卷积步长,padding是边缘填充大小。我们这里没有加填充,所以边缘会被卷积核切掉一点,不影响结果。

维度计算:我们这里计算出来两次卷积池化之后是4×4×32,怎么来的?给大家一个公式:输出尺寸 = (输入尺寸 - 卷积核尺寸 + 2*填充)/步长 + 1。第一次输入28,卷积核5,填充0,步长1:(28-5 + 0)/1 + 1 = 24,然后池化核2,步长2:24/2=12,所以是12×16。第二次输入12,同样计算得到(12-5)/1+1=8,池化之后8/2=4,所以是4×4×32,没错。

为什么要用ReLU激活函数?如果没有激活函数,不管你网络有多少层,整个网络其实本质还是一个线性变换,表达能力非常有限,加了非线性激活函数之后,网络才能拟合复杂的非线性关系,所以激活函数是必须的。

我们最后一层为什么不接softmax?因为我们用的交叉熵损失函数SoftmaxCrossEntropyWithLogits已经帮我们内置了softmax计算,所以我们最后一层直接输出logits就可以了,不需要重复计算,这样更稳定。

3.5 训练配置:损失函数、优化器、评估指标

定义好模型之后,我们需要配置训练需要的损失函数、优化器,还有我们评估模型用的准确率指标:

定义损失函数:多分类交叉熵损失,我们这里是稀疏标签(每个样本只有一个整数标签,不是one-hot),所以用sparse设置为True

loss_fn = nn.SoftmaxCrossEntropyWithLogits(sparse=True, reduction='mean')

reduction='mean'代表对一个batch里所有样本的损失求平均,这样损失不会因为batch大小变化

定义优化器:Adam优化器,是目前最常用的优化器,收敛稳定,学习率我们设置为0.001,把模型的所有参数传给优化器

optimizer = nn.Adam(net.trainable_params(), learning_rate=0.001)

net.trainableParams()可以拿到模型所有需要训练的参数,优化器就是更新这些参数

定义评估指标:我们用准确率(Accuracy)来评估,准确率就是预测正确的样本数除以总样本数,越高越好

metrics = {"accuracy": nn.Accuracy()}

用MindSpore的Model高阶API封装模型,把我们定义好的网络、损失函数、优化器、评估指标传进去

model = Model(network=net, loss_fn=loss_fn, optimizer=optimizer, metrics=metrics)

这里给大家解释一下:什么是稀疏标签?我们的MNIST标签是每个样本一个0~9的整数,比如标签就是5代表这个图片是5,而不是[0,0,0,0,0,1,0,0,0,0]这样的one-hot编码,所以叫稀疏标签,我们把sparse设置成True,损失函数就可以直接处理这种整数标签,不需要我们自己转成one-hot,非常方便。

3.6 模型训练

配置好了之后,我们就可以开始训练了。MindSpore的Model API提供了model.fit方法,直接传入训练集和测试集,还有回调工具用来保存模型 checkpoint 和打印日志,非常方便:

配置 checkpoint 保存:每训练1个epoch保存一次,最多保留5个checkpoint

config_ckpt = CheckpointConfig(save_checkpoint_steps=len(train_dataset), keep_checkpoint_max=5)

len(train_dataset)就是一个epoch有多少个step,所以每一个epoch保存一次

ckpt_cb = ModelCheckpoint(prefix="mnist_net", directory="./checkpoint", config=config_ckpt)

LossMonitor用来打印训练过程中的损失,每100个step打印一次损失

loss_cb = LossMonitor(per_print_times=100)

开始训练,训练5个epoch,也就是把整个训练数据集过5遍,足够MNIST数据集收敛了

我们同时指定验证集,每个epoch训练完成之后,会在验证集上评估准确率,方便我们看效果

model.fit(epoch=5, train_dataset=train_dataset, valid_dataset=test_dataset, callbacks=[ckpt_cb, loss_cb])

我们来解释一下什么是epoch:一个epoch就是把整个训练数据集完整过一遍,我们这里训练集总共有60000张图片,batch size是32,所以一个epoch就是60000/32 = 1875个step,我们每100个step打印一次损失,你会看到损失不断下降,每个epoch训练完成之后会输出在测试集上的准确率。

正常训练下来,5个epoch之后准确率应该能达到98%以上,效果非常好。如果你的电脑比较慢,训练一个epoch大概几分钟,CPU也完全可以跑下来,因为MNIST数据集和模型都很小。

训练过程输出大概是这样:

epoch: 1 step: 100, loss is 0.456 epoch: 1 step: 200, loss is 0.123 ... Eval result: epoch 1, metric: {'accuracy': 0.9752} ... Eval result: epoch 5, metric: {'accuracy': 0.986}

这个就是正常的训练结果,说明我们模型训练好了,准确率接近99%,非常优秀。

3.7 模型测试与结果验证

训练完成之后,我们可以单独对测试集做一次完整的评估,看看最终的准确率:

在测试集上评估模型,输出最终准确率

eval_result = model.eval(test_dataset) print("测试集最终评估结果:", eval_result)

运行之后就能输出最终准确率,比如我这里训练得到的结果是{'accuracy': 0.9878},也就是98.78%的准确率,100张图片里只有不到两张预测错误,效果非常好,对于入门项目来说完全足够了。

3.8 单张图片推理演示

模型训练好了,我们可以拿一张图片来测试,看看模型预测对不对。我们从测试集里随机拿几张图片,做推理然后可视化结果:

加载我们训练好的模型参数,如果需要重新加载可以用这个代码,这里如果是刚刚训练完,可以不用重新加载,net已经是训练好的了

from mindspore import load_checkpoint, load_param_into_net

param_dict = load_checkpoint("./checkpoint/mnist_net-5_1875.ckpt")

load_param_into_net(net, param_dict)

将模型设置为评估模式,这个一定要做,因为dropout、batch norm这些层训练和推理模式行为不一样,我们推理一定要改成评估模式

net.set_train(False)

从测试集里随机拿5张图片做推理

for i, batch in enumerate(test_dataset.create_tuple_iterator()): images, labels = batch # 模型推理,得到预测结果 logits = net(images) # logits是每个类别的得分,我们取得分最高的就是预测类别 pred = mindspore.argmax(logits, axis=1) # 按最后一维取最大值的索引,就是预测类别 # 可视化前5张 if i >= 1: break for j in range(min(5, len(images))): img = images[j].asnumpy().squeeze() plt.figure() plt.imshow(img, cmap="gray") plt.title(f"真实标签: {labels[j].asnumpy()}, 预测结果: {pred[j].asnumpy()}") plt.show()

运行之后你会看到,几乎所有的图片模型都能预测正确,只有极少数写得特别潦草的会预测错,比如你会看到类似这样的输出:真实标签是5,预测结果也是5,和真实结果一致。

四、项目总结与进阶方向

我们来回顾一下整个项目流程,我们从认识MindSpore框架开始,完成了环境安装,梳理了核心基础概念,然后一步步实现了数据加载预处理、模型搭建、训练配置、模型训练、推理测试整个流程,最终得到了一个准确率接近99%的手写数字识别模型,整个过程代码非常简洁,MindSpore帮我们封装了很多复杂的底层细节,让我们可以专注于模型和业务逻辑。

4.1 常见问题与解决方法

我们整理了初学者做这个项目最常遇到的几个问题,给大家说一下解决方法:

导入MnistDataset报错,找不到数据集:如果自动下载失败,你可以手动去MNIST官网下载四个压缩包,放到./mnist目录下,MindSpore会自动读取,不需要解压。四个文件名称是:train-images-idx3-ubyte.gztrain-labels-idx1-ubyte.gzt10k-images-idx3-ubyte.gzt10k-labels-idx1-ubyte.gz

维度不匹配错误:一般是图片维度没有转成CHW格式,检查一下你的预处理有没有加HWC2CHW(),还有检查模型输入维度对不对。

训练速度很慢:如果是CPU的话,本来就会慢一点,MNIST这个模型小,等几分钟就好了,如果有GPU安装GPU版本会快很多。

准确率很低:检查一下你的学习率是不是设置太大,还有训练epoch是不是不够,一般5个epoch足够了,如果不行可以改成10个epoch,学习率改成0.001,一般都能上来。

4.2 后续进阶学习方向

做完这个入门项目之后,你如果想继续深入学习MindSpore,可以从这些方向入手:

尝试更复杂的数据集和模型:比如用CIFAR10数据集做10分类,尝试ResNet等经典卷积网络结构,感受一下不同模型的效果。

学习动态图调试:MindSpore默认动态图调试非常方便,你可以试着自己写训练循环,不使用Model高阶API,理解梯度计算和参数更新的整个过程。

尝试端侧部署:MindSpore支持把训练好的模型转换成MindSpore Lite格式,部署到手机或者开发板上运行,体验一下全场景开发的流程。

学习大模型开发:MindSpore现在对大模型支持非常好,有很多预置的大模型权重,可以试着体验一下微调大模型的流程。

五、结语

作为一款国产开源AI框架,MindSpore确实做到了对初学者非常友好,语法简洁,文档完善,社区活跃,非常适合作为入门AI开发的第一个框架。本文我们从基础认知到项目实战,完整走了一遍入门流程,相信你跟着代码一步步跑下来,已经对MindSpore有了基本的认识,也完成了你的第一个AI项目。

AI开发其实没有那么难,只要动手跑通第一个项目,你就入门了,后续不断做更多项目,学习更深入的知识,慢慢就能掌握更复杂的AI开发技能。如果在学习过程中遇到问题,可以去MindSpore官方论坛或者Gitee仓库提issue,社区里有很多开发者会帮你解决问题。

本文完整代码已经可以直接运行,你只需要按照步骤安装环境,一步步执行就可以得到结果,赶紧动手试试吧!

Logo

昇腾计算产业是基于昇腾系列(HUAWEI Ascend)处理器和基础软件构建的全栈 AI计算基础设施、行业应用及服务,https://devpress.csdn.net/organization/setting/general/146749包括昇腾系列处理器、系列硬件、CANN、AI计算框架、应用使能、开发工具链、管理运维工具、行业应用及服务等全产业链

更多推荐