@BACKBONES.register_module()
class ResNet3d(nn.Module):
"""ResNet 3d backbone.
Args:
depth (int): Depth of resnet, from {18, 34, 50, 101, 152}. Default: 50.
pretrained (str | None): Name of pretrained model.
stage_blocks (tuple | None): Set number of stages for each res layer. Default: None.
pretrained2d (bool): Whether to load pretrained 2D model. Default: True.
in_channels (int): Channel num of input features. Default: 3.
base_channels (int): Channel num of stem output features. Default: 64.
out_indices (tuple[int]): Indices of output feature. Default: (3, ).
num_stages (int): Resnet stages. Default: 4.
spatial_strides (tuple[int]): Spatial strides of residual blocks of each stage. Default: (1, 2, 2, 2).
temporal_strides (tuple[int]): Temporal strides of residual blocks of each stage. Default: (1, 1, 1, 1).
conv1_kernel (tuple[int]): Kernel size of the first conv layer. Default: (3, 7, 7).
conv1_stride (tuple[int]): Stride of the first conv layer (temporal, spatial). Default: (1, 2).
pool1_stride (tuple[int]): Stride of the first pooling layer (temporal, spatial). Default: (1, 2).
advanced (bool): Flag indicating if an advanced design for downsample is adopted. Default: False.
frozen_stages (int): Stages to be frozen (all param fixed). -1 means not freezing any parameters. Default: -1.
inflate (tuple[int]): Inflate Dims of each block. Default: (1, 1, 1, 1).
inflate_style (str): '3x1x1' or '3x3x3'. which determines the kernel sizes and padding strides
for conv1 and conv2 in each block. Default: '3x1x1'.
conv_cfg (dict): Config for conv layers. required keys are 'type'. Default: 'dict(type='Conv3d')'.
norm_cfg (dict): Config for norm layers. required keys are 'type' and 'requires_grad'.
Default: 'dict(type='BN3d', requires_grad=True)'.
act_cfg (dict): Config dict for activation layer. Default: 'dict(type='ReLU', inplace=True)'.
norm_eval (bool): Whether to set BN layers to eval mode, namely, freeze running stats (mean and var).
Default: False.
zero_init_residual (bool): Whether to use zero initialization for residual block. Default: True.
"""
arch_settings = {
18: (BasicBlock3d, (2, 2, 2, 2)),
34: (BasicBlock3d, (3, 4, 6, 3)),
50: (Bottleneck3d, (3, 4, 6, 3)),
101: (Bottleneck3d, (3, 4, 23, 3)),
152: (Bottleneck3d, (3, 8, 36, 3))
}
分析:这个代码定义了一个名为 ResNet3d 的 PyTorch 模块,它实现了 3D ResNet 的骨干网络
-
class ResNet3d(nn.Module):
定义了一个名为ResNet3d
的类,它继承自 PyTorch 的nn.Module
类,表示这是一个神经网络模块。 -
"""ResNet 3d backbone."""
这是一个文档字符串,描述了该模块的作用,即作为 3D ResNet 的骨干网络。 -
Args:
这是一个参数列表,定义了该模块可接受的各种参数。 -
arch_settings = {...}
这是一个字典,定义了不同深度的 ResNet3d 网络中使用的基础块的类型和每个阶段的块数。
总之,这个代码定义了一个可以用于 3D 视频处理的 ResNet 骨干网络,并提供了许多可配置的参数来满足不同的需求。
arch_settings = {
18: (BasicBlock3d, (2, 2, 2, 2)),
34: (BasicBlock3d, (3, 4, 6, 3)),
50: (Bottleneck3d, (3, 4, 6, 3)),
101: (Bottleneck3d, (3, 4, 23, 3)),
152: (Bottleneck3d, (3, 8, 36, 3))
}
详细解释一下这个 arch_settings
字典中的每一行:
-
18: (BasicBlock3d, (2, 2, 2, 2)),
- 当
depth
参数设置为 18 时,使用BasicBlock3d
作为基础块,每个阶段的块数为 (2, 2, 2, 2)。
- 当
-
34: (BasicBlock3d, (3, 4, 6, 3)),
- 当
depth
参数设置为 34 时,使用BasicBlock3d
作为基础块,每个阶段的块数为 (3, 4, 6, 3)。
- 当
-
50: (Bottleneck3d, (3, 4, 6, 3)),
- 当
depth
参数设置为 50 时,使用Bottleneck3d
作为基础块,每个阶段的块数为 (3, 4, 6, 3)。
- 当
-
101: (Bottleneck3d, (3, 4, 23, 3)),
- 当
depth
参数设置为 101 时,使用Bottleneck3d
作为基础块,每个阶段的块数为 (3, 4, 23, 3)。
- 当
-
152: (Bottleneck3d, (3, 8, 36, 3)),
- 当
depth
参数设置为 152 时,使用Bottleneck3d
作为基础块,每个阶段的块数为 (3, 8, 36, 3)。
- 当
这个字典提供了不同深度的 ResNet3d 网络的架构设置。当用户指定 depth
参数时,模块会根据这个字典中的对应信息来构建网络。
BasicBlock3d
和 Bottleneck3d
是 3D 版本的 ResNet 基础块,它们具有不同的结构。(2, 2, 2, 2)
这样的元组表示每个阶段的块数,决定了网络的深度。
总的来说,这个字典为不同深度的 ResNet3d 网络提供了标准的架构设置。
每个阶段的块数为 (2, 2, 2, 2)。四个数字什么意思呢?
这四个数字代表了 ResNet3d 网络中每个阶段的块数。
ResNet3d 网络由多个"阶段"组成,每个阶段包含多个基础块。这四个数字分别代表了每个阶段中包含的基础块数量:
- 第一个数字 (2) 表示网络的第一个阶段包含 2 个基础块。
- 第二个数字 (2) 表示网络的第二个阶段包含 2 个基础块。
- 第三个数字 (2) 表示网络的第三个阶段包含 2 个基础块。
- 第四个数字 (2) 表示网络的第四个阶段包含 2 个基础块。
所以对于 depth=18
的 ResNet3d 网络,它由 4 个阶段组成,每个阶段包含 2 个基础块,总共 2 + 2 + 2 + 2 = 8 个基础块。
这种设置可以让网络的深度和复杂度根据需求进行调整。更深的网络会有更多的阶段和基础块,从而能够学习到更复杂的特征。
总之,这四个数字描述了 ResNet3d 网络的"深度"和每个阶段的基础块数量,是决定网络复杂度的重要参数。
那既然是8个基础块为什么 depth=18?
尽管 ResNet3d 网络的第一到四个阶段共有 8 个基础块,但是 depth=18
并不意味着整个网络只有 18 层。
在 ResNet 架构中,每个基础块通常包含 2-3 个卷积层。因此,每个基础块实际上贡献了 2-3 个网络层。
对于 depth=18
的 ResNet3d 网络:
- 每个阶段有 2 个基础块
- 每个基础块有 2-3 个卷积层
- 所以第一个阶段有 2 * 2 = 4 层
- 第二到第四个阶段各有 2 * 2 = 4 层
- 再加上网络开始和结束的一些层
- 总共就构成了 18 层的 ResNet3d 网络
所以尽管基础块的数量为 8 个,但是整个网络的深度为 18 层,这就是 depth=18
的含义。
其他深度设置,如 depth=34
、depth=50
等,同样遵循这个规则,根据基础块的数量和每个基础块的层数来确定整个网络的深度。
总之,ResNet3d 网络的深度并不直接等于基础块的数量,而是根据一定的换算关系来确定的。
那Bottleneck3d什么意思呢?
Bottleneck3d
是 ResNet3D 网络中使用的一种特殊的基础块设计。
在标准的 ResNet 网络中,基础块通常由 2-3 个3x3的卷积层组成。而在 Bottleneck3d
设计中,基础块由以下 3 个部分组成:
-
1x1x1 的卷积层:
- 用于在通道维度上进行压缩,减少feature map的通道数。
- 这可以有效降低计算量和参数量。
-
3x3x3 的卷积层:
- 在空间维度上进行特征提取。
-
1x1x1 的卷积层:
- 用于在通道维度上进行扩展,恢复feature map的通道数。
这种设计被称为"瓶颈"(Bottleneck)结构,因为它首先将通道数压缩,然后在3D卷积层中提取特征,最后再将通道数恢复到原来的大小。
这种结构相比于标准的 ResNet 基础块,有以下优点:
- 参数量更少
- 计算量更低
- 网络容量更大
因此,在需要构建更深层次的 3D 卷积网络时,使用 Bottleneck3d
设计通常是一个不错的选择。
总之,Bottleneck3d
就是 ResNet3D 网络中使用的一种特殊的基础块设计,它通过"瓶颈"结构来提高网络的效率和性能。
参考: