Residual, BottleNeck, Inverted Residual, MBConv的解释和Pytorch实现
上篇ConvNext的文章有小伙伴问BottleNeck,Inverted Residual的区别,所以找了这篇文章,详细的解释一些用到的卷积块,当作趁热打铁吧
在介绍上面的这些概念之间,我们先创建一个通用的 conv-norm-act 层,这也是最基本的卷积块。
fromfunctoolsimportpartialfromtorchimportnnclassConvNormAct(nn.Sequential):def__init__(self,in_features: int,out_features: int,kernel_size: int,norm: nn.Module = nn.BatchNorm2d,act: nn.Module = nn.ReLU,**kwargs):super().__init__(nn.Conv2d(in_features,out_features,kernel_size=kernel_size,padding=kernel_size//2,),norm(out_features),act(),)Conv1X1BnReLU = partial(ConvNormAct, kernel_size=1)Conv3X3BnReLU = partial(ConvNormAct, kernel_size=3)importtorchx = torch.randn((1, 32, 56, 56))Conv1X1BnReLU(32, 64)(x).shape#torch.Size([1, 64, 56, 56])
残差连接
ResNet 中提出并使用了残差连接, 这个想法是将层的输入与层的输出相加,输出 = 层(输入)+ 输入。下图可以帮助您将其可视化。但是,它只使用了一个 + 运算符。残差操作提高了梯度在乘法器层上传播的能力,允许有效地训练超过一百层的网络。

在PyTorch中,我们可以轻松地创建一个ResidualAdd层
fromtorchimportnnfromtorchimportTensorclassResidualAdd(nn.Module):def__init__(self, block: nn.Module):super().__init__()self.block = blockdefforward(self, x: Tensor) ->Tensor:res = xx = self.block(x)x += resreturnxResidualAdd(nn.Conv2d(32, 32, kernel_size=1))(x).shape
捷径 Shortcut
有时候残差没有相同的输出维度,所以无法将它们相加。所以就需要使用conv(带+的黑色箭头)来投影输入,以匹配输出的特性
完整文章
https://avoid.overfit.cn/post/af49b27f50bb416ca829b4987e902874

浙公网安备 33010602011771号