第五章:计算机视觉(Computer Vision)

第一部分:计算机视觉基础

第五节:项目实战:利用 PyTorch 实现一个前馈神经网络和一个卷积神经网络


一、实验目标

  • 熟悉 PyTorch 基本结构DatasetDataLoadernn.ModuleOptimizer

  • 分别实现 前馈神经网络(FNN)卷积神经网络(CNN),并在 MNIST 手写数字数据集 上进行训练和测试。

  • 比较 FNN 和 CNN 在图像任务上的效果差异。


二、环境准备

安装 PyTorch:

pip install torch torchvision

导入常用库:

import torch
import torch.nn as nn
import torch.optim as optim
import torchvision
import torchvision.transforms as transforms

三、数据集准备

使用 MNIST 手写数字集(28×28 灰度图):

# 数据预处理:转为Tensor并归一化
transform = transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize((0.5,), (0.5,))
])

# 训练集 & 测试集
trainset = torchvision.datasets.MNIST(root='./data', train=True, download=True, transform=transform)
testset = torchvision.datasets.MNIST(root='./data', train=False, download=True, transform=transform)

trainloader = torch.utils.data.DataLoader(trainset, batch_size=64, shuffle=True)
testloader = torch.utils.data.DataLoader(testset, batch_size=64, shuffle=False)

四、实现前馈神经网络(FNN)

FNN 将图像拉平成一维向量,直接输入全连接层。

class FeedForwardNN(nn.Module):
    def __init__(self):
        super(FeedForwardNN, self).__init__()
        self.fc1 = nn.Linear(28*28, 256)  # 输入层 → 隐藏层
        self.fc2 = nn.Linear(256, 128)    # 隐藏层 → 隐藏层
        self.fc3 = nn.Linear(128, 10)     # 输出层(10类)
        self.relu = nn.ReLU()

    def forward(self, x):
        x = x.view(-1, 28*28)  # 展平
        x = self.relu(self.fc1(x))
        x = self.relu(self.fc2(x))
        x = self.fc3(x)
        return x

五、实现卷积神经网络(CNN)

CNN 保留了图像的空间结构,使用卷积层提取局部特征。

class SimpleCNN(nn.Module):
    def __init__(self):
        super(SimpleCNN, self).__init__()
        self.conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)  # 1 通道 → 32 通道
        self.conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1) # 32 通道 → 64 通道
        self.pool = nn.MaxPool2d(2, 2)
        self.fc1 = nn.Linear(64 * 7 * 7, 128)
        self.fc2 = nn.Linear(128, 10)
        self.relu = nn.ReLU()

    def forward(self, x):
        x = self.relu(self.conv1(x))
        x = self.pool(self.relu(self.conv2(x)))
        x = x.view(-1, 64 * 7 * 7)
        x = self.relu(self.fc1(x))
        x = self.fc2(x)
        return x

六、训练与测试函数

def train_model(model, trainloader, criterion, optimizer, epochs=5):
    for epoch in range(epochs):
        running_loss = 0.0
        for images, labels in trainloader:
            optimizer.zero_grad()
            outputs = model(images)
            loss = criterion(outputs, labels)
            loss.backward()
            optimizer.step()
            running_loss += loss.item()
        print(f"Epoch {epoch+1}, Loss: {running_loss/len(trainloader):.4f}")

def test_model(model, testloader):
    correct, total = 0, 0
    with torch.no_grad():
        for images, labels in testloader:
            outputs = model(images)
            _, predicted = torch.max(outputs, 1)
            total += labels.size(0)
            correct += (predicted == labels).sum().item()
    print(f"Accuracy: {100 * correct / total:.2f}%")

七、模型训练对比

1. 前馈神经网络(FNN)

fnn = FeedForwardNN()
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(fnn.parameters(), lr=0.001)

train_model(fnn, trainloader, criterion, optimizer)
test_model(fnn, testloader)

2. 卷积神经网络(CNN)

cnn = SimpleCNN()
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(cnn.parameters(), lr=0.001)

train_model(cnn, trainloader, criterion, optimizer)
test_model(cnn, testloader)

八、实验结果与分析

  • FNN:准确率一般在 92% 左右,因为它没有利用图像的空间信息。

  • CNN:准确率通常超过 98%,明显优于 FNN。

结论:

  • CNN 更适合处理图像任务,因为它能自动学习空间特征。

  • FNN 作为基线模型简单易懂,但在视觉任务上表现有限。


九、总结

本节通过 PyTorch 实现了:

  1. 前馈神经网络:结构简单,但忽略了图像空间结构。

  2. 卷积神经网络:利用卷积和池化提取图像特征,性能更强。

实践表明,CNN 在计算机视觉任务中比 FNN 更加适合,几乎成为图像处理任务的默认选择。

更多推荐