7.2.1 VGG块
考虑一下这个问题如何回答。想一下我们可能的选项如下
于是VGG就采用了最后一个选项
那么为什么不用
最后全连接层那个地方,VGG跟
可以看下各种网络的对比,如下
横轴是计算速度,纵轴是准确率。可以看到,同一个网络架构(比如都是VGG)有不同的表现,跑得快的准确率低,跑得慢的准确率高(不同的卷积块个数和超参数可以得到不同复杂度的变种)
在vgg_block
函数中,不需要更新out_channels
,原因如下:
1. VGG块的设计原则
VGG的核心思想是:在同一块内,所有卷积层的输出通道数保持一致。例如:
- 若定义
vgg_block(num_convs=2, in_channels=3, out_channels=64)
,块内会连续堆叠两个3×3卷积层,每个卷积层的输出通道均为64。 - 第一个卷积层将输入通道从3变为64,第二个卷积层保持输入和输出通道均为64(通过更新
in_channels = out_channels
实现)。
这种设计让块内的所有卷积层共享相同的通道数,简化参数管理,同时通过堆叠多个小卷积核(3×3)来模拟更大感受野(等效于5×5或7×7)。
2. 代码逻辑分析
for _ in range(num_convs):
# 添加卷积层:输入通道为当前in_channels,输出通道固定为out_channels
layers.append(nn.Conv2d(in_channels, out_channels, kernel_size=3, padding=1))
layers.append(nn.ReLU())
# 更新输入通道为当前块的输出通道(保证下一层的输入与当前输出一致)
in_channels = out_channels
- 不更新
out_channels
:因为块内所有卷积层的目标是保持输出通道数一致(由out_channels
参数指定),只有输入通道数(in_channels
)需要逐层更新。 - 最终效果:无论
num_convs
是多少,块的输出通道数始终为初始的out_channels
值。例如,num_convs=3
时,块的输出通道数仍为初始设定的值(如64)。
3. 对比其他网络结构
- AlexNet/ResNet:不同阶段的块会逐步增加通道数(如64→128→256),但这是在跨块时通过手动调整
out_channels
实现的。 - VGG:通过固定块内通道数,仅在跨块时通过池化层后手动调整通道数(例如,下一个块的
in_channels
设为当前块的out_channels
,out_channels
设为更大的值)。
示例说明
假设定义两个连续的VGG块:
block1 = vgg_block(num_convs=2, in_channels=3, out_channels=64) # 输出通道64
block2 = vgg_block(num_convs=2, in_channels=64, out_channels=128) # 输出通道128
- 块内:每个块内部的卷积层输出通道数固定(如第一个块固定为64)。
- 跨块:通过手动指定下一个块的
in_channels
和out_channels
来增加通道数(如64→128),这是VGG的分阶段特征提取策略。
总结
不更新out_channels
是因为VGG块的设计要求同一块内的所有卷积层保持相同的输出通道数,而通道数的增加是通过跨块时手动调整参数实现的。这种设计保证了块内结构的简洁性和一致性,符合VGG“通过堆叠相同配置的块构建深度网络”的核心思想。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
2024-02-21 Fractal Origami
2024-02-21 Did We Get Everything Covered?
2024-02-21 We Got Everything Covered!
2024-02-21 Permutation of Given
2024-02-21 ace5 and Task Order