使用Python实现一个简单的神经网络分类器
在机器学习和人工智能领域,神经网络是一种非常强大的工具,广泛应用于图像识别、自然语言处理、语音识别等领域。本文将介绍如何使用 Python 和 PyTorch
框架来构建一个简单的全连接神经网络(Fully Connected Neural Network),用于对经典的 MNIST 手写数字数据集进行分类。
我们将从环境准备开始,逐步介绍代码实现,并解释其工作原理。最终的模型将在测试集上达到较高的准确率。
环境准备
首先,确保你的环境中安装了以下依赖库:
Python 3.xPyTorchmatplotlib(用于可视化)torchvision(提供标准数据集)你可以通过以下命令安装所需的库:
pip install torch torchvision matplotlib
导入必要的模块
import torchimport torch.nn as nnimport torch.optim as optimfrom torchvision import datasets, transformsfrom torch.utils.data import DataLoaderimport matplotlib.pyplot as plt
定义超参数
batch_size = 64learning_rate = 0.01num_epochs = 5
这些参数决定了训练过程的行为:
batch_size
: 每次迭代使用的样本数量。learning_rate
: 控制优化器的学习步长。num_epochs
: 训练整个数据集的次数。加载MNIST数据集
我们使用 torchvision.datasets.MNIST
来加载手写数字数据集,并对其进行预处理。
transform = transforms.Compose([ transforms.ToTensor(), transforms.Normalize((0.5,), (0.5,))])train_dataset = datasets.MNIST(root='./data', train=True, transform=transform, download=True)test_dataset = datasets.MNIST(root='./data', train=False, transform=transform, download=True)train_loader = DataLoader(dataset=train_dataset, batch_size=batch_size, shuffle=True)test_loader = DataLoader(dataset=test_dataset, batch_size=batch_size, shuffle=False)
我们可以查看一下数据集的基本信息:
print(f"Train dataset size: {len(train_dataset)}")print(f"Test dataset size: {len(test_dataset)}")
输出示例:
Train dataset size: 60000Test dataset size: 10000
构建神经网络模型
我们定义一个具有两个隐藏层的全连接神经网络。
class SimpleNN(nn.Module): def __init__(self): super(SimpleNN, self).__init__() self.flatten = nn.Flatten() self.fc1 = nn.Linear(28 * 28, 512) self.relu1 = nn.ReLU() self.fc2 = nn.Linear(512, 256) self.relu2 = nn.ReLU() self.fc3 = nn.Linear(256, 10) def forward(self, x): x = self.flatten(x) x = self.fc1(x) x = self.relu1(x) x = self.fc2(x) x = self.relu2(x) x = self.fc3(x) return x
该模型结构如下:
输入层:28x28 = 784 个像素点。隐藏层1:512个神经元,ReLU激活函数。隐藏层2:256个神经元,ReLU激活函数。输出层:10个神经元,对应0~9的数字类别。初始化模型、损失函数和优化器
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")model = SimpleNN().to(device)criterion = nn.CrossEntropyLoss()optimizer = optim.Adam(model.parameters(), lr=learning_rate)
这里我们使用交叉熵损失函数(CrossEntropyLoss)和 Adam 优化器。
训练模型
for epoch in range(num_epochs): model.train() running_loss = 0.0 for images, labels in train_loader: images, labels = images.to(device), labels.to(device) # 前向传播 outputs = model(images) loss = criterion(outputs, labels) # 反向传播与优化 optimizer.zero_grad() loss.backward() optimizer.step() running_loss += loss.item() print(f"Epoch [{epoch+1}/{num_epochs}], Loss: {running_loss/len(train_loader):.4f}")
每轮训练结束后,打印当前的平均损失值。
评估模型性能
model.eval()correct = 0total = 0with torch.no_grad(): for images, labels in test_loader: images, labels = images.to(device), labels.to(device) outputs = model(images) _, predicted = torch.max(outputs.data, 1) total += labels.size(0) correct += (predicted == labels).sum().item()print(f"Test Accuracy: {100 * correct / total:.2f}%")
这段代码将计算模型在测试集上的准确率。
可视化部分预测结果
为了更直观地了解模型的表现,我们可以随机选择一些测试图片并显示模型的预测结果。
def imshow(img): img = img / 2 + 0.5 # unnormalize npimg = img.numpy() plt.imshow(np.transpose(npimg, (1, 2, 0)), cmap='gray') plt.show()dataiter = iter(test_loader)images, labels = next(dataiter)imshow(torchvision.utils.make_grid(images[:4]))model.eval()with torch.no_grad(): outputs = model(images.to(device)) _, predicted = torch.max(outputs, 1)print('Predicted:', ' '.join(f'{predicted[j].item()}' for j in range(4)))print('GroundTruth:', ' '.join(f'{labels[j]}' for j in range(4)))
这段代码会显示前4张图像及其预测标签与真实标签。
十、完整代码汇总
以下是完整的代码整合版本:
import torchimport torch.nn as nnimport torch.optim as optimfrom torchvision import datasets, transformsfrom torch.utils.data import DataLoaderimport matplotlib.pyplot as pltimport torchvision# 超参数batch_size = 64learning_rate = 0.01num_epochs = 5# 数据预处理transform = transforms.Compose([ transforms.ToTensor(), transforms.Normalize((0.5,), (0.5,))])# 加载数据集train_dataset = datasets.MNIST(root='./data', train=True, transform=transform, download=True)test_dataset = datasets.MNIST(root='./data', train=False, transform=transform, download=True)train_loader = DataLoader(dataset=train_dataset, batch_size=batch_size, shuffle=True)test_loader = DataLoader(dataset=test_dataset, batch_size=batch_size, shuffle=False)# 定义神经网络class SimpleNN(nn.Module): def __init__(self): super(SimpleNN, self).__init__() self.flatten = nn.Flatten() self.fc1 = nn.Linear(28 * 28, 512) self.relu1 = nn.ReLU() self.fc2 = nn.Linear(512, 256) self.relu2 = nn.ReLU() self.fc3 = nn.Linear(256, 10) def forward(self, x): x = self.flatten(x) x = self.fc1(x) x = self.relu1(x) x = self.fc2(x) x = self.relu2(x) x = self.fc3(x) return x# 初始化设备、模型、损失函数和优化器device = torch.device("cuda" if torch.cuda.is_available() else "cpu")model = SimpleNN().to(device)criterion = nn.CrossEntropyLoss()optimizer = optim.Adam(model.parameters(), lr=learning_rate)# 训练模型for epoch in range(num_epochs): model.train() running_loss = 0.0 for images, labels in train_loader: images, labels = images.to(device), labels.to(device) outputs = model(images) loss = criterion(outputs, labels) optimizer.zero_grad() loss.backward() optimizer.step() running_loss += loss.item() print(f"Epoch [{epoch+1}/{num_epochs}], Loss: {running_loss/len(train_loader):.4f}")# 测试模型model.eval()correct = 0total = 0with torch.no_grad(): for images, labels in test_loader: images, labels = images.to(device), labels.to(device) outputs = model(images) _, predicted = torch.max(outputs.data, 1) total += labels.size(0) correct += (predicted == labels).sum().item()print(f"Test Accuracy: {100 * correct / total:.2f}%")# 显示预测结果def imshow(img): img = img / 2 + 0.5 npimg = img.numpy() plt.imshow(np.transpose(npimg, (1, 2, 0)), cmap='gray') plt.show()dataiter = iter(test_loader)images, labels = next(dataiter)imshow(torchvision.utils.make_grid(images[:4]))model.eval()with torch.no_grad(): outputs = model(images.to(device)) _, predicted = torch.max(outputs, 1)print('Predicted:', ' '.join(f'{predicted[j].item()}' for j in range(4)))print('GroundTruth:', ' '.join(f'{labels[j]}' for j in range(4)))
十总结与展望
本文介绍了如何使用 PyTorch 构建一个简单的全连接神经网络,并在 MNIST 数据集上进行训练和测试。我们实现了数据加载、模型定义、训练循环、模型评估以及结果可视化等完整流程。
虽然这个模型相对简单,但它为理解深度学习的基础提供了良好的实践基础。未来可以尝试以下改进:
使用卷积神经网络(CNN)提升准确率;添加 dropout 层防止过拟合;使用学习率调度器动态调整学习率;尝试不同的优化器和损失函数组合;部署模型到 Web 或移动端应用中。希望这篇文章能够帮助你入门神经网络编程和 PyTorch 的使用!如果你有任何问题或建议,欢迎留言讨论。
字数统计:约1400字