上篇ConvNext的文章有小夥伴問BottleNeck,Inverted Residual的區別,所以找了這篇文章,詳細的解釋一些用到的卷積塊,當作趁熱打鐵吧
在介紹上面的這些概念之間,我們先創建一個通用的 conv-norm-act 層,這也是最基本的卷積塊。
fromfunctoolsimportpartial
fromtorchimportnn
classConvNormAct(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)
importtorch
x = torch.randn((1, 32, 56, 56))
Conv1X1BnReLU(32, 64)(x).shape
#torch.Size([1, 64, 56, 56])
殘差連接
ResNet 中提出並使用了殘差連接, 這個想法是將層的輸入與層的輸出相加,輸出 = 層(輸入)+ 輸入。下圖可以幫助您將其可視化。但是,它只使用了一個 + 運算符。殘差操作提高了梯度在乘法器層上傳播的能力,允許有效地訓練超過一百層的網絡。
在PyTorch中,我們可以輕鬆地創建一個ResidualAdd層
fromtorchimportnn
fromtorchimportTensor
classResidualAdd(nn.Module):
def__init__(self, block: nn.Module):
super().__init__()
self.block = block
defforward(self, x: Tensor) ->Tensor:
res = x
x = self.block(x)
x += res
returnx
ResidualAdd(
nn.Conv2d(32, 32, kernel_size=1)
)(x).shape
捷徑 Shortcut
有時候殘差沒有相同的輸出維度,所以無法將它們相加。所以就需要使用conv(帶+的黑色箭頭)來投影輸入,以匹配輸出的特性
完整文章
https://avoid.overfit.cn/post/af49b27f50bb416ca829b4987e902874