手写体数字识别讲解

这个 notebook 的完整流程是:准备环境 → 载入 MNIST 数据 → 数据预处理(缩放/归一化/转置/分批)→ 构建网络(nn.Cell)→ 定义损失与优化器 → 用 value_and_grad 计算梯度并训练 → 每轮评估 → 保存/加载模型 → 推理预测。核心框架是 MindSpore(类似 PyTorch/TensorFlow 的深度学习库)。官方安装与 API 说明请参考 MindSpore 官网安装与 transform 文档。(昇思MindSpore)


详细逐步解析(按 notebook 的 cell 顺序)

Cell 2 — import ...

1
2
3
4
5
import mindspore
import numpy as np
from mindspore import nn
from mindspore.dataset import vision, transforms
from mindspore.dataset import MnistDataset

作用:引入 MindSpore 主包、神经网络模块 nn、数据变换 visiontransforms,以及 MNIST 数据读取器。
知识点:Python 包导入、MindSpore 模块划分(模型层/数据处理/训练工具)。

Cell 3 — 载入数据

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

作用:把硬盘上的 MNIST 数据封装为 MindSpore 的 dataset 对象。注意 MnistDataset 会生成两列 ['image','label'],image 初始是 uint8 类型。目录结构要按官方示例准备(README/quickstart 文档里有范例)。(昇思MindSpore)

Cell 4 — datapipe():数据预处理流水线

1
2
3
4
5
6
7
8
9
10
11
12
def datapipe(dataset,batch_size):
image_transforms = [
vision.Rescale(1.0 / 255.0, 0),
vision.Normalize(mean=(0.1307,), std=(0.3081,)),
vision.HWC2CHW()
]
label_transform = transforms.TypeCast(mindspore.int32)

dataset = dataset.map(image_transforms, 'image')
dataset = dataset.map(label_transform, 'label')
dataset = dataset.batch(batch_size)
return dataset

解释:

  • Rescale(1.0/255.0, 0):把像素从 [0,255] 缩放到 [0,1]output = image * rescale + shift)。如果你遇到“Rescale 参数缺失”的错误,通常是因为没有传入两个参数(scale, shift)。(昇思MindSpore)
  • Normalize(mean, std):按均值和标准差做归一化(这里是 MNIST 常用值)。
  • HWC2CHW():把形状从 [H,W,C] 变为 [C,H,W](框架对通道维度的期待)。
  • TypeCast(int32):把 label 转为 int32(损失函数/指标通常要求整型标签)。
    知识点:数据管线(map、batch)、图像标准化、通道维度约定。官方有示例说明数据流(map → batch → shuffle),强烈建议读官方 transforms / dataset 教程。(昇思MindSpore)

Cell 5 — 应用 datapipe

1
2
train_dataset = datapipe(train_dataset,64)
test_dataset = datapipe(test_dataset,64)

说明:把数据包装为按 batch 输出(每个 batch 的 image tensor 形状一般是 [B, C, H, W])。

Cell 6/7 — 调试打印 shape

示例里用 create_tuple_iterator()create_dict_iterator() 打印 shape/dtype,用来确认数据输出的维度与类型是否符合模型输入要求。
知识点:如何用迭代器取一批数据、asnumpy()/.shape 查看具体数据。

Cell 9 — 网络结构 NetWork(nn.Cell)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class NetWork(nn.Cell):
def __init__(self):
super().__init__()
self.flatten = nn.Flatten()
self.dense_relu_sequential = nn.SequentialCell(
nn.Dense(28*28,512),
nn.ReLU(),
nn.Dense(512,512),
nn.ReLU(),
nn.Dense(512,10),
)
def construct(self, x):
x= self.flatten(x)
logits = self.dense_relu_sequential(x)
return logits

说明:

  • 这是一个最简单的全连接(MLP)分类器:先把图片 flatten(28*28=784),经过两层隐藏层,最后输出 10 个 logits(对应 10 个数字类)。
    知识点:nn.Cell 是 MindSpore 的网络基类,construct 相当于 PyTorch 的 forwardnn.SequentialCell 是层的容器。

Cell 11 — 损失、优化器与 value_and_grad

1
2
3
4
5
6
7
8
9
loss_fn = nn.CrossEntropyLoss()
optimizer = nn.SGD(model.trainable_params(), 0.01)

def forward_fn(data, label):
logits = model(data)
loss = loss_fn(logits, label)
return loss, logits

grad_fn = mindspore.value_and_grad(forward_fn, None, optimizer.parameters, has_aux=True)

解释:

  • CrossEntropyLoss:常用分类损失(softmax + 交叉熵)。
  • optimizer = nn.SGD(...):构造优化器(传入模型参数与学习率)。在 MindSpore 中,优化器可以像一个可调用对象,用来把梯度应用到参数上(例子里后面直接 optimizer(grads))。
  • mindspore.value_and_grad(...):这是一个方便的工具,一次性计算(loss, aux outputs)和梯度has_aux=True 表示前向函数返回 (loss, aux) 这种格式,返回的梯度函数会把 (loss, aux)grads 打包好返回。更详细说明见官方文档。(昇思MindSpore)

