MobileNetV2: Inverted Residuals and Linear Bottlenecks, CVPR 2018.
谷歌公司
MobileNet V1 結構非常簡單, 發明了 Depthwise 和 Pointwise 卷積,但是沒有使用RestNet里的residual learning;另一方面,Depthwise Conv確實是大大降低了計算量,但實際中,發現不少訓練出來的kernel是空的。

ResNet 中的 bottleneck (兩頭粗,中間細,所以得名),先用1x1卷積把通道數由256降到64,然后進行3x3卷積,不然中間3x3卷積計算量太大。所以bottleneck是兩邊寬中間窄(也是名字的由來)。
但是在 MobilenetV2中,反了過來,輸入是24維,輸出也是24維,但中間我們擴展了6倍。網絡是中間胖、兩頭窄,所以叫做 Inverted residule block。
其中的原理是:通道越少,卷積層的乘法計算量就越小。那么如果整個網絡都是低維的通道,那么整體計算速度就會很快。然而,這樣效果並不好,沒有辦法提取到整體的足夠多的信息。所以,如果提取特征數據的話,我們可能更希望有高維的通道來做這個事情。V2就設計這樣一個結構來達到平衡。
V2中首先擴展維度,然后用depthwise conv來提取特征,最后再壓縮數據,讓網絡變小。

網絡的整體結構如下,同時,性能進一步得到了提升。


代碼如下,也比較容易理解:
# 通過 expansion 增大 feature map 的數量
planes = expansion * in_planes
self.conv1 = nn.Conv2d(in_planes, planes, kernel_size=1, stride=1,
padding=0, bias=False)
self.bn1 = nn.BatchNorm2d(planes)
self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=stride,
padding=1, groups=planes, bias=False)
self.bn2 = nn.BatchNorm2d(planes)
self.conv3 = nn.Conv2d(planes, out_planes, kernel_size=1, stride=1,
padding=0, bias=False)
self.bn3 = nn.BatchNorm2d(out_planes)