LeNet(又称 LeNet-5)是最早发布的卷积神经网络之一,因其在计算机视觉任务中的高效性能而受到广泛关注。 这个模型是由Yann LeCun在1989年提出的(并以其命名),目的是识别图像中的手写数字(灰度图,即单通道图像)。
LeNet-5 中的数字 5 5 5 指的是该网络一共有五层,其中包括:
注意,我们通常把一个卷积层和随后紧连的一个汇聚层视为一个卷积层,这是因为汇聚层中没有任何可学习的参数。
LeNet(简化版)的架构如下图所示:
在了解了 LeNet 的架构后,我们可以使用Pytorch进行搭建:
from torch import nn
class LeNet(nn.Module):
def __init__(self):
super().__init__()
self.net = nn.Sequential(
nn.Conv2d(1, 6, kernel_size=5, padding=2),
nn.Sigmoid(),
nn.AvgPool2d(kernel_size=2, stride=2),
nn.Conv2d(6, 16, kernel_size=5),
nn.Sigmoid(),
nn.AvgPool2d(kernel_size=2, stride=2),
nn.Flatten(),
nn.Linear(16 * 5 * 5, 120),
nn.Sigmoid(),
nn.Linear(120, 84),
nn.Sigmoid(),
nn.Linear(84, 10),
)
def forward(self, inputs):
return self.net(inputs)
这里对原始模型做了一点小改动,去掉了最后一层的高斯激活。除此之外,这个网络与最初的LeNet-5一致。
我们依然使用Fashion-MNIST数据集进行训练,首先导入必要的包:
import torch
import torchvision
from torch import nn
from torch.utils.data import DataLoader
from torchvision.transforms import ToTensor
然后处理数据集:
train_data = torchvision.datasets.FashionMNIST(root='./data', train=True, transform=ToTensor())
test_data = torchvision.datasets.FashionMNIST(root='./data', train=False, transform=ToTensor())
train_loader = DataLoader(train_data, batch_size=64, shuffle=True)
test_loader = DataLoader(test_data, batch_size=64)
初始化 LeNet,损失函数以及相应的优化器:
lenet = LeNet()
lenet.cuda() # 移动到GPU上
loss_fn = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(lenet.parameters(), lr=1e-2)
定义训练与测试函数:
def train(train_loader, model, loss_fn, optimizer):
for batch_idx, (X, y) in enumerate(train_loader):
X, y = X.cuda(), y.cuda()
loss = loss_fn(model(X), y)
optimizer.zero_grad()
loss.backward()
optimizer.step()
def test(test_loader, model):
size = len(test_loader.dataset)
correct = 0
with torch.no_grad():
for X, y in test_loader:
X, y = X.cuda(), y.cuda()
pred = model(X)
correct += (pred.argmax(dim=1) == y).sum().item()
correct /= size
print('Test Accuracy: {:.6f}\n'.format(correct))
num_epochs = 20
for epoch in range(num_epochs):
print(f"Epoch {epoch+1}\n-------------------------------")
train(train_loader, lenet, loss_fn, optimizer)
test(test_loader, lenet)
print("Done!")
训练20个Epoch后的结果如下:
Epoch 20
-------------------------------
Test Accuracy: 0.896300