Residual, BottleNeck, Linear BottleNeck, MBConv解釋
今天,我們將看到現(xiàn)代CNN架構(gòu)中使用的不同模塊,如ResNet、MobileNet、EfficientNet,以及它們?cè)赑yTorch中的實(shí)現(xiàn)。
讓我們創(chuàng)建一個(gè)通用的conv-norm-act層
from functools import partial
from torch import nn
class ConvNormAct(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)
import torch
x = torch.randn((1, 32, 56, 56))
Conv1X1BnReLU(32, 64)(x).shape
torch.Size([1, 64, 56, 56])
殘差連接殘差連接用于ResNet中,想法是將輸入添加到輸出中,輸出=層+輸入。下圖可能會(huì)幫助你將其可視化。但是,我的意思是它只是一個(gè)+運(yùn)算符。殘差操作提高了梯度傳播的能力,允許有效地訓(xùn)練具有100層以上的網(wǎng)絡(luò)。
在PyTorch中,我們可以輕松創(chuàng)建一個(gè)ResidualAdd層
from torch import nn
from torch import Tensor
class ResidualAdd(nn.Module):
def __init__(self, block: nn.Module):
super().__init__()
self.block = block
def forward(self, x: Tensor) -> Tensor:
res = x
x = self.block(x)
x += res
return x
ResidualAdd(
nn.Conv2d(32, 32, kernel_size=1)
)(x).shape
shortcut
有時(shí)你的殘差沒(méi)有相同的輸出維度,所以我們不能添加它們。我們可以使用shortcut中的卷積投射輸入,以匹配輸出特征:
from typing import Optional
class ResidualAdd(nn.Module):
def __init__(self, block: nn.Module, shortcut: Optional[nn.Module] = None):
super().__init__()
self.block = block
self.shortcut = shortcut
def forward(self, x: Tensor) -> Tensor:
res = x
x = self.block(x)
if self.shortcut:
res = self.shortcut(res)
x += res
return x
ResidualAdd(
nn.Conv2d(32, 64, kernel_size=1),
shortcut=nn.Conv2d(32, 64, kernel_size=1)
)(x).shape
BottleNeck Blocks
在圖像識(shí)別的深度殘差學(xué)習(xí)中引入了Bottlenecks。Bottlenecks塊接受大小為BxCxHxW的輸入,它首先使用1x1 卷積將其變?yōu)锽xC/rxHxW,然后應(yīng)用3x3 卷積,最后將輸出重新映射到與輸入相同的特征維度BxCxHxW,然后再次使用1x1卷積。這比使用三個(gè)3x3卷積更快。
因?yàn)槭紫葴p少了輸入,所以我們稱之為“Bottlenecks”。下圖顯示了該塊,我們?cè)谠紝?shí)現(xiàn)中使用了r=4
前兩個(gè)卷積之后是batchnorm和一個(gè)非線性激活層,而最后一個(gè)非線性層在加法后應(yīng)用。
在PyTorch中為:
from torch import nn
class BottleNeck(nn.Sequential):
def __init__(self, in_features: int, out_features: int, reduction: int = 4):
reduced_features = out_features // reduction
super().__init__(
nn.Sequential(
ResidualAdd(
nn.Sequential(
# wide -> narrow
Conv1X1BnReLU(in_features, reduced_features),
# narrow -> narrow
Conv3X3BnReLU(reduced_features, reduced_features),
# narrow -> wide
Conv1X1BnReLU(reduced_features, out_features, act=nn.Identity),
),
shortcut=Conv1X1BnReLU(in_features, out_features)
if in_features 。 out_features
else None,
),
nn.ReLU(),
)
)
BottleNeck(32, 64)(x).shape
請(qǐng)注意,僅當(dāng)輸入和輸出特征不同時(shí),我們才應(yīng)用shortcut。
在實(shí)踐中,當(dāng)我們希望減小空間維數(shù)時(shí),在卷積中使用stride=2。
Linear BottleNecks
MobileNet V2中引入了Linear Bottleneck。Linear BottleNecks是沒(méi)有激活函數(shù)的Bottlenecks塊。
在論文的第3.2節(jié)中,他們?cè)敿?xì)討論了為什么在輸出之前存在非線性會(huì)損害性能。簡(jiǎn)而言之,非線性函數(shù)ReLU在<0時(shí)設(shè)為0會(huì)導(dǎo)致破壞信息。因此,在Bottlenecks中刪除nn.ReLU你就可以擁有Linear BottleNecks。
倒殘差
MobileNet V2中再次引入了倒殘差。
倒殘差塊是反向的Bottlenecks層。它們通過(guò)第一次卷積擴(kuò)展特征,而不是減少特征。
下圖應(yīng)該可以清楚地說(shuō)明這一點(diǎn)
我們從BxCxHxW到->BxCxHxW->BxCxHxW->BxCxHxW,其中e是膨脹率,它被設(shè)置為4。而不是像在正常的Bottlenecks區(qū)那樣變寬->變窄->變寬,而是相反,變窄->變寬->變窄。
在PyTorch中,實(shí)現(xiàn)如下
class InvertedResidual(nn.Sequential):
def __init__(self, in_features: int, out_features: int, expansion: int = 4):
expanded_features = in_features * expansion
super().__init__(
nn.Sequential(
ResidualAdd(
nn.Sequential(
# narrow -> wide
Conv1X1BnReLU(in_features, expanded_features),
# wide -> wide
Conv3X3BnReLU(expanded_features, expanded_features),
# wide -> narrow
Conv1X1BnReLU(expanded_features, out_features, act=nn.Identity),
),
shortcut=Conv1X1BnReLU(in_features, out_features)
if in_features 。 out_features
else None,
),
nn.ReLU(),
)
)
InvertedResidual(32, 64)(x).shape
在MobileNet中,只有當(dāng)輸入和輸出特征匹配時(shí),才會(huì)應(yīng)用殘差連接
class MobileNetLikeBlock(nn.Sequential):
def __init__(self, in_features: int, out_features: int, expansion: int = 4):
# use ResidualAdd if features match, otherwise a normal Sequential
residual = ResidualAdd if in_features == out_features else nn.Sequential
expanded_features = in_features * expansion
super().__init__(
nn.Sequential(
residual(
nn.Sequential(
# narrow -> wide
Conv1X1BnReLU(in_features, expanded_features),
# wide -> wide
Conv3X3BnReLU(expanded_features, expanded_features),
# wide -> narrow
Conv1X1BnReLU(expanded_features, out_features, act=nn.Identity),
),
),
nn.ReLU(),
)
)
MobileNetLikeBlock(32, 64)(x).shape
MobileNetLikeBlock(32, 32)(x).shape
MBConv
MobileNet V2的構(gòu)建塊被稱為MBConv。MBConv是具有深度可分離卷積的倒殘差的Linear BottleNecks層。
深度可分離卷積
深度可分離卷積采用一種技巧,將一個(gè)正常的3x3卷積夾在兩個(gè)卷積中,以減少參數(shù)數(shù)量。
第一個(gè)對(duì)每個(gè)輸入的通道應(yīng)用單個(gè)3x3濾波器,另一個(gè)對(duì)所有通道應(yīng)用1x1濾波器。
這與正常的3x3卷積相同,但你節(jié)省了參數(shù)。
然而它比我們現(xiàn)有硬件上的普通3x3慢得多。
下圖顯示了這個(gè)想法
通道中的不同顏色表示每個(gè)通道應(yīng)用的單個(gè)過(guò)濾器
PyTorch中:
class DepthWiseSeparableConv(nn.Sequential):
def __init__(self, in_features: int, out_features: int):
super().__init__(
nn.Conv2d(in_features, in_features, kernel_size=3, groups=in_features),
nn.Conv2d(in_features, out_features, kernel_size=1)
)
DepthWiseSeparableConv(32, 64)(x).shape
第一次卷積通常稱為depth,而第二次卷積稱為point。讓我們統(tǒng)計(jì)參數(shù)量
sum(p.numel() for p in DepthWiseSeparableConv(32, 64).parameters() if p.requires_grad)
輸出:2432
讓我們看一個(gè)普通的Conv2d
sum(p.numel() for p in nn.Conv2d(32, 64, kernel_size=3).parameters() if p.requires_grad)
輸出:18496
有很大的區(qū)別
實(shí)現(xiàn)MBConv
那么,讓我們創(chuàng)建一個(gè)完整的MBConv。
MBConv有幾個(gè)重要的細(xì)節(jié),標(biāo)準(zhǔn)化應(yīng)用于深度和點(diǎn)卷積,非線性僅應(yīng)用于深度卷積(Linear Bottlenecks)。
class MBConv(nn.Sequential):
def __init__(self, in_features: int, out_features: int, expansion: int = 4):
residual = ResidualAdd if in_features == out_features else nn.Sequential
expanded_features = in_features * expansion
super().__init__(
nn.Sequential(
residual(
nn.Sequential(
# narrow -> wide
Conv1X1BnReLU(in_features,
expanded_features,
act=nn.ReLU6
),
# wide -> wide
Conv3X3BnReLU(expanded_features,
expanded_features,
groups=expanded_features,
act=nn.ReLU6
),
# here you can apply SE
# wide -> narrow
Conv1X1BnReLU(expanded_features, out_features, act=nn.Identity),
),
),
nn.ReLU(),
)
)
MBConv(32, 64)(x).shape
Fused MBConv
EfficientNetV2中引入了融合倒殘差
所以基本上,由于深度卷積比較慢,他們將第一個(gè)和第二個(gè)卷積融合在一個(gè)3x3的卷積中(第3.2節(jié))。
class FusedMBConv(nn.Sequential):
def __init__(self, in_features: int, out_features: int, expansion: int = 4):
residual = ResidualAdd if in_features == out_features else nn.Sequential
expanded_features = in_features * expansion
super().__init__(
nn.Sequential(
residual(
nn.Sequential(
Conv3X3BnReLU(in_features,
expanded_features,
act=nn.ReLU6
),
# here you can apply SE
# wide -> narrow
Conv1X1BnReLU(expanded_features, out_features, act=nn.Identity),
),
),
nn.ReLU(),
)
)
MBConv(32, 64)(x).shape
結(jié)論
現(xiàn)在你應(yīng)該知道所有這些塊之間的區(qū)別以及它們背后的原因了!
原文標(biāo)題 : Residual, BottleNeck, Linear BottleNeck, MBConv解釋

