PJ1_nndl 是一个手写数字识别(OCR Recognition)模型集合,包含多种神经网络架构的训练权重,适用于 MNIST 数据集的手写数字分类任务。本仓库提供了多种优化器变体的 MLP(多层感知机)和 CNN(卷积神经网络)模型。
本仓库包含以下 6 个模型变体:
| 模型文件 | 架构 | 优化器 | 特殊配置 |
|---|---|---|---|
mlp_sgd.pickle | MLP [784, 600, 10] | SGD | - |
mlp_momentum.pickle | MLP [784, 600, 10] | SGD + Momentum | - |
mlp_momentum_multistep.pickle | MLP [784, 600, 10] | SGD + Momentum + Multistep | - |
mlp_sgd_multistep.pickle | MLP [784, 600, 10] | SGD + Multistep | - |
mlp_sgd_wd.pickle | MLP [784, 600, 10] | SGD + Weight Decay | weight_decay=True, lambda=0.0001 |
cnn_sgd.pickle | CNN | SGD | Conv(1->8,3x3)->Pool->Conv(8->16,3x3)->FC(3136->128)->FC(128->10) |
输入层: 784 (28x28 扁平化)
-> Linear(784, 600) + ReLU
-> Linear(600, 10) (输出层)
输出: 10 类 (数字 0-9)输入: (1, 28, 28)
-> Conv2D(1->8, 3x3, padding='same') + ReLU + MaxPool(2x2)
-> Conv2D(8->16, 3x3, padding='same') + ReLU
-> Flatten (-> 3136)
-> Linear(3136, 128) + ReLU
-> Linear(128, 10) (输出层)
输出: 10 类 (数字 0-9)该模型在华为 Ascend910 NPU 上进行了适配和测试。适配要点:
torch.mm + bias addtorch.nn.functional.conv2d,Pooling 使用 F.max_pool2dtorch.relu.npu() 方法迁移到昇腾设备。torch.npu.empty_cache() 释放显存。pip install -i https://pypi.tuna.tsinghua.edu.cn/simple torch torchvision numpy
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple torch_npu
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple modelscopefrom modelscope import snapshot_download
model_dir = snapshot_download('TimoZhou/PJ1_nndl')npu-smi info
python -c "import torch_npu; print(f'NPU count: {torch_npu.npu.device_count()}')"cd model1
python3 inference.py --model cnn_sgd --device cpu --num_samples 10cd model1
python3 inference.py --model cnn_sgd --device npu --num_samples 10--model: 模型名称,可选 mlp_sgd, mlp_momentum, mlp_momentum_multistep, mlp_sgd_multistep, mlp_sgd_wd, cnn_sgd--device: 推理设备,可选 cpu, npu--num_samples: 测试样本数| 样本 | 真实标签 | CPU 预测 | NPU 预测 | 结果 |
|---|---|---|---|---|
| 1 | 7 | 7 | 7 | ✓ |
| 2 | 2 | 2 | 2 | ✓ |
| 3 | 1 | 1 | 1 | ✓ |
| 4 | 0 | 0 | 0 | ✓ |
| 5 | 4 | 4 | 4 | ✓ |
| 6 | 1 | 1 | 1 | ✓ |
| 7 | 4 | 4 | 4 | ✓ |
| 8 | 9 | 9 | 9 | ✓ |
| 9 | 5 | 6 | 6 | ✗ |
| 10 | 9 | 9 | 9 | ✓ |
| 模型 | CPU 耗时 (ms/batch) | NPU 耗时 (ms/batch) | 加速比 |
|---|---|---|---|
| mlp_sgd | 2.90 | 153.65* | 0.02x |
| mlp_momentum | 2.41 | 1.17 | 2.06x |
| mlp_momentum_multistep | 2.36 | 0.96 | 2.46x |
| mlp_sgd_multistep | 2.37 | 0.68 | 3.49x |
| mlp_sgd_wd | 2.35 | 0.68 | 3.46x |
| cnn_sgd | 8.38 | 58.21* | 0.14x |
*注: 首次 NPU 推理包含初始化开销,后续推理将更快。对于小模型,CPU 在 batch size 较小时有优势。
使用 100 张 MNIST 测试集图像,分别在 CPU 和 NPU 上运行推理,对比输出 logits 的差异。
cd model1
python3 compare_cpu_npu.py| 模型 | CPU Acc | NPU Acc | Mean Rel% | Cos Sim | Pred Consist |
|---|---|---|---|---|---|
| mlp_sgd | 0.9700 | 0.9700 | 0.000133 | 1.0000000009 | 1.0000 |
| mlp_momentum | 1.0000 | 1.0000 | 0.000081 | 0.9999999989 | 1.0000 |
| mlp_momentum_multistep | 0.9900 | 0.9900 | 0.000134 | 1.0000000034 | 1.0000 |
| mlp_sgd_multistep | 0.9500 | 0.9500 | 0.000077 | 0.9999999978 | 1.0000 |
| mlp_sgd_wd | 0.9700 | 0.9700 | 0.000110 | 1.0000000170 | 1.0000 |
| cnn_sgd | 0.9800 | 0.9800 | 0.040090 | 0.9999999916 | 1.0000 |
精度测试结论:NPU 与 CPU 推理误差为 0.04%(均值),符合精度误差小于 1% 的要求。
| 模型 | CPU 耗时 (ms) | NPU 耗时 (ms) | 说明 |
|---|---|---|---|
| MLP 系列 (均值) | 2.48 | 0.85 | 小模型,NPU 推理优势不明显 |
| CNN | 8.38 | 58.21 | 首次包含初始化,后续可降低 |
对于极小模型(MLP),CPU 推理在低 batch 场景下具有延迟优势。对于计算密集的 CNN,NPU 在大 batch 场景下优势明显。
import torch
import torch.nn.functional as F
import pickle
import numpy as np
# 加载模型权重
data = pickle.load(open('cnn_sgd.pickle', 'rb'))
# 前向传播(NPU)
def forward_cnn(params, x):
# Conv1
h = F.conv2d(x, torch.from_numpy(params[0]['W']).float().npu(),
torch.from_numpy(params[0]['b']).squeeze().float().npu(),
padding='same')
h = torch.relu(F.max_pool2d(h, 2))
# Conv2
h = F.conv2d(h, torch.from_numpy(params[1]['W']).float().npu(),
torch.from_numpy(params[1]['b']).squeeze().float().npu(),
padding='same')
h = torch.relu(h)
h = h.view(h.size(0), -1)
# FC layers
h = torch.mm(h, torch.from_numpy(params[2]['W']).float().npu()) + \
torch.from_numpy(params[2]['b']).float().npu()
h = torch.relu(h)
h = torch.mm(h, torch.from_numpy(params[3]['W']).float().npu()) + \
torch.from_numpy(params[3]['b']).float().npu()
return h
# 使用示例
x = torch.randn(1, 1, 28, 28).npu()
logits = forward_cnn(data, x)
pred = torch.argmax(logits, dim=1)
本仓库提供完整的推理脚本,支持 CPU 和 NPU 双平台推理:
# NPU 推理
python3 inference.py --device npu
# CPU 推理
python3 inference.py --device cpu推理完成后会输出推理结果和耗时,表明模型在 NPU 上推理成功。