LeNet:深度学习图像识别的里程碑
LeNet是卷积神经网络(Convolutional Neural Network, CNN)领域的先驱模型,由Yann LeCun等人在1998年提出,被广泛应用于手写数字识别和其他计算机视觉任务。本文将介绍LeNet模型的数学原理,使用PyTorch进行代码实现和实验验证。
数学原理
卷积操作
卷积是CNN中最重要的操作之一,它可以从输入数据中提取特征。在LeNet模型中,卷积操作使用卷积核与输入数据进行逐元素相乘,然后将相乘后的结果相加得到输出特征图。
Y
[
i
,
j
]
=
∑
m
∑
n
(
X
[
m
,
n
]
∗
K
[
i
−
m
,
j
−
n
]
)
Y[i, j] = \sum_{m}\sum_{n}(X[m, n] * K[i-m, j-n])
Y[i,j]=m∑n∑(X[m,n]∗K[i−m,j−n])
其中,Y是输出特征图的某个位置上的值,i和j是输出特征图的索引,m和n是卷积核的索引,X是输入特征图的值,K是卷积核的权重。
卷积操作的步骤如下:
1.将卷积核与输入特征图进行逐元素相乘。
2.将相乘后的结果相加得到输出特征图的对应位置的值。
卷积操作的作用是通过滑动窗口的方式对输入特征图进行扫描,提取局部特征,并保留空间关系。卷积核的权重可以学习到不同的特征,例如边缘、纹理等。
池化操作
池化操作用于对特征图进行下采样,以减少数据维度并保留重要特征。在LeNet模型中,常见的池化方式包括最大池化和平均池化。
最大池化(Max Pooling)
最大池化是池化操作中常用的一种类型,它会选取一个滤波器区域内的最大值作为输出。
平均池化(Average Pooling)
平均池化是另一种常见的池化方式,它会选取一个滤波器区域内所有值的平均值作为输出。
池化操作有助于减少数据的维度,降低计算复杂度,同时保留重要的特征信息,有利于提高模型的鲁棒性和泛化能力。
全连接层
全连接层将上一层的所有神经元与当前层的所有神经元进行连接,通过权重矩阵和偏置向量进行线性变换,然后再通过激活函数进行非线性变换。
Y = tanh ( ∑ i = 1 n ( W i X i + b i ) ) Y = \tanh(\sum_{i=1}^{n}(W_{i}X_{i} + b_{i})) Y=tanh(i=1∑n(WiXi+bi))
激活函数
激活函数是CNN中必不可少的组成部分,它可以将线性模型转化为非线性模型,从而提高模型的表达能力。在LeNet模型中,使用tanh作为激活函数。
tanh ( x ) = e x − e − x e x + e − x \tanh(x) = \frac{e^x - e^{-x}}{e^x + e^{-x}} tanh(x)=ex+e−xex−e−x
前向传播
LeNet模型的前向传播过程包括卷积运算、池化操作、全连接层的线性变换和非线性变换,最终通过softmax函数得到分类结果。
反向传播
反向传播用于计算损失函数对模型参数的梯度,通过梯度下降算法来更新模型参数,使损失函数达到最小值,从而训练模型。
代码实现
以下是使用PyTorch实现LeNet模型的代码:
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision.datasets import MNIST
from torchvision.transforms import ToTensor
from torch.utils.data import DataLoader
import tqdm
# 定义LeNet模型
class LeNet(nn.Module):
def __init__(self):
super(LeNet, self).__init__()
self.conv1 = nn.Conv2d(in_channels=1, out_channels=6, kernel_size=5)
self.pool1 = nn.AvgPool2d(kernel_size=2, stride=2)
self.conv2 = nn.Conv2d(in_channels=6, out_channels=16, kernel_size=5)
self.pool2 = nn.AvgPool2d(2)
self.fc1 = nn.Linear(in_features=4 * 4 * 16, out_features=120)
self.fc2 = nn.Linear(in_features=120, out_features=84)
self.fc3 = nn.Linear(in_features=84, out_features=10)
def forward(self, x):
x = F.tanh(self.conv1(x))
x = self.pool1(x)
x = F.tanh(self.conv2(x))
x = self.pool2(x)
x = x.view(-1, 4 * 4 * 16)
x = F.tanh(self.fc1(x))
x = F.tanh(self.fc2(x))
output = F.softmax(self.fc3(x), dim=1)
return output
# 准备数据集
train_set = MNIST(root='.', train=True, download=True, transform=ToTensor())
test_set = MNIST(root='.', train=False, download=True, transform=ToTensor())
train_loader = DataLoader(train_set, batch_size=128, shuffle=True)
test_loader = DataLoader(test_set, batch_size=128, shuffle=False)
# 训练模型
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model = LeNet().to(device)
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(model.parameters(), lr=0.01, momentum=0.9)
for epoch in range(10):
model.train()
for images, labels in train_loader:
images, labels = images.to(device), labels.to(device)
optimizer.zero_grad()
outputs = model(images)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
print(f"[{epoch+1}] loss:{loss}")
# 测试模型
model.eval()
correct = 0
total = 0
with 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()
accuracy = 100 * correct / total
print('Test Accuracy: {:.2f}%'.format(accuracy))
上述代码首先定义了LeNet模型,包含两个卷积层、两个池化层、三个全连接层,并使用tanh和softmax作为激活函数。然后通过PyTorch的数据加载器准备MNIST数据集,并使用交叉熵损失和随机梯度下降优化算法训练模型。最后在测试集上评估模型的准确率。文章来源:https://www.toymoban.com/news/detail-836774.html
总结
LeNet模型是卷积神经网络领域的里程碑,为深度学习图像识别任务的发展做出了重要贡献。本文介绍了LeNet模型的数学原理、PyTorch的代码实现,并通过训练和测试模型展示了其在手写数字识别任务上的性能。文章来源地址https://www.toymoban.com/news/detail-836774.html
到了这里,关于计算机视觉初探--LeNet原理与实践的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!