深度学习笔记_5 经典卷积神经网络LeNet-5 解决MNIST数据集

1、定义LeNet-5模型,包括卷积层和全连接层。

import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms

# 导入必要的库

# 定义 LeNet-5 模型
class LeNet5(nn.Module):
    def __init__(self):
        super(LeNet5, self).__init__()
        # 定义卷积层和全连接层
        self.conv1 = nn.Conv2d(1, 6, kernel_size=5)  # 输入通道1,输出通道6,卷积核大小5x5
        self.conv2 = nn.Conv2d(6, 16, kernel_size=5)  # 输入通道6,输出通道16,卷积核大小5x5
        self.fc1 = nn.Linear(16 * 4 * 4, 120)  # 全连接层,输入维度为16*4*4,输出维度为120
        self.fc2 = nn.Linear(120, 84)  # 全连接层,输入维度为120,输出维度为84
        self.fc3 = nn.Linear(84, 64)  # 全连接层,输入维度为84,输出维度为64
        self.fc4 = nn.Linear(64, 10)  # 全连接层,输入维度为64,输出维度为10

    def forward(self, x):
        x = torch.relu(self.conv1(x))  # 第一个卷积层后接ReLU激活函数
        x = torch.max_pool2d(x, 2)  # 池化层,执行2x2的最大池化
        x = torch.relu(self.conv2(x))  # 第二个卷积层后接ReLU激活函数
        x = torch.max_pool2d(x, 2)  # 池化层,执行2x2的最大池化
        x = x.view(-1, 16 * 4 * 4)  # 数据展平,以便输入全连接层
        x = torch.relu(self.fc1(x))  # 第一个全连接层后接ReLU激活函数
        x = torch.relu(self.fc2(x))  # 第二个全连接层后接ReLU激活函数
        x = self.fc3(x)  # 第三个全连接层
        return x

2、对MNIST数据集进行加载和预处理,包括将图像转换为张量和标准化。

# 加载 MNIST 训练集和测试集
transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,))])
# 定义数据预处理,包括转换为张量和标准化

train_dataset = datasets.MNIST(root='./data', train=True, download=True, transform=transform)
test_dataset = datasets.MNIST(root='./data', train=False, download=True, transform=transform)
# 下载MNIST数据集,并应用数据预处理

train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=64, shuffle=True)
test_loader = torch.utils.data.DataLoader(test_dataset, batch_size=64, shuffle=False)
# 创建训练和测试数据加载器

3、初始化模型和优化器,使用随机梯度下降(SGD)优化器。

# 初始化模型和优化器
model = LeNet5()  # 创建LeNet-5模型
optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.9)  # 使用随机梯度下降作为优化器

# 训练模型
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")  # 检查是否支持GPU,如果支持则使用GPU
model.to(device)  # 将模型移动到GPU或CPU
criterion = nn.CrossEntropyLoss()  # 使用交叉熵损失函数

4、在每个训练周期内,进行前向传播、反向传播和参数更新。在训练集上进行精度测试,以评估模型性能。

import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms

# 导入必要的库

# 定义 LeNet-5 模型
class LeNet5(nn.Module):
    def __init__(self):
        super(LeNet5, self).__init__()
        # 定义卷积层和全连接层
        self.conv1 = nn.Conv2d(1, 6, kernel_size=5)  # 输入通道1,输出通道6,卷积核大小5x5
        self.conv2 = nn.Conv2d(6, 16, kernel_size=5)  # 输入通道6,输出通道16,卷积核大小5x5
        self.fc1 = nn.Linear(16 * 4 * 4, 120)  # 全连接层,输入维度为16*4*4,输出维度为120
        self.fc2 = nn.Linear(120, 84)  # 全连接层,输入维度为120,输出维度为84
        self.fc3 = nn.Linear(84, 64)  # 全连接层,输入维度为84,输出维度为64
        self.fc4 = nn.Linear(64, 10)  # 全连接层,输入维度为64,输出维度为10

    def forward(self, x):
        x = torch.relu(self.conv1(x))  # 第一个卷积层后接ReLU激活函数
        x = torch.max_pool2d(x, 2)  # 池化层,执行2x2的最大池化
        x = torch.relu(self.conv2(x))  # 第二个卷积层后接ReLU激活函数
        x = torch.max_pool2d(x, 2)  # 池化层,执行2x2的最大池化
        x = x.view(-1, 16 * 4 * 4)  # 数据展平,以便输入全连接层
        x = torch.relu(self.fc1(x))  # 第一个全连接层后接ReLU激活函数
        x = torch.relu(self.fc2(x))  # 第二个全连接层后接ReLU激活函数
        x = self.fc3(x)  # 第三个全连接层
        return x

