【深度学习|学习笔记】卷积神经网络LeNet的起源、原理、演化、优缺点详解!附可直接运行的 PyTorch 代码。
【深度学习|学习笔记】卷积神经网络LeNet的起源、原理、演化、优缺点详解!附可直接运行的 PyTorch 代码。
·
【深度学习|学习笔记】卷积神经网络LeNet的起源、原理、演化、优缺点详解!附可直接运行的 PyTorch 代码。
【深度学习|学习笔记】卷积神经网络LeNet的起源、原理、演化、优缺点详解!附可直接运行的 PyTorch 代码。
文章目录
欢迎铁子们点赞、关注、收藏!
祝大家逢考必过!逢投必中!上岸上岸上岸!upupup
大多数高校硕博生毕业要求需要参加学术会议,发表EI或者SCI检索的学术论文会议论文。详细信息可扫描博文下方二维码 “
学术会议小灵通”或参考学术信息专栏:https://blog.csdn.net/2401_89898861/article/details/148877490
一、经典卷积分类网络的通用结构(从机器学习范式看)
- 目标:学一个从图像 x x x 到类别 y y y 的判别函数 f θ ( x ) f_θ(x) fθ(x)。
- 基本骨架:
[卷积(Conv) → 非线性(Act) → 归一化(Norm) → 下采样(Pool/Stride)] × L → 全局聚合(GAP/FC) → Softmax。
动机来自机器学习的两条主线:
- 归纳偏置:局部连接 + 权值共享(CNN)将先验“局部相关、平移等变”写进模型,减少参数、降过拟合。
- 分层表示学习:从边缘/角点(浅层)到部件/语义(深层),逐层抽象,避免手工特征。
代表性里程碑(分类方向):LeNet-5 (1998) → AlexNet (2012) → VGG (2014) → GoogLeNet/Inception (2014) → ResNet (2015) → EfficientNet/ConvNeXt 等。下面聚焦 LeNet 的来龙去脉。
二、LeNet 的起源与历史脉络
- 起源:Yann LeCun 团队在 1989–1998 年间提出的卷积网络家族(LeNet-1/4/5),面向手写数字识别(银行支票、USPS/MNIST)。
- 关键技术融合:反向传播(80s)+ 卷积/子采样 + 端到端训练 +(当时)有限的数据增强和先验。
- 代表作:LeNet-5(1998)——论文《Gradient-Based Learning Applied to Document Recognition》(LeCun, Bottou, Bengio, Haffner)。
三、LeNet-5 的原理与结构细节
- 经典输入是 32 × 32 32×32 32×32 灰度图(MNIST 原图 28 × 28 28×28 28×28 会先零填充到 32 × 32 32×32 32×32)。
层级结构(原版记号:C=Conv,S=Subsampling/Pooling,F=全连接)
- C1:Conv 5 × 5 5×5 5×5, 输入 1 通道 → 输出 6 通道,尺寸 32 → 28 32→28 32→28。
- S2:Average Pool 2 × 2 2×2 2×2(带可学习系数), 6 × 14 × 14 6×14×14 6×14×14。
- C3:Conv 5 × 5 5×5 5×5,输出 16 通道,尺寸 14 → 10 14→10 14→10。注意部分连接表(非每个输入通道都连到每个输出通道)以打破对称性、降参。
- S4:Average Pool 2 × 2 2×2 2×2, 16 × 5 × 5 16×5×5 16×5×5。
- C5:Conv 5 × 5 5×5 5×5(在 5 × 5 5×5 5×5 上相当于 全连接到 120 维),输出 120。
- F6:全连接 120 → 84(配合 tanh 非线性)。
- 输出:84 → 10(分类),Softmax。
激活/归一化:历史版本用 tanh/sigmoid,无 BatchNorm;子采样是 平均池化(带可训练缩放/偏置)。
损失:多分类交叉熵(原文中也有使用高斯径向基与不同输出层变体的讨论)。
四、LeNet 的发展与影响
- 从 LeNet 到 AlexNet:LeNet 证明“端到端卷积 + 共享权重 + 子采样”有效,但受算力/数据限制;2012 年AlexNet 用 ReLU、Dropout、数据增强、GPU 并行 把 CNN 推向大规模 ImageNet。
- 后续演化:VGG 用小卷积堆叠、Inception 用多尺度分支、ResNet 用残差连接(解决退化/梯度消失),形成现代 CNN 族谱。
- 在小数据/灰度识别上,LeNet 仍是轻量基准;在教学与工业嵌入式原型中常用作基线。
五、优缺点一览
优点
- 强归纳偏置:局部连接/共享权重显著减少参数,泛化好。
- 平移稳健:子采样(平均池化)引入一定程度的平移不变性。
- 端到端:无需手工特征,统一用梯度下降训练。
- 轻量:参数/算力小,适合入门与小规模任务。
缺点
- 激活饱和:tanh/sigmoid 易梯度消失;无 BN,收敛慢。
- 平均池化信息损失:细节被平滑,分类边界可能变钝。
- 结构浅/容量有限:对复杂/大规模数据表达力不足。
- 连接表复杂:C3 的部分连接在现代实现中不常保留(改成全连接更简洁)。
因此现代常用“LeNet-like”改造:ReLU/SiLU + BatchNorm + MaxPool,去掉连接表,训练稳定、精度更高。
六、PyTorch 实现(原版风格 & 现代化 LeNet)
6.1 原版风格(tanh + AvgPool,简化为 C3 全连接以便实现)
import torch
import torch.nn as nn
import torch.nn.functional as F
class LeNet5Classic(nn.Module):
def __init__(self, num_classes=10):
super().__init__()
# C1: 1x32x32 -> 6x28x28
self.c1 = nn.Conv2d(1, 6, kernel_size=5, stride=1, padding=0)
# S2: 6x28x28 -> 6x14x14 (AvgPool with learnable scale is simplified to AvgPool)
self.s2 = nn.AvgPool2d(kernel_size=2, stride=2)
# C3: 6x14x14 -> 16x10x10 (we use full connection among channels for simplicity)
self.c3 = nn.Conv2d(6, 16, kernel_size=5, stride=1, padding=0)
# S4: 16x10x10 -> 16x5x5
self.s4 = nn.AvgPool2d(kernel_size=2, stride=2)
# C5: 16x5x5 -> 120x1x1 (conv as FC)
self.c5 = nn.Conv2d(16, 120, kernel_size=5, stride=1, padding=0)
# F6: 120 -> 84
self.f6 = nn.Linear(120, 84)
# Output: 84 -> num_classes
self.out = nn.Linear(84, num_classes)
def forward(self, x):
x = torch.tanh(self.c1(x))
x = self.s2(x)
x = torch.tanh(self.c3(x))
x = self.s4(x)
x = torch.tanh(self.c5(x)) # [N,120,1,1]
x = x.view(x.size(0), -1) # [N,120]
x = torch.tanh(self.f6(x)) # [N,84]
logits = self.out(x) # [N,C]
return logits
六、PyTorch 实现(原版风格 & 现代化 LeNet)
6.2 现代化 LeNet(ReLU + BN + MaxPool,训练更稳)
class LeNet5Modern(nn.Module):
def __init__(self, num_classes=10):
super().__init__()
self.conv1 = nn.Sequential(
nn.Conv2d(1, 6, 5, 1, 0, bias=False), nn.BatchNorm2d(6), nn.ReLU(inplace=True),
nn.MaxPool2d(2) # 32->28->14
)
self.conv2 = nn.Sequential(
nn.Conv2d(6, 16, 5, 1, 0, bias=False), nn.BatchNorm2d(16), nn.ReLU(inplace=True),
nn.MaxPool2d(2) # 14->10->5
)
self.fc1 = nn.Sequential(nn.Linear(16*5*5, 120), nn.ReLU(inplace=True))
self.fc2 = nn.Sequential(nn.Linear(120, 84), nn.ReLU(inplace=True))
self.out = nn.Linear(84, num_classes)
def forward(self, x):
x = self.conv1(x)
x = self.conv2(x)
x = x.flatten(1)
x = self.fc1(x)
x = self.fc2(x)
return self.out(x)
6.3 训练脚手架(MNIST 为例;可替换为你的数据)
import torch, torch.nn as nn
from torch.utils.data import DataLoader
# 若有 torchvision 可用:
# from torchvision import datasets, transforms
def train_one_epoch(model, loader, optimizer, device='cuda'):
model.train()
ce = nn.CrossEntropyLoss()
total, correct, total_loss = 0, 0, 0.0
for x, y in loader:
x, y = x.to(device), y.to(device)
logits = model(x)
loss = ce(logits, y)
optimizer.zero_grad(); loss.backward(); optimizer.step()
total_loss += loss.item() * x.size(0)
correct += (logits.argmax(1) == y).sum().item()
total += x.size(0)
return total_loss/total, correct/total
@torch.no_grad()
def evaluate(model, loader, device='cuda'):
model.eval()
total, correct = 0, 0
for x, y in loader:
x, y = x.to(device), y.to(device)
pred = model(x).argmax(1)
correct += (pred == y).sum().item()
total += x.size(0)
return correct/total
# 你可以把 DataLoader 换成自己的;例如(需要 torchvision):
# tfm = transforms.Compose([transforms.Pad(2), transforms.ToTensor()])
# trainset = datasets.MNIST(root='./data', train=True, download=True, transform=tfm)
# testset = datasets.MNIST(root='./data', train=False, download=True, transform=tfm)
# train_loader = DataLoader(trainset, batch_size=128, shuffle=True, num_workers=2)
# test_loader = DataLoader(testset, batch_size=256, shuffle=False, num_workers=2)
# model = LeNet5Modern().to('cuda'); opt = torch.optim.AdamW(model.parameters(), lr=1e-3)
# for ep in range(10):
# tl, ta = train_one_epoch(model, train_loader, opt, 'cuda')
# va = evaluate(model, test_loader, 'cuda')
# print(f"Epoch {ep+1}: loss={tl:.4f}, train_acc={ta:.3f}, test_acc={va:.3f}")
七、与现代 CNN 的结构对比要点(有助于理解“为什么 LeNet 如此设计”)
- 非线性:tanh → ReLU/SiLU(缓解梯度消失、收敛快)。
- 池化:Average → Max/Strided Conv(保边缘/纹理)。
- 归一化:无 → BatchNorm/GroupNorm(稳定训练)。
- 深度与可达性:浅层 + 无残差 → 深层 + 残差/跨层连接(优化更易)。
- 大规模训练:小数据/CPU → 大数据 + GPU/分布式、数据增强/正则(Label Smoothing、Mixup/CutMix、EMA 等)。
八、小结
- LeNet 把“卷积 + 子采样 + 端到端”首次系统用于视觉分类,开了 CNN 之先河。
- 作为教学/基线它依然实用;但在真实复杂任务上,建议使用现代化改造(ReLU+BN+MaxPool 或更先进骨干),再配合现代训练“配方”(Cosine LR、数据增广、蒸馏/正则),能显著提升精度与稳定性。
更多推荐
所有评论(0)