1998年诞生的LeNet和2012年横空出世的AlexNet,是卷积神经网络发展史上两座重要的里程碑。作为初学者,理解这两个经典模型的架构差异,就像是拿到了打开深度学习大门的钥匙。我刚开始接触CNN时,最困惑的就是为什么AlexNet比LeNet强大这么多?直到亲手用PyTorch实现这两个模型后,才真正明白其中的设计奥秘。
LeNet最初是为手写数字识别设计的,它的结构非常简单:两个卷积层加上三个全连接层。而AlexNet在ImageNet竞赛中一战成名,深度达到8层,参数规模更是LeNet的数百倍。这种进化不是简单的堆叠,而是包含了激活函数、池化策略、正则化方法等多个维度的创新。下面我们就用PyTorch从零开始,一步步搭建这两个模型,看看它们的具体差异在哪里。
LeNet的结构就像是一个精心设计的流水线。我们先来看它的卷积部分:
python复制self.conv = nn.Sequential(
nn.Conv2d(1, 6, 5), # 输入通道1,输出通道6,5x5卷积核
nn.Sigmoid(),
nn.MaxPool2d(2, 2), # 2x2最大池化
nn.Conv2d(6, 16, 5),
nn.Sigmoid(),
nn.MaxPool2d(2, 2)
)
这个设计有几个关键点值得注意:
全连接部分的设计也很有时代特点:
python复制self.fc = nn.Sequential(
nn.Linear(256, 120),
nn.Sigmoid(),
nn.Linear(120, 84),
nn.Sigmoid(),
nn.Linear(84, 10)
)
全连接层之间全部使用Sigmoid激活,这在当时是标准做法。但实际训练时会发现,这种设计容易导致梯度消失问题,特别是当网络加深时。
用现代PyTorch训练LeNet时,有几个实用技巧:
python复制model = LeNet()
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
for epoch in range(10):
for images, labels in train_loader:
outputs = model(images)
loss = criterion(outputs, labels)
optimizer.zero_grad()
loss.backward()
optimizer.step()
我在MNIST数据集上测试时,LeNet能达到98%左右的准确率。虽然现在看来不算高,但在90年代这已经是突破性的成果了。
AlexNet的出现彻底改变了计算机视觉领域的格局。它的卷积部分设计明显复杂得多:
python复制self.conv = nn.Sequential(
nn.Conv2d(3, 96, kernel_size=11, stride=4), # 大跨度卷积
nn.ReLU(),
nn.MaxPool2d(kernel_size=3, stride=2),
nn.Conv2d(96, 256, kernel_size=5, padding=2),
nn.ReLU(),
nn.MaxPool2d(kernel_size=3, stride=2),
nn.Conv2d(256, 384, kernel_size=3, padding=1),
nn.ReLU(),
nn.Conv2d(384, 384, kernel_size=3, padding=1),
nn.ReLU(),
nn.Conv2d(384, 256, kernel_size=3, padding=1),
nn.ReLU(),
nn.MaxPool2d(kernel_size=3, stride=2)
)
与LeNet相比,AlexNet的创新点包括:
AlexNet的全连接层也很有特色:
python复制self.fc = nn.Sequential(
nn.Linear(6400, 4096),
nn.ReLU(),
nn.Dropout(0.5),
nn.Linear(4096, 4096),
nn.ReLU(),
nn.Dropout(0.5),
nn.Linear(4096, 1000)
)
这里有两个革命性的设计:
在实际编码时,我发现AlexNet对输入尺寸有严格要求(224x224)。如果输入不符合要求,可以通过添加自适应池化层来解决:
python复制self.adapt_pool = nn.AdaptiveAvgPool2d((6,6))
为了直观展示两个模型的差异,我在CIFAR-10数据集上做了对比实验:
| 指标 | LeNet | AlexNet |
|---|---|---|
| 参数量 | 60K | 60M |
| 训练时间/epoch | 45s | 8min |
| 测试准确率 | 68.2% | 82.7% |
| 内存占用 | 150MB | 1.2GB |
从结果可以看出,AlexNet的准确率优势明显,但资源消耗也大幅增加。这印证了深度学习中的一个重要trade-off:性能提升往往以计算资源为代价。
通过控制变量实验,可以验证各个创新点的实际效果:
激活函数对比:
池化策略对比:
Dropout的影响:
这些实验数据生动地展示了AlexNet各项设计的实际价值。
虽然现在看LeNet和AlexNet已经有些"古老",但它们的设计思想至今仍在影响CNN的发展。比如:
我在实际项目中发现,理解这些经典模型的设计思路,对调参和模型改进非常有帮助。比如当遇到梯度消失问题时,会自然想到尝试ReLU;当过拟合严重时,会考虑增加Dropout。
建议初学者不要只满足于跑通代码,而是要多思考:为什么这里用5x5卷积?为什么那里要加Dropout?这种思考方式比单纯记忆模型结构要有价值得多。