经典模型纵览:LeNet 到 ResNet
本教程共 60 篇 · 第 24 篇 · 更新于 2026-08-17 · 约 2 分钟阅读
本节目标:沿着时间线认识五个里程碑式的卷积网络——LeNet、AlexNet、VGG、GoogLeNet、ResNet,理解它们各自解决了什么问题,并学会从
torchvision里直接调用预训练模型。
把 CNN 的发展史看一遍,你会发现一条主线:网络越做越深,效果越来越好。而每个经典模型,都踩平了一个「变深」路上的坑。
LeNet-5(1998):祖师爷
LeNet 由 Yann LeCun 提出,用来识别手写数字(MNIST)。它奠定了 CNN 的标准范式:卷积提特征、池化降尺寸、全连接分类。
结构很小:2 个卷积层加 3 个全连接层,参数量约 6 万。这个「卷积-池化-全连接」三段式,直到今天还是教科书级的骨架。第 21 章我们搭的小网络,就是它的现代简化版。
AlexNet(2012):深度学习元年
2012 年,AlexNet 在 ImageNet 大赛上一鸣惊人,把 top-5 错误率从上一年的约 26% 拉到 15.3%。深度学习从此成为主流。
它带来三个改变:用 ReLU 替代 sigmoid,训练快了好几倍;用 Dropout 和数据增强防过拟合;用两块 GPU 并行训练,让更大的模型成为可能。8 层结构,参数量约 6000 万。
VGG(2014):越深越好
VGG 的贡献可以浓缩成一句话:把 3×3 的小卷积反复堆,堆出深度。
两个 3×3 卷积的感受野等于一个 5×5,三个等于一个 7×7,但参数更少、非线性更强。VGG16 有 16 层,参数量约 1.38 亿。它证明了深度就是生产力,而且结构极度规整,成了后来模型的标准参照。
GoogLeNet(2014):又深又省
同一年,GoogLeNet(也叫 Inception v1)换了个思路:不堆深度,改加宽度。它设计了 Inception 模块,同一层里并行放多种尺寸的卷积核,让网络自己挑。
点睛之笔是 1×1 卷积:在保持空间尺寸的同时压缩通道数,参数大幅削减。22 层深的 GoogLeNet,参数量只有约 680 万,是 VGG16 的二十分之一。
ResNet(2015):152 层怎么训
按 VGG 的思路继续加深,问题来了:层数超过一定限度,网络不升反降。连训练集误差都变高,说明不是过拟合,是网络本身训不动了。研究者叫它退化问题。
何恺明团队的 ResNet 给出答案:残差连接(Residual Connection)。每两层之间加一条「抄近道」,输出 = 卷积结果 + 原输入。梯度能沿着近道直接回流,深层网络终于训得动了。
import torch
import torch.nn as nn
class ResidualBlock(nn.Module):
"""最简残差块:两个卷积层加一条短路连接"""
def __init__(self, channels):
super().__init__()
self.conv1 = nn.Conv2d(channels, channels, 3, padding=1)
self.bn1 = nn.BatchNorm2d(channels)
self.conv2 = nn.Conv2d(channels, channels, 3, padding=1)
self.bn2 = nn.BatchNorm2d(channels)
self.relu = nn.ReLU()
def forward(self, x):
identity = x # 抄近道,原样留一份
out = self.relu(self.bn1(self.conv1(x)))
out = self.bn2(self.conv2(out))
return self.relu(out + identity) # 加起来再激活
block = ResidualBlock(channels=16)
x = torch.randn(2, 16, 32, 32)
print(block(x).shape) # torch.Size([2, 16, 32, 32]),尺寸不变
ResNet 一口气做到 152 层,拿下 2015 年 ImageNet 冠军,top-5 错误率 3.57%,比人类标注的水平还低。它配套的批归一化(BatchNorm)也成了此后网络的标配。
Note残差连接要求输入输出形状一致,所以残差块里的卷积都要用 padding 保持尺寸。这也是上面代码里
padding=1的原因。
直接调用预训练模型
这些模型不用自己从头实现。torchvision 把主流模型都打包好了,还附赠 ImageNet 预训练权重:
import torch
from torchvision import models
print(models.list_models()[:10]) # 看看模型库都有啥
# 加载带预训练权重的 ResNet18
resnet18 = models.resnet18(weights=models.ResNet18_Weights.DEFAULT)
resnet18.eval()
x = torch.randn(1, 3, 224, 224)
with torch.no_grad():
out = resnet18(x)
print(out.shape) # torch.Size([1, 1000]),ImageNet 的 1000 类得分
Note加载权重需要联网,首次会下载约 45MB 的文件。不想要预训练权重,把
weights参数去掉,得到的就是随机初始化的空结构。
怎么选型
- 入门学习:LeNet 或第 21 章的小网络,几分钟跑通。
- 小任务、资源紧张:MobileNet 系列,为移动端设计。
- 快速见效:ResNet18/34,轻量又够用。
- 精度优先:ResNet50/101,工业界常见选择。
记住这条主线:LeNet 立规矩,AlexNet 掀革命,VGG 证深度,GoogLeNet 求效率,ResNet 破深度极限。看懂这五个模型,图像分类的来龙去脉就通了。