class BaseConv(nn.Module):
"""A Conv2d -> Batchnorm -> silu/leaky relu block"""
def __init__(
self, in_channels, out_channels, ksize, stride, groups=1, bias=False, act="silu"
):
super().__init__()
# same padding
pad = (ksize - 1) // 2 # 计算padding的大小,如果ksize为奇数,则pad=(ksize-1)//2,如果ksize为偶数,则pad=ksize//2-1
self.conv = nn.Conv2d(
in_channels, # 输入通道数
out_channels, # 输出通道数
kernel_size=ksize, # 卷积核大小
stride=stride, # 步长
padding=pad, # padding
groups=groups, # 分组卷积,当groups=1时,表示不使用分组卷积,当groups=in_channels时,表示使用深度可分离卷积
# 分组卷积的作用是将输入的通道数分成groups组,每组的通道数为in_channels//groups,然后对每组通道数进行卷积,最后将每组卷积后的特征图进行拼接
bias=bias, # 是否使用偏置,如果使用偏置,则在卷积后加上偏置,如果不使用偏置,则不加偏置
# 偏置的作用是使得卷积后的特征图的每个通道的均值为0,方差为1,这样可以使得卷积后的特征图更加稳定
)
self.bn = nn.BatchNorm2d(out_channels) # BN层,将卷积后的特征图进行归一化,使得每个通道的均值为0,方差为1
self.act = get_activation(act, inplace=True) # 激活函数,这里使用的是silu激活函数,silu激活函数的计算公式为x*sigmoid(x),这里的sigmoid是指logistic函数,即1/(1+exp(-x))
def forward(self, x):
return self.act(self.bn(self.conv(x)))
def fuseforward(self, x): # fuseforward函数用于融合BN和激活函数,将BN和激活函数融合成一个卷积层,这样可以减少计算量
return self.act(self.conv(x)) # Q: 这里没有使用BN层,是因为BN层的参数已经融合到了卷积层中吗?在哪里融合的? A: 在utils/model_utils.py中的fuse_model函数中,将BN层的参数融合到了卷积层中
发表回复