# 加载 MNIST 训练集和测试集
transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,))])
# 定义数据预处理,包括转换为张量和标准化

train_dataset = datasets.MNIST(root='./data', train=True, download=True, transform=transform)
test_dataset = datasets.MNIST(root='./data', train=False, download=True, transform=transform)
# 下载MNIST数据集,并应用数据预处理

train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=64, shuffle=True)
test_loader = torch.utils.data.DataLoader(test_dataset, batch_size=64, shuffle=False)
# 创建训练和测试数据加载器

# 初始化模型和优化器
model = LeNet5()  # 创建LeNet-5模型
optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.9)  # 使用随机梯度下降作为优化器

# 训练模型
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")  # 检查是否支持GPU,如果支持则使用GPU
model.to(device)  # 将模型移动到GPU或CPU
criterion = nn.CrossEntropyLoss()  # 使用交叉熵损失函数

for epoch in range(10):
    model.train()  # 设置模型为训练模式
    running_loss = 0.0
    for images, labels in train_loader:
        images, labels = images.to(device), labels.to(device)  # 将数据移动到GPU或CPU
        optimizer.zero_grad()  # 梯度清零
        outputs = model(images)  # 前向传播
        loss = criterion(outputs, labels)  # 计算损失
        loss.backward()  # 反向传播
        optimizer.step()  # 更新模型参数
        running_loss += loss.item()

    # 在训练集上进行精度测试
    model.eval()  # 设置模型为评估模式
    correct = 0
    total = 0
    with torch.no_grad():
        for images, labels in test_loader:
            images, labels = images.to(device), labels.to(device)  # 将数据移动到GPU或CPU
            outputs = model(images)  # 前向传播
            _, predicted = torch.max(outputs.data, 1)  # 获取预测类别
            total += labels.size(0)
            correct += (predicted == labels).sum().item()
    accuracy = 100 * correct / total

    print('Epoch: %d, Loss: %.3f, Accuracy: %.2f%%' % (epoch+1, running_loss, accuracy))

5、实验步骤和关键要点:

  1. 模型定义:LeNet-5模型被定义为一个经典的卷积神经网络,包括卷积层和全连接层。模型结构包括两个卷积层、两个池化层和三个全连接层。

  2. 数据加载和预处理:MNIST数据集被加载并进行预处理。预处理包括将图像转换为张量,并进行标准化,以确保输入数据在训练期间具有相似的尺度和分布。

  3. 初始化模型和优化器:LeNet-5模型被初始化,并使用随机梯度下降(SGD)作为优化器。SGD用于在训练期间调整模型参数以最小化损失函数。

  4. 模型训练:模型被训练在训练集上进行了多个周期的训练。对于每个训练周期,执行以下步骤:

    • 设置模型为训练模式。
    • 对每个批次进行前向传播,计算损失,执行反向传播,更新模型参数。
    • 记录每个训练周期的损失值。
  5. 模型测试:在每个训练周期结束后,模型在测试集上进行了精度测试。在测试期间,执行以下步骤:

    • 设置模型为评估模式。
    • 通过模型进行前向传播,计算测试集上的预测结果。
    • 检查模型的准确性,计算正确分类的样本数量,并计算总样本数量。
    • 记录每个训练周期的测试精度。
  6. 打印结果:在每个训练周期结束后,打印出训练周期的损失和测试精度,以便监控模型的性能。

这个实验展示了如何使用PyTorch框架构建、训练和测试深度学习模型。LeNet-5模型在MNIST数据集上取得了不错的手写数字识别性能。通过多个训练周期,模型的损失逐渐减小,测试精度逐渐增加,表明模型在训练过程中逐渐学习到了有效的特征表示,从而提高了在新样本上的分类准确性。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

知源书院

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值