使用块的网络 (VGG)
探索VGG网络的模块化设计理念,理解块结构在深度网络中的重要作用和实现方法

展开文章目录
1. VGG 网络的设计理念
AlexNet 首次证明了模型能自动学习特征的能力,但这一突破并没有为后续的研究提供用于构建新网络的模板。
2. VGG 网络架构
2.1 VGG 块设计
VGG 块是VGG网络的核心构建单元,具有统一而简洁的设计模式:
VGG 块的实现
import torch
from torch import Tensor, nn
class VGGBlock(nn.Module):
"""
VGG 块
由两层使用 ReLU 激活函数的 3×3 卷积层,后接一个 2×2 步幅为 2 的最大池化层组成
"""
def __init__(self, in_channels: int, out_channels: int):
super(VGGBlock, self).__init__()
self.block = nn.Sequential(
# 第一个3×3卷积层
nn.Conv2d(in_channels, out_channels, kernel_size=3, padding=1),
nn.ReLU(inplace=True),
# 第二个3×3卷积层
nn.Conv2d(out_channels, out_channels, kernel_size=3, padding=1),
nn.ReLU(inplace=True),
# 2×2最大池化层
nn.MaxPool2d(kernel_size=2, stride=2)
)
def forward(self, x: Tensor) -> Tensor:
return self.block(x)
2.2 完整的 VGG11 网络
与 AlexNet、LeNet 类似,VGG 网络同样由卷积层、汇聚层组成的特征提取模块和由全连接层组成的分类模块组成。
VGG11 网络实现
class VGG11(nn.Module):
"""VGG11 网络实现"""
def __init__(self, num_classes: int = 10):
super(VGG11, self).__init__()
# 特征提取器 - 由5个VGG块组成
self.features = nn.Sequential(
VGGBlock(1, 16), # 输入: 224×224×1 -> 输出: 112×112×16
VGGBlock(16, 32), # 输入: 112×112×16 -> 输出: 56×56×32
VGGBlock(32, 64), # 输入: 56×56×32 -> 输出: 28×28×64
VGGBlock(64, 128), # 输入: 28×28×64 -> 输出: 14×14×128
VGGBlock(128, 128), # 输入: 14×14×128 -> 输出: 7×7×128
)
# 分类器 - 由全连接层组成
self.classifier = nn.Sequential(
nn.Dropout(0.5),
nn.Linear(7 * 7 * 128, 4096),
nn.ReLU(inplace=True),
nn.Dropout(0.5),
nn.Linear(4096, 4096),
nn.ReLU(inplace=True),
nn.Linear(4096, num_classes)
)
def forward(self, x: Tensor) -> Tensor:
# 特征提取
x = self.features(x)
# 展平特征图
x = torch.flatten(x, 1)
# 分类
x = self.classifier(x)
return x
/1735111445040-6337b7a4-bea7-4e4e-9647-c69d52882174.png)
2.3 网络结构分析
使用 torchinfo 库的 summary 函数来详细分析网络结构:
from torchinfo import summary
# 创建模型并分析
model = VGG11(num_classes=10)
summary(model, input_size=(1, 1, 224, 224))
查看详细网络结构信息
==========================================================================================
Layer (type:depth-idx) Output Shape Param #
==========================================================================================
VGG11 [1, 10] --
├─Sequential: 1-1 [1, 128, 7, 7] --
│ └─VGGBlock: 2-1 [1, 16, 112, 112] --
│ │ └─Sequential: 3-1 [1, 16, 112, 112] 2,480
│ └─VGGBlock: 2-2 [1, 32, 56, 56] --
│ │ └─Sequential: 3-2 [1, 32, 56, 56] 13,888
│ └─VGGBlock: 2-3 [1, 64, 28, 28] --
│ │ └─Sequential: 3-3 [1, 64, 28, 28] 55,424
│ └─VGGBlock: 2-4 [1, 128, 14, 14] --
│ │ └─Sequential: 3-4 [1, 128, 14, 14] 221,440
│ └─VGGBlock: 2-5 [1, 128, 7, 7] --
│ │ └─Sequential: 3-5 [1, 128, 7, 7] 295,168
├─Sequential: 1-2 [1, 10] --
│ └─Dropout: 2-6 [1, 6272] --
│ └─Linear: 2-7 [1, 4096] 25,694,208
│ └─ReLU: 2-8 [1, 4096] --
│ └─Dropout: 2-9 [1, 4096] --
│ └─Linear: 2-10 [1, 4096] 16,781,312
│ └─ReLU: 2-11 [1, 4096] --
│ └─Linear: 2-12 [1, 10] 40,970
==========================================================================================
Total params: 43,104,890
Trainable params: 43,104,890
Non-trainable params: 0
Total mult-adds (Units.MEGABYTES): 746.44
==========================================================================================
Input size (MB): 0.20
Forward/backward pass size (MB): 24.55
Params size (MB): 172.42
Estimated Total Size (MB): 197.17
==========================================================================================3. 模型训练与评估
3.1 训练配置
继续使用 training_tools.py 中的工具来训练和评估VGG11模型:
import torch
from torch import nn, optim
from training_tools import fashionMNIST_loader, Trainer
def train_vgg11():
"""训练VGG11模型"""
# 超参数设置
BATCH_SIZE = 128
EPOCHS = 15 # 减少训练轮数用于演示
LEARNING_RATE = 0.005 # 降低学习率以获得更稳定的训练
# 创建模型和数据加载器
model = VGG11(num_classes=10)
train_loader, test_loader = fashionMNIST_loader(BATCH_SIZE, resize=224)
# 损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=LEARNING_RATE, weight_decay=1e-4)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"使用设备: {device}")
print(f"模型参数数量: {sum(p.numel() for p in model.parameters()):,}")
# 开始训练
with Trainer(model, train_loader, test_loader, criterion, optimizer, device) as trainer:
trainer.train(EPOCHS)
if __name__ == '__main__':
train_vgg11()
3.2 训练结果分析
查看训练过程详细输出
使用设备: cuda
模型参数数量: 43,104,890
Epoch [ 1/15] Train Loss: 2.3027, Train Acc: 9.90%, Test Loss: 2.3026, Test Acc: 10.00%
Epoch [ 2/15] Train Loss: 2.3028, Train Acc: 9.85%, Test Loss: 2.3027, Test Acc: 10.00%
...
Epoch [ 12/15] Train Loss: 2.3027, Train Acc: 9.88%, Test Loss: 2.3025, Test Acc: 10.00%
Epoch [ 13/15] Train Loss: 2.3025, Train Acc: 10.22%, Test Loss: 2.3021, Test Acc: 10.00%
Epoch [ 14/15] Train Loss: 2.2864, Train Acc: 17.02%, Test Loss: 2.3021, Test Acc: 10.00%
Epoch [ 15/15] Train Loss: 1.6031, Train Acc: 38.25%, Test Loss: 0.6503, Test Acc: 74.66%
# 继续训练会看到快速提升:
Epoch [ 16/30] Train Loss: 0.5281, Train Acc: 80.15%, Test Loss: 0.4621, Test Acc: 83.29%
Epoch [ 20/30] Train Loss: 0.2704, Train Acc: 90.00%, Test Loss: 0.2714, Test Acc: 90.12%
Epoch [ 30/30] Train Loss: 0.1174, Train Acc: 95.60%, Test Loss: 0.2576, Test Acc: 92.31%/1735115597514-8f9ba437-f99c-4770-9bb8-be0f70e88709.png)
训练特点分析
VGG训练分析
训练过程的三个阶段:
- 停滞期(1-12轮):模型几乎没有学习到有用的特征,准确率徘徊在10%左右
- 突破期(13-21轮):模型开始学习有效特征,精度迅速提高
- 稳定期(22-30轮):训练精度稳定在约95%左右,测试精度稳定在92%左右
训练初期停滞的原因:
- 网络深度:VGG11相对较深,梯度传播困难
- 学习率设置:可能初始学习率不够合适
- 权重初始化:深层网络对初始化更加敏感
- 优化器选择:SGD相比Adam在深层网络上收敛较慢
改善训练的策略:
- 降低学习率并使用学习率衰减策略
- 使用Xavier或He权重初始化
- 采用Adam等自适应优化器
- 添加批归一化层加速收敛
- 使用预训练权重进行迁移学习
参考资料
如果这篇记录对你有帮助,可以留下一句回应。

DISCUSSION
讨论与回应
欢迎补充细节、指出问题,或分享与这篇文章有关的经验。
昵称与邮箱为必填项,邮箱仅用于头像和回复通知,不会公开。网址可以留空。