使用 Python 实现一个简单的神经网络分类器
在当今的人工智能领域,深度学习技术已经成为解决复杂问题的重要工具之一。其中,神经网络作为深度学习的核心组成部分,广泛应用于图像识别、自然语言处理、语音识别等领域。本文将介绍如何使用 Python 编写一个简单的全连接神经网络(Fully Connected Neural Network)来实现对 MNIST 手写数字数据集的分类任务。
我们将从以下几个方面展开:
环境准备与数据加载 构建神经网络模型 模型训练过程 模型评估与可视化 总结1. 环境准备与数据加载
首先,我们需要安装必要的库:numpy
用于数值计算,torch
是 PyTorch 框架,用于构建和训练神经网络。
pip install numpy torch torchvision matplotlib
接下来,我们导入所需的库并加载 MNIST 数据集。MNIST 包含了 70,000 张手写数字图片,每张图片为 28x28 的灰度图,对应数字 0 到 9。
import torchfrom torch import nn, optimfrom torch.utils.data import DataLoaderfrom torchvision import datasets, transformsimport matplotlib.pyplot as plt# 设置随机种子以保证结果可复现torch.manual_seed(42)# 定义数据预处理transform = transforms.Compose([ transforms.ToTensor(), transforms.Normalize((0.5,), (0.5,))])# 加载训练集和测试集train_dataset = datasets.MNIST(root='./data', train=True, download=True, transform=transform)test_dataset = datasets.MNIST(root='./data', train=False, download=True, transform=transform)# 创建数据加载器train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True)test_loader = DataLoader(test_dataset, batch_size=64, shuffle=False)
我们可以查看一下数据的结构:
images, labels = next(iter(train_loader))print(f"Batch shape: {images.shape}")print(f"Labels: {labels}")
输出示例:
Batch shape: torch.Size([64, 1, 28, 28])Labels: tensor([5, 0, 4, ..., 8, 4, 9])
每张图片是一个 1x28x28 的张量(通道数为1),每个 batch 包含 64 张图片。
2. 构建神经网络模型
我们使用 PyTorch 的 nn.Module
类来自定义一个简单的全连接神经网络。该网络包括两个隐藏层,激活函数使用 ReLU。
class SimpleNN(nn.Module): def __init__(self): super(SimpleNN, self).__init__() self.flatten = nn.Flatten() self.fc1 = nn.Linear(28 * 28, 128) self.fc2 = nn.Linear(128, 64) self.fc3 = nn.Linear(64, 10) self.relu = nn.ReLU() def forward(self, x): x = self.flatten(x) x = self.relu(self.fc1(x)) x = self.relu(self.fc2(x)) x = self.fc3(x) return xmodel = SimpleNN()print(model)
模型结构如下:
输入层:28x28 → 784 个节点隐藏层1:128 个节点,ReLU 激活隐藏层2:64 个节点,ReLU 激活输出层:10 个节点(对应 10 个类别)3. 模型训练过程
我们使用交叉熵损失函数和 Adam 优化器进行训练。
criterion = nn.CrossEntropyLoss()optimizer = optim.Adam(model.parameters(), lr=0.001)# 训练模型def train(model, train_loader, criterion, optimizer, epochs=5): model.train() for epoch in range(epochs): running_loss = 0.0 for images, labels in train_loader: # 前向传播 outputs = model(images) loss = criterion(outputs, labels) # 反向传播和优化 optimizer.zero_grad() loss.backward() optimizer.step() running_loss += loss.item() print(f"Epoch [{epoch+1}/{epochs}], Loss: {running_loss/len(train_loader):.4f}")train(model, train_loader, criterion, optimizer, epochs=5)
运行结果类似:
Epoch [1/5], Loss: 0.2987Epoch [2/5], Loss: 0.1432Epoch [3/5], Loss: 0.1035Epoch [4/5], Loss: 0.0821Epoch [5/5], Loss: 0.0689
可以看到随着训练轮数增加,损失值逐渐减小,说明模型正在学习。
4. 模型评估与可视化
训练完成后,我们评估模型在测试集上的表现。
def evaluate(model, test_loader): model.eval() correct = 0 total = 0 with torch.no_grad(): for images, labels in test_loader: outputs = model(images) _, predicted = torch.max(outputs.data, 1) total += labels.size(0) correct += (predicted == labels).sum().item() accuracy = 100 * correct / total print(f"Test Accuracy: {accuracy:.2f}%")evaluate(model, test_loader)
输出示例:
Test Accuracy: 97.23%
我们的简单模型已经达到了 97% 以上的准确率。为了更直观地理解模型预测效果,我们可以可视化一些测试样本及其预测结果。
def visualize_predictions(model, test_loader, num_images=6): model.eval() data_iter = iter(test_loader) images, labels = next(data_iter) outputs = model(images) _, preds = torch.max(outputs, 1) plt.figure(figsize=(10, 5)) for i in range(num_images): plt.subplot(2, 3, i + 1) image = images[i].numpy().squeeze() plt.imshow(image, cmap='gray') plt.title(f"Pred: {preds[i]}, True: {labels[i]}") plt.axis('off') plt.tight_layout() plt.show()visualize_predictions(model, test_loader)
这段代码会显示 6 张测试图片,并标注模型的预测结果和真实标签。
5. 总结
本文介绍了如何使用 Python 和 PyTorch 构建一个简单的全连接神经网络来完成 MNIST 手写数字分类任务。我们完成了以下工作:
加载和预处理数据;定义了一个三层全连接神经网络;使用交叉熵损失函数和 Adam 优化器进行训练;在测试集上评估模型性能;可视化部分预测结果。虽然这个模型比较简单,但它为我们深入理解神经网络的工作原理打下了基础。后续可以尝试引入卷积神经网络(CNN)、使用 GPU 加速训练、以及调整超参数等方法进一步提升模型性能。
如果你对深度学习感兴趣,建议继续学习 PyTorch 或 TensorFlow 框架的高级用法,例如迁移学习、模型保存与加载、分布式训练等内容。