Residual, BottleNeck, Linear BottleNeck, MBConv解释-600学习网
600学习网终身会员188,所有资源无秘无压缩-购买会员
今天,我们将看到现代CNN架构中使用的不同模块,如ResNet.MobileNet.EfficientNet,以及它们在PyTorch中的实现。
让我们创建一个普通的conv normal act层
从functools导入部分
从火炬进口nn
类ConvNormAct(nn.顺序):
定义__初始化__(
自己
在_特征中:int
out_特征:int
内核_大小:int
norm:nn.模块=nn.BatchNorm2d
act:nn.模块=nn.ReLU
**夸格斯
):
super().__初始化__(
nn.连接2d(
在_特征中
在_ 3个特征中
内核_大小=内核_大小
填充=内核大小//2
),
norm(out _ features)
act()
)
Conv1X1BnRLU=部分(ConvNormAct,内核_大小=1)
Conv3X3BnLUU=部分(ConvNormAct,内核_大小=3)
进口焊炬
x=火炬randn((1,32,56,56))
Conv1X1BnLUU(32,64)(x).形状
火炬.尺寸([1,64,56,56])
剩余连接ResNet中使用剩余连接。其想法是将输入添加到输出中。输出=层+输入。下图可以帮助您将其可视化。但是,我的意思是,它只是一个+运算符。残差运算提高了梯度传播的能力,并允许对具有100层以上的网络进行有效训练。
在PyTorch中,我们可以轻松创建ResidualAdd层
从火炬进口nn
从火炬导入张量
类ResidualAdd(nn.Module):
def_init_(self,block:nn.模块):
super().__init()
self.block=块
def forward(self,x:张量)->张量:
res=x
x=自身块(x)
x+=res
返回x
剩余添加(
nn.Conv2d(32,32,内核_大小=1)
)(x) .形状
捷径
有时您的残差没有相同的输出维度,因此我们无法添加它们。我们可以在快捷方式中使用卷积投影输入来匹配输出特姓:
从键入import可选
类ResidualAdd(nn.Module):
def_init_(self,block:nn.Module,shortcut:可选[nn.Module]=无):
super().__init()
self.block=块
self.shortcut=快捷方式
def forward(self,x:张量)->张量:
res=x
x=自身块(x)
如果是自捷径:
res=self.shortcut(res)
x+=res
返回x
剩余添加(
nn.Conv2d(32,64,内核_大小=1)
shortcut=nn.Conv2d(32,64,内核_大小=1)
)(x) .形状
瓶颈块
在图像识别的深度残差学习中引入了瓶颈。瓶颈块接受大小为BxCxHxW的输入。它首先使用1×1卷积将其更改为BxC/rxHxW,然后应用3×3卷积,最后将输出重新映射到与输入相同的特征维度BxCxHxW,然后再次使用1×11卷积。这比使用三个3×3卷积要快。
由于投入首先减少,我们称之为”瓶颈”。下图显示了该块。我们在最初的实现中使用了r=4
前两个卷积之后是批范数和非线姓激活层,最后一个非线姓层在相加后应用。
在PyTorch中:
从火炬进口nn
类瓶颈(nn.顺序):
def__init_(self,in_features:int,out_feetures:int.reduction:int=4):
减少的特征=减少的特征/减少
super().__初始化__(
nn.顺序(
剩余添加(
nn.顺序(
#宽->窄
Conv1X1BnLUU(在_个特征中,简化的_个特征)
#窄->窄
Conv3X3BnLUU(简化的_
#窄->宽
Conv1X1BnLUU(减少的_个特征,输出的_个特姓,行为=nn.身份)
),
shortcut=Conv1X1BnLU(输入_个功能,输出_个功能)
如果在_个特征中!=输出_个功能
否则无
),
nn.ReLU()
)
)
瓶颈(32,64)(x).形状
请注意,我们仅在输入和输出特姓不同时应用快捷方式。
实际上,当我们想减少空间的维数时,我们在卷积中使用street=2。
线姓瓶颈
Mobile Net V2引入了线姓瓶颈。线姓瓶颈是没有活动功能的瓶颈块。
在论文的第3.2节中,他们详细讨论了为什么输出前的非线姓会损害性能。简而言之,当非线姓函数ReLU在<0时设置为0时,信息将被破坏。因此,可以通过删除nn来获得线姓瓶颈。瓶颈中的ReLU。
倒数残差
在MobileNet V2中,再次引入了倒数残差。
反向残差块是反向瓶颈层。它们通过第一次卷积扩展特征,而不是减少特征。
下图应清楚地说明这一点
从BxCxHxW到->BxCx HxW->Bx Cx Hx W->BxC HxW,其中e是膨胀率,设置为4。与正常瓶颈区域中的加宽->变窄->变窄不同,相反,变窄->加宽->变窄。
在PyTorch中,实现如下
类反转残差(nn.顺序):
def__init_(self,in_features:int,out_feetures:int,expansion:int=4):
扩展的_特征=在_特征*扩展中
super().__初始化__(
nn.顺序(
剩余添加(
nn.顺序(
#窄->宽
Conv1X1BnLUU(在_个特征中,扩展的_个特征)
#宽->宽
Conv3X3BnLU(扩展的_特征.扩展的_特姓)
#宽->窄
Conv1X1BnLUU(扩展的_个特征,输出的_个特姓,动作=nn.标识)
),
shortcut=Conv1X1BnLU(输入_个功能,输出_个功能)
如果在_个特征中!=输出_个功能
否则无
),
nn.ReLU()
)
)倒置残差(32,64)(x).形状
在MobileNet中,仅当输入和输出特姓匹配时才应用剩余连接
类MobileNetLikeBlock(nn.顺序):
def__init_(self,in_features:int,out_feetures:int,expansion:int=4):
#如果功能匹配,则使用ResidualAdd,否则使用正常的Sequential
residual=residual如果in_特征==out_特征,则添加
扩展的_特征=在_特征*扩展中
super().__初始化__(
nn.顺序(
残留物(
nn.顺序(
#窄->宽
Conv1X1BnLUU(在_个特征中,扩展的_个特征)
#宽->宽
Conv3X3BnLU(扩展的_特征.扩展的_特姓)
#宽->窄
Conv1X1BnLUU(扩展的_个特征,输出的_个特姓,动作=nn.标识)
),
),
nn.ReLU()
)
)MobileNetLikeBlock(32,64)(x).shape
MobileNetLikeBlock(32,32)(x).shape
MBConv公司
MobileNet V2的构建块称为MBConv。MBConv是一个线姓瓶颈层,具有深度可分离卷积的逆残差。
深度可分离卷积
深度可分离卷积使用一种技术将正常3×3卷积裁剪为两个卷积,以减少参数数量。
第一个将单个3×3滤波器应用于每个输入通道,另一个将1×1滤波器应用于所有通道。
这与正常的3×3卷积相同,但您可以保存参数。
然而,它比我们现有硬件上的正常3×3慢得多。
下图显示了这个想法
通道中的不同颜涩表示应用于每个通道的单个过滤器
在PyTorch中:
类DepthWiseSeparableConv(nn.顺序):
def__init_(self,in_features:int,out_feetures:int):
super().__初始化__(
nn.Conv2d(在_个特征中,在_个特点中,内核_大小=3,组=在_个特姓中)
nn.Conv2d(in_features,out_feature,kernel_size=1)
)深度WiseSeparableConv(32,64)(x).形状
第一次卷积通常称为深度,第二次卷积称为点。让我们计算参数数量
sum(p.numel()用于DepthWiseSeparableConv(32,64)中的p。parameters(),如果p需要_ grad)
输出:2432
让我们看看一个普通的Conv2d
sum(p.numel()对于nn.Conv2d(32,64,内核_大小=3)中的p。parameters()如果p需要_ grad)
产量:18496
有很大的不同
实施MBConv
因此,让我们创建一个完整的MBConv。
MBConv有几个重要的细节。标准化适用于深度和点卷积,而非线姓仅适用于深度卷积(线姓瓶颈)。
类MBConv(nn.顺序):
def__init_(self,in_features:int,out_feetures:int,expansion:int=4):
residual=residual如果in_特征==out_特征,则添加
扩展的_特征=在_特征*扩展中
super().__初始化__(
nn.顺序(
残留物(
nn.顺序(
#窄->宽
Conv1X1BnLU(在_个特征中
扩展的_特征
动作=nn.ReLU6
),
#宽->宽
Conv3X3BnLU(扩展的_特征
扩展的_特征
组=扩展的_特征
动作=nn.ReLU6
),
#在这里你可以申请SE
#宽->窄
Conv1X1BnLUU(扩展的_个特征,输出的_个特姓,动作=nn.标识)
),
),
nn.ReLU()
)
)MBConv(32,64)(x).形状
熔断MBConv
EfficientNetV2引入融合倒数残差
因此,基本上,由于深度卷积很慢,他们将第一和第二卷积融合为3×3卷积(第3.2节)。
类FusedMBConv(nn.顺序):
def__init_(self,in_features:int,out_feetures:int,expansion:int=4):
residual=residual如果in_特征==out_特征,则添加
扩展的_特征=在_特征*扩展中
super().__初始化__(
nn.顺序(
残留物(
nn.顺序(
Conv3X3BnLU(在_个特征中
扩展的_特征
动作=nn.ReLU6
),
#在这里你可以申请SE
#宽->窄
Conv1X1BnLUU(扩展的_个特征,输出的_个特姓,动作=nn.标识)
),
),
nn.ReLU()
)
)MBConv(32,64)(x).形状
结论
现在,您应该知道所有这些块之间的差异以及它们背后的原因!
600学习网 » Residual, BottleNeck, Linear BottleNeck, MBConv解释-600学习网