Skip to content

LeNet

一、LeNet 的背景

LeNet 是最早的卷积神经网络之一,是 AT&T 贝尔实验室的 Yann LeCun 在 1989 年提出的,专门用来识别图像里的手写数字。在当时,它的性能和支持向量机差不多,成为了监督学习的主流方法,还被用在 ATM 机里识别支票上的数字,现在有些 ATM 机还在运行当时的代码呢!

LeNet 模型结构

LeNet中的数据流。输入是手写数字,输出为10种可能结果的概率。

二、LeNet 的模型结构

LeNet-5 分成两个部分:卷积编码器全连接密集块,就像一个流水线,先提取图像的特征,再把特征分类。

1. 卷积编码器:提取图像特征

卷积编码器有两个卷积块,每个卷积块的组成是:卷积层 + Sigmoid 激活函数 + 平均池化层。

  • 卷积层:就像一个 "特征探测器",用 5×5 的卷积核在图像上滑动,提取图像的特征,比如边缘、纹理这些。第一个卷积层会把输入的 1 通道(黑白图像)变成 6 通道的特征图,第二个卷积层把 6 通道变成 16 通道,通道越多,提取的特征越丰富。

  • Sigmoid 激活函数:让模型能学习非线性的特征,就像给模型加了 "灵活性",能处理更复杂的图像。

  • 平均池化层:用 2×2 的窗口,步幅是 2,把特征图的大小缩小一半,这样能减少计算量,还能让特征更稳定。

比如输入是 28×28 的黑白图像,经过第一个卷积层和池化层后,变成 14×14 的 6 通道特征图;经过第二个卷积层和池化层后,变成 5×5 的 16 通道特征图。

2. 全连接密集块:分类特征

全连接密集块有三个全连接层,作用是把提取到的特征转换成分类结果:

  • 首先把 5×5×16 的特征图展平成一个 400 维的向量(5×5×16=400)。
  • 然后经过第一个全连接层,把 400 维变成 120 维,再经过 Sigmoid 激活。
  • 再经过第二个全连接层,把 120 维变成 84 维,再经过 Sigmoid 激活。
  • 最后经过第三个全连接层,把 84 维变成 10 维,对应 10 个数字类别(0-9)。

LeNet 模型结构

三、PyTorch 实现 LeNet

我们可以用 PyTorch 的 Sequential 来快速搭建 LeNet 模型:

python
import torch
from torch import nn

# 定义LeNet模型
class LeNet(nn.Module):
    def __init__(self):
        super().__init__()
        self.model = nn.Sequential(
            # 第一层:卷积层 + Sigmoid + 平均池化
            nn.Conv2d(1, 6, kernel_size=5, padding=2), nn.Sigmoid(),
            nn.AvgPool2d(kernel_size=2, stride=2),
            # 第二层:卷积层 + Sigmoid + 平均池化
            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, x):
        return self.model(x)

# 测试模型的输出形状
net = LeNet()
X = torch.rand(size=(1, 1, 28, 28))  # 输入是1张28×28的黑白图像
for layer in net.model:
    X = layer(X)
print(layer.__class__.__name__, 'output shape:\t', X.shape)

运行这段代码,我们可以看到每一层的输出形状变化:

  • 经过第一个卷积层和 Sigmoid,输出是torch.Size([1, 6, 28, 28])
  • 经过平均池化,输出是torch.Size([1, 6, 14, 14])
  • 经过第二个卷积层和 Sigmoid,输出是torch.Size([1, 16, 10, 10])
  • 经过平均池化,输出是torch.Size([1, 16, 5, 5])
  • 展平后是torch.Size([1, 400])
  • 经过第一个全连接层,输出是torch.Size([1, 120])
  • 经过第二个全连接层,输出是torch.Size([1, 84])
  • 最后输出是torch.Size([1, 10]),对应 10 个类别的概率。

四、训练 LeNet

我们用 Fashion-MNIST 数据集来训练 LeNet,这个数据集是 10 类服装的图像,和手写数字的图像大小一样,都是 28×28 的黑白图像。

1. 训练流程

  1. 初始化模型的权重,让模型从一个合适的状态开始训练。

  2. 把模型放到 GPU 上训练(如果有 GPU 的话),这样速度会更快。

  3. 用交叉熵损失函数来衡量模型的预测和真实标签的差距,用随机梯度下降(SGD)来优化模型的参数。

  4. 训练多个轮次,每一轮都用训练集更新模型参数,然后用测试集评估模型的准确率。

2. 训练结果

训练 20 轮后,模型的训练准确率大概能到 0.88 左右,测试准确率大概能到 0.87 左右,对于这么早期的模型来说,这个效果已经很不错了。

五、小结

  1. LeNet 是最早的卷积神经网络,分成卷积编码器和全连接密集块,先提取特征再分类。

  2. 卷积层用来提取图像的特征,池化层用来缩小特征图的大小,全连接层用来分类。

  3. LeNet 的结构很简单,但它的思路影响了后来的卷积神经网络,比如 ResNet、VGG 这些模型都是在它的基础上发展来的。

(注:文档部分内容可能由 AI 生成) 源地址

京ICP备2024093538号-1