共计 1773 个字符,预计需要花费 5 分钟才能阅读完成。
MNIST 数据集与前馈神经网络的优势
MNIST 数据集包含 60,000 张训练图像和 10,000 张测试图像,每张都是 28×28 像素的手写数字灰度图。这个数据集之所以经典,是因为它足够小(适合快速验证),但又能体现真实场景的变异性(不同书写风格)。前馈神经网络 (FNN) 在这里的优势很明显:

- 图像尺寸固定,适合全连接层处理
- 数字识别是典型非线性分类问题,FNN 能通过激活函数学习复杂模式
- 计算量适中,在 CPU 上也能快速训练
数据预处理与模型设计
数据加载与标准化
PyTorch 的 torchvision 已经内置了 MNIST 数据加载器,但我们需要做关键处理:
- 将图像像素值从 [0,255] 归一化到[0,1]
- 用均值 0.1307 和标准差 0.3081 进行标准化(这是 MNIST 的统计特性)
import torchvision.transforms as transforms
transform = transforms.Compose([transforms.ToTensor(),
transforms.Normalize((0.1307,), (0.3081,))
])
网络架构设计
我们的网络包含三个全连接层:
- 输入层:28×28=784 个神经元
- 隐藏层:512 个神经元,使用 ReLU 激活
- 输出层:10 个神经元(对应 0 - 9 数字),使用 LogSoftmax
数学上看,隐藏层的计算过程是:
h = ReLU(W1 * x + b1)
output = LogSoftmax(W2 * h + b2)
训练实现
使用 PyTorch Lightning 规范代码结构,关键组件包括:
import pytorch_lightning as pl
import torch.nn.functional as F
class MNISTModel(pl.LightningModule):
def __init__(self):
super().__init__()
self.fc1 = nn.Linear(784, 512)
self.fc2 = nn.Linear(512, 10)
def forward(self, x):
x = x.view(-1, 784) # 展平输入
x = F.relu(self.fc1(x))
return F.log_softmax(self.fc2(x), dim=1)
def training_step(self, batch, batch_idx):
x, y = batch
loss = F.nll_loss(self(x), y) # 负对数似然损失
return loss
def configure_optimizers(self):
return torch.optim.Adam(self.parameters(), lr=0.001)
性能优化
Batch Size 选择
- 太小(如 32):更新频繁但梯度噪声大
- 太大(如 1024):内存压力大且可能陷入局部最优
- 推荐值:128-256 之间
动态学习率
使用 ReduceLROnPlateau 策略:
scheduler = {
'scheduler': torch.optim.lr_scheduler.ReduceLROnPlateau(
optimizer,
patience=3,
verbose=True
),
'monitor': 'val_loss'
}
GPU 加速
实测在 NVIDIA T4 上:
- CPU:约 90 秒 /epoch
- GPU:约 15 秒 /epoch
生产环境注意事项
模型量化
将 FP32 转为 INT8:
model = torch.quantization.quantize_dynamic(model, {torch.nn.Linear}, dtype=torch.qint8
)
异常处理
输入校验必不可少:
def preprocess(input_image):
assert input_image.shape == (1,28,28), "Invalid input shape"
assert input_image.min() >= 0 and input_image.max() <= 1, "Pixel value out of range"
性能监控
建议指标:
- 单次推理耗时(P99 < 50ms)
- 内存占用(<100MB)
- 吞吐量(QPS)
扩展思考
当需要识别更多类别(如字母 + 数字)时,我们需要:
- 修改输出层神经元数量
- 考虑更复杂的网络结构(如 CNN)
- 处理类别不平衡问题
实际部署时,你会选择直接扩展本模型,还是重构为新的架构呢?
正文完
发表至: 未分类
近一天内
