1. 引言
深度学习的模型设计从最初关注单个神经元,逐步发展到以“层”为单位,现在进一步抽象为“块”的概念。VGG网络由牛津大学视觉几何组提出,它通过模块化的方式设计神经网络,使得网络结构清晰、简单且具有复用性。本文将以浅显易懂的方式带你理解VGG网络的设计与实现。
2. VGG块:网络的基本构件
2.1 VGG块的定义
一个典型的VGG块包含以下组成部分:
- 多个卷积层:使用固定大小的卷积核(通常为 ),并通过填充保持输出尺寸不变。
- ReLU激活函数:为网络增加非线性。
- 最大池化层:用于空间下采样,将特征图的宽和高减半。
在代码中,VGG块可以通过以下函数实现:
import torch
from torch import nn
def vgg_block(num_convs, in_channels, out_channels):
"""
定义一个VGG块,由若干个卷积层和一个最大池化层组成。
参数:
- num_convs (int): 当前块中卷积层的数量。
- in_channels (int): 输入特征图的通道数。
- out_channels (int): 输出特征图的通道数。
返回:
- nn.Sequential: 包含所有卷积层和池化层的顺序容器。
"""
layers = []
for _ in range(num_convs):
layers.append(nn.Conv2d(in_channels, out_channels, kernel_size=3, padding=1))
layers.append(nn.ReLU())
in_channels = out_channels
layers.append(nn.MaxPool2d(kernel_size=2, stride=2))
return nn.Sequential(*layers)
2.2 数学公式
- 卷积层的输出大小计算公式:
- :输入特征图的高度和宽度;
- :卷积核大小;
- :填充大小;
- :步幅。
- 最大池化层的输出大小公式:
3. VGG网络结构设计
3.1 整体架构
VGG网络由两部分组成:
- 卷积部分:包含若干个VGG块,用于特征提取。
- 全连接部分:将提取的特征展平后输入到全连接层进行分类。
代码实现:
def vgg(conv_arch):
"""
定义VGG网络,由多个卷积块和全连接层组成。
参数:
- conv_arch (list): VGG块的配置列表,其中每个元素是一个元组,格式为
(num_convs, out_channels),表示卷积块中卷积层的数量和输出通道数。
返回:
- nn.Sequential: 包含卷积块和全连接层的顺序容器。
"""
conv_blks = []
in_channels = 1 # 假设输入为单通道灰度图(例如Fashion-MNIST)
# 构造卷积块部分
for num_convs, out_channels in conv_arch:
conv_blks.append(vgg_block(num_convs, in_channels, out_channels))
in_channels = out_channels # 更新输入通道数为当前块的输出通道数
# 构造全连接层部分
return nn.Sequential(
*conv_blks, # 卷积块
nn.Flatten(),
nn.Linear(in_channels * 7 * 7, 4096),
nn.ReLU(),
nn.Dropout(0.5),
nn.Linear(4096, 4096),
nn.ReLU(),
nn.Dropout(0.5),
nn.Linear(4096, 10)
)
# 定义VGG-11的架构
conv_arch = [(1, 64), (1, 128), (2, 256), (2, 512), (2, 512)]
net = vgg(conv_arch)
3.2 输出形状分析
我们以输入为 的单通道图像为例,查看每一层的输出形状:
# 测试VGG网络的输出形状
X = torch.randn(size=(1, 1, 224, 224)) # 假设输入为 224x224 的单通道图像
for blk in net:
X = blk(X)
print(f"{blk.__class__.__name__} output shape: {X.shape}")
Sequential output shape: torch.Size([1, 64, 112, 112])
Sequential output shape: torch.Size([1, 128, 56, 56])
Sequential output shape: torch.Size([1, 256, 28, 28])
Sequential output shape: torch.Size([1, 512, 14, 14])
Sequential output shape: torch.Size([1, 512, 7, 7])
Flatten output shape: torch.Size([1, 25088])
Linear output shape: torch.Size([1, 4096])
ReLU output shape: torch.Size([1, 4096])
Dropout output shape: torch.Size([1, 4096])
Linear output shape: torch.Size([1, 4096])
ReLU output shape: torch.Size([1, 4096])
Dropout output shape: torch.Size([1, 4096])
Linear output shape: torch.Size([1, 10])
4. 模型训练与测试
4.1 数据集准备
我们使用 Fashion-MNIST 数据集,并将图片尺寸调整为 :
batch_size = 128
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size, resize=224)
4.2 模型训练
为了减少计算量,缩小通道数比例:
ratio = 4
small_conv_arch = [(pair[0], pair[1] // ratio) for pair in conv_arch]
net = vgg(small_conv_arch)
lr, num_epochs = 0.05, 10
d2l.train_ch6(net, train_iter, test_iter, num_epochs, lr, d2l.try_gpu())
5. 总结
- VGG网络通过模块化设计实现了简单高效的网络构建。
- 重复使用卷积块的设计思想在深度学习领域具有重要的启发性。
- VGG的尝试证明了深层、窄卷积网络的优越性,为后续网络的设计提供了重要参考。
VGG的理念体现了现代神经网络设计中的“简单即美”的原则,为深度学习的发展打下了坚实基础。