Cell 11(后半)— 训练步骤和循环

  • train_step:调用 grad_fn(data,label) 得到 (loss, aux), grads,然后调用 optimizer(grads) 更新参数。
  • train 函数:对每个 batch 调用 train_step,并按固定频率打印 loss。
    知识点:反向传播、梯度更新、batch 概念。

Cell 12 — test(评估)

  • model.set_train(False)(推理模式)下,对测试集逐 batch 计算 loss 和正确数,最终汇报平均 loss 与准确率(accuracy)。

Cell 13 — 训练主循环

1
2
3
4
epochs = 10
for t in range(epochs):
train(model, train_dataset)
test(model, test_dataset, loss_fn)

说明:按 epoch 进行训练和评估。

Cell 15/17 — 保存/加载模型

  • mindspore.save_checkpoint(model, "model.ckpt") 保存参数。
  • param_dict = mindspore.load_checkpoint("model.ckpt") + mindspore.load_param_into_net(...) 用于加载模型参数,并打印未匹配的参数(方便检查模型结构是否变动)。

Cell 18 — 简单推理示例

对测试数据做一次前向预测并打印前 10 个预测与真实标签对比。


关键知识点(你需要理解的概念——小白必读)

  1. 数据形状(shape)与通道顺序:MNIST 单张图片原始为 [28,28,1](H,W,C),训练时通常为 [B, C, H, W]HWC2CHW 就是做这一步转换。
  2. 归一化 / 标准化Rescale 把像素缩放到 [0,1];Normalize 用特定均值/方差进一步标准化。正确的顺序和参数很重要(见 transforms 文档)。(昇思MindSpore)
  3. 模型(nn.Cell)与前向/反向construct 是前向函数,梯度由 value_and_grad 或者 grad API 计算并由 optimizer 应用。(昇思MindSpore)
  4. 训练循环:每个 batch 做前向→计算 loss→反向→更新参数,周期性评估。
  5. 上下文(device / mode):训练前通常需要设置运行环境(CPU/GPU/Graph 或 PyNative 模式),用 mindspore.set_context(...) 设置。若没设置,可能导致框架选择默认设备或发生不兼容错误(例如把 GPU 版本误当成 Ascend)。(昇思MindSpore)

常见错误 & 排查建议(你碰到的问题大概率是其中之一)

  • Rescale 参数缺失:确保 vision.Rescale(1.0/255.0, 0) 两个参数都传了(scale, shift)。(昇思MindSpore)
  • 数据路径错误 / 文件格式不对MnistDataset 期望特定目录结构,先确认 MNIST_Data/train 下是否有正确数据文件。可用 print(train_dataset.get_col_names()) 检查列名。(昇思MindSpore)
  • shape 不匹配(Dense 的输入维度):如果 Flatten 后维度不是 784,说明批量或通道处理有问题,打印 data.shape(或 data.asnumpy().shape)来确定。
  • 设备不匹配错误(Ascend/GPU/CPU):在脚本开始处 mindspore.set_context(device_target="CPU")"GPU" 指明目标设备,避免默认行为出错。(昇思MindSpore)

小白可执行的 10 步实操清单(照着做)

  1. 新建虚拟环境:

    1
    2
    3
    python -m venv venv
    source venv/bin/activate # Windows: venv\Scripts\activate
    pip install --upgrade pip
  2. 安装 MindSpore(强烈建议按官方安装页面选择对应 CPU/GPU/系统的 wheel):官方安装说明请看这里。(昇思MindSpore)

  3. 安装其他依赖:

    1
    pip install numpy jupyter matplotlib
  4. 确保 MNIST 数据放在 MNIST_Data/trainMNIST_Data/test(按官方示例的目录结构)。若没有数据,可到官网下载并解压。(昇思MindSpore)

  5. 在 notebook 第一个 cell(最上方)加入运行环境设置(可选但建议):

    1
    2
    import mindspore as ms
    ms.set_context(mode=ms.PYNATIVE_MODE, device_target="CPU")

    (如果你有 GPU,改成 "GPU"。)(昇思MindSpore)

  6. 按 cell 顺序逐个运行(避免跳过):先运行 imports → datapipe → model 定义 → loss/optimizer → train loop。

  7. 先把 epochs 设小(比如 1 或 2),batch_size 也可以设小(如 16),确认能跑通并输出 loss/accuracy。

  8. 如果出错误,优先打印:print(data.shape, data.dtype); print(label.shape, label.dtype),并检查看 dataset.get_col_names()

  9. 训练成功后运行 save_checkpoint,再新开一个 kernel 测试 load_checkpoint + load_param_into_net、推理代码。

  10. 逐步改进:把 MLP 换成简单的卷积网络(Conv2D→ReLU→Pool→FC),观察准确率提升;或者使用 MindSpore 的高阶 mindspore.train.Model 封装来简化训练流程(如果想要更“高层”的训练 API)。(昇思MindSpore)


推荐学习顺序(对小白)

  1. 学会 Python 基本操作与虚拟环境管理。
  2. 学会用 Jupyter 逐 cell 调试(按顺序运行)。
  3. 看懂数据 pipeline(map / batch / iterator / dtype / shape)。(昇思MindSpore)
  4. 学习神经网络基础:线性层、激活、损失函数(交叉熵)、优化器(SGD / Adam)。
  5. 进阶了解:gradient/backprop(value_and_grad 的工作机制)。(昇思MindSpore)