class SparseBasicBlock(BasicBlock, spconv.SparseModule):
# 该类使用子流形稀疏卷积(submanifold sparse convolution)实现。
适用于稀疏点云卷积网络的基本块。
# 参数:
inplanes (int): 输入的通道数。
planes (int): 输出的通道数。
stride (int): 第一个卷积层的步长。默认为 1。
downsample (None | Module): 用于下采样的模块(可选)。
conv_cfg (dict): 用于构造和配置卷积层的字典,默认为 None。
norm_cfg (dict): 用于构造和配置归一化层的字典,默认为 {'type':'BN'}。
"""Sparse basic block for PartA^2.
Sparse basic block implemented with submanifold sparse convolution.
Args:
inplanes (int): inplanes of block.
planes (int): planes of block.
stride (int): stride of the first block. Default:1
downsample (None | Module): down sample module for block.
conv_cfg (dict): dictionary to construct and config conv layer.
Default: None
norm_cfg (dict): dictionary to construct and config norm layer.
Default:dict(type='BN')"""
expansion =1 # 扩展倍数。该值影响输出通道数,通常为 1。
def __init__(self, inplanes, planes, stride=1, downsample=None, conv_cfg=None, norm_cfg=None):
spconv.SparseModule.__init__(self) # 初始化 SparseModule(稀疏模块)的基类
BasicBlock.__init__( # 初始化 BasicBlock(基础卷积块)的基类,传入必要参数
self,
inplanes,
planes,
stride=stride,
downsample=downsample,
conv_cfg=conv_cfg,
norm_cfg=norm_cfg,)
def forward(self, x): # x: 输入的稀疏张量(包含 features 和 coordinates 等信息)。
identity = x.features # 保存输入的 features 作为残差连接的 identity
assert x.features.dim()==2, f"x.features.dim()={x.features.dim()}"
out = self.conv1(x) # 第一个卷积层的前向传播
out.features = self.norm1(out.features)
out.features = self.relu(out.features)
out = self.conv2(out) # 第二个卷积层的前向传播
out.features = self.norm2(out.features)if self.downsample is not None: # 如果存在下采样模块,则对输入进行下采样
identity = self.downsample(x)
out.features += identity # 将残差连接 (identity) 加到当前输出的特征上,实现残差连接
out.features = self.relu(out.features) # 对加和后的特征应用 ReLU 激活函数
return out
def make_sparse_convmodule(
in_channels,
out_channels,
kernel_size,
indice_key, # 稀疏张量的索引键,用于 spconv 内部的索引管理
stride=1,
padding=0, # 输入的填充大小,可以是整数或列表
conv_type="SubMConv3d", # 使用的稀疏卷积类型,默认为子流形卷积 (SubMConv3d)
norm_cfg=None,
order=("conv","norm","act"),):"""Make sparse convolution module.
Args:
in_channels (int): the number of input channels
out_channels (int): the number of out channels
kernel_size (int|tuple(int)): kernel size of convolution
indice_key (str): the indice key used for sparse tensor
stride (int|tuple(int)): the stride of convolution
padding (int or list[int]): the padding number of input
conv_type (str): sparse conv type in spconv
norm_cfg (dict[str]): config of normalization layer
order (tuple[str]): The order of conv/norm/activation layers. It is a
sequence of "conv","norm" and "act". Common examples are
("conv","norm","act") and ("act","conv","norm").
Returns:
spconv.SparseSequential: sparse convolution module."""
assert isinstance(order, tuple) and len(order)<=3
assert set(order)|{"conv","norm","act"}=={"conv","norm","act"}
# 配置卷积层的参数字典,包括卷积类型和索引键
conv_cfg =dict(type=conv_type, indice_key=indice_key)
layers =list()for layer in order: # 根据指定的层顺序逐层构建网络
if layer =="conv":if conv_type not in["SparseInverseConv3d","SparseInverseConv2d","SparseInverseConv1d",]:
layers.append(build_conv_layer(
conv_cfg,
in_channels,
out_channels,
kernel_size,
stride=stride,
padding=padding,
bias=False,))else:
layers.append(build_conv_layer(conv_cfg, in_channels, out_channels, kernel_size, bias=False))
elif layer =="norm":
layers.append(build_norm_layer(norm_cfg, out_channels)[1])
elif layer =="act":
layers.append(nn.ReLU(inplace=True))
layers = spconv.SparseSequential(*layers)return layers