一、LeNet
1、LeNet简介
LeNet是一种卷积神经网络(CNN)结构,旨在解决手写数字识别问题,特别是用于 MNIST 数据集中的数字分类。LeNet 是最早的深度学习卷积神经网络之一,它奠定了卷积神经网络(CNN)在计算机视觉领域的基础,并对后来的神经网络发展产生了深远的影响。网络结构如下图:
2、简单代码实现
import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms
from torch.utils.data import DataLoader
import matplotlib.pyplot as plt
# 数据预处理:将图像转换为Tensor,并进行归一化处理
transform = transforms.Compose([
transforms.ToTensor(), # 将图片转换为Tensor
transforms.Normalize((0.5,), (0.5,)) # 标准化,MNIST图像是灰度图像
])
# 下载 MNIST 数据集
trainset = datasets.MNIST(root='./data/data', train=True, download=False, transform=transform)
testset = datasets.MNIST(root='./data/data', train=False, download=False, transform=transform)
# 使用 DataLoader 加载数据
trainloader = DataLoader(trainset, batch_size=32, shuffle=True)
testloader = DataLoader(testset, batch_size=32, shuffle=False)
# 定义 LeNet 网络
model = nn.Sequential(
# 第一卷积层: 输入1通道,输出6通道,卷积核大小5x5
nn.Conv2d(1, 6, kernel_size=5), # 28*28*1 + 5*5*6--->(28+2*0-5/1+1)=24*24*6
nn.Sigmoid(), # 激活函数Sigmoid
nn.AvgPool2d(2, 2), # 2x2 平均池化 # 24*24*6 --> (24-2/2+1)=12*12*6
# 第二卷积层: 输入6通道,输出16通道,卷积核大小5x5
nn.Conv2d(6, 16, kernel_size=5), # 12*12*6 --> (12+2*0-5/1+1)=8*8*16
nn.Sigmoid(), # 激活函数Sigmoid
nn.AvgPool2d(2, 2), # 2x2 平均池化 # 8*8*16 --> (8-2/2+1)=4*4*16
# 展平层,将特征图展平为一维向量
nn.Flatten(),
# 全连接层1: 16 * 5 * 5 -> 120
nn.Linear(16 * 4 * 4, 120),
nn.Sigmoid(), # 激活函数Sigmoid
# 全连接层2: 120 -> 84
nn.Linear(120, 84),
nn.Sigmoid(), # 激活函数Sigmoid
# 输出层: 84 -> 10 (分类输出)
nn.Linear(84, 10)
)
# 查看各层输出
X = torch.rand(size=(1,1,28,28),dtype=torch.float32)
for layer in model:
X = layer(X)
print(layer.__class__.__name__,"output_shape:\t",X.shape)
print("\n")
# 使用 GPU 如果可用
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model = model.to(device)
# 定义损失函数
criterion = nn.CrossEntropyLoss()
# 定义优化器
optimizer = optim.Adam(model.parameters(), lr=0.001)
# 训练过程
num_epochs = 10
for epoch in range(num_epochs):
running_loss = 0.0
correct = 0
total = 0
model.train() # 设置模型为训练模式
for inputs, labels in trainloader:
inputs, labels = inputs.to(device), labels.to(device) # 将数据转移到GPU或CPU
optimizer.zero_grad() # 清零梯度
outputs = model(inputs) # 前向传播
loss = criterion(outputs, labels) # 计算损失
loss.backward() # 反向传播
optimizer.step() # 更新参数
running_loss += loss.item()
# 计算准确率
_, predicted = torch.max(outputs, 1)
total += labels.size(0)
correct += (predicted == labels).sum().item()
epoch_loss = running_loss / len(trainloader)
epoch_accuracy = 100 * correct / total
print(f"Epoch {epoch + 1}/{num_epochs}, Loss: {epoch_loss:.4f}, Accuracy: {epoch_accuracy:.2f}%")
# 测试过程
model.eval() # 设置模型为评估模式
correct = 0
total = 0
with torch.no_grad(): # 在评估阶段不需要计算梯度
for inputs, labels in testloader:
inputs, labels = inputs.to(device), labels.to(device) # 将数据转移到GPU或CPU
outputs = model(inputs)
_, predicted = torch.max(outputs, 1)
total += labels.size(0)
correct += (predicted == labels).sum().item()
test_accuracy = 100 * correct / total
print(f"Test Accuracy: {test_accuracy:.2f}%")
# 可视化一些测试图片
dataiter = iter(testloader) # 创建一个迭代器
images, labels = next(dataiter) # 获取第一个批次的数据
# 显示图片
fig, axes = plt.subplots(1, 10, figsize=(12, 4))
for i in range(10):
img = images[i] / 2 + 0.5 # 将图像从[-1, 1]范围反归一化到[0, 1]范围
axes[i].imshow(img.squeeze(), cmap='gray') # 转换维度顺序为 (H, W)
axes[i].set_title(f'Pred: {torch.argmax(model(images[i:i + 1].to(device)))}')
axes[i].axis('off')
plt.show()
运行结果图:
二、AlexNet
1、AlexNet简介
AlexNet 是一种较为深层的卷积神经网络,它不仅在深度和结构上比之前的 LeNet 等网络更复杂,而且使用了现代卷积神经网络中的一些关键技巧(如 ReLU 激活函数、GPU 加速、Dropout、数据增强等),为深度学习的快速发展奠定了基础。网络结构如下图:
2、简单代码实现
由于在AlexNet原数据集ImageNet上训练模型可能需要数小时才能收敛,所以这里采用MINT数据集来进行训练,为了保持输入一致,将MINT的28*28*1的数据resize为224*224*1大小。
import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms
from torch.utils.data import DataLoader
import matplotlib.pyplot as plt
# 数据预处理:将图像转换为Tensor,并进行归一化处理
transform = transforms.Compose([
transforms.Resize(224),
transforms.ToTensor(), # 将图片转换为Tensor
transforms.Normalize((