發(fā)表評(píng)論
請(qǐng)輸入評(píng)論內(nèi)容...
請(qǐng)輸入評(píng)論/評(píng)論長(zhǎng)度6~500個(gè)字
圖片新聞
-
機(jī)器人奧運(yùn)會(huì)戰(zhàn)報(bào):宇樹(shù)機(jī)器人摘下首金,天工Ultra搶走首位“百米飛人”
-
存儲(chǔ)圈掐架!江波龍起訴佰維,索賠121萬(wàn)
-
長(zhǎng)安汽車母公司突然更名:從“中國(guó)長(zhǎng)安”到“辰致科技”
-
豆包前負(fù)責(zé)人喬木出軌BP后續(xù):均被辭退
-
字節(jié)AI Lab負(fù)責(zé)人李航卸任后返聘,Seed進(jìn)入調(diào)整期
-
員工持股爆雷?廣汽埃安緊急回應(yīng)
-
中國(guó)“智造”背后的「關(guān)鍵力量」
-
小米汽車研發(fā)中心重磅落地,寶馬家門口“搶人”
最新活動(dòng)更多
-
即日-9.16點(diǎn)擊進(jìn)入 >> 【限時(shí)福利】TE 2025國(guó)際物聯(lián)網(wǎng)展·深圳站
-
10月23日火熱報(bào)名中>> 2025是德科技創(chuàng)新技術(shù)峰會(huì)
-
10月23日立即報(bào)名>> Works With 開(kāi)發(fā)者大會(huì)深圳站
-
10月24日立即參評(píng)>> 【評(píng)選】維科杯·OFweek 2025(第十屆)物聯(lián)網(wǎng)行業(yè)年度評(píng)選
-
11月27日立即報(bào)名>> 【工程師系列】汽車電子技術(shù)在線大會(huì)
-
12月18日立即報(bào)名>> 【線下會(huì)議】OFweek 2025(第十屆)物聯(lián)網(wǎng)產(chǎn)業(yè)大會(huì)
推薦專題
- 1 先進(jìn)算力新選擇 | 2025華為算力場(chǎng)景發(fā)布會(huì)暨北京xPN伙伴大會(huì)成功舉辦
- 2 人形機(jī)器人,正狂奔在批量交付的曠野
- 3 宇樹(shù)機(jī)器人撞人事件的深度剖析:六維力傳感器如何成為人機(jī)安全的關(guān)鍵屏障
- 4 解碼特斯拉新AI芯片戰(zhàn)略 :從Dojo到AI5和AI6推理引擎
- 5 AI版“四萬(wàn)億刺激”計(jì)劃來(lái)了
- 6 2025年8月人工智能投融資觀察
- 7 騰訊 Q2 財(cái)報(bào)亮眼:AI 已成第二增長(zhǎng)曲線
- 8 a16z最新AI百?gòu)?qiáng)榜:硅谷頂級(jí)VC帶你讀懂全球生成式AI賽道最新趨勢(shì)
- 9 10 Manus跑路,大廠掉線,只能靠DeepSeek了