轉載請注明出處:
https://www.cnblogs.com/darkknightzh/p/9410540.html
論文:
MobileNets: Efficient Convolutional Neural Networks for Mobile Vision Applications
網址:
https://arxiv.org/abs/1704.04861?context=cs
非官方的pytorch代碼:
https://github.com/marvis/pytorch-mobilenet
1. 深度可分離卷積
mobilenetV1使用的是深度可分離卷積(Depthwise Separable Convolution,DSC),DSC包含兩部分:depthwise convolution(DWC)+ pointwise convolution(PWC)。DWC對輸入的通道進行濾波,其不增加通道的數量,PWC用於將PWC不同的通道進行連接,其可以增加通道的數量。通過這種分解的方式,可以明顯的減少計算量。
如下圖所示,傳統的卷積(a),卷積核參數為${{D}_{K}}\centerdot {{D}_{K}}\centerdot M\centerdot N$,其中${{D}_{K}}$為卷積核大小,M為輸入的通道數,N為輸出的通道數。DWC(b)中卷積核參數為${{D}_{K}}\centerdot {{D}_{K}}\centerdot 1\centerdot M$,其中M個${{D}_{K}}\centerdot {{D}_{K}}$的核和輸入特征的對應通道進行卷積,如下式所示。PWC(c)中卷積核參數為$1\centerdot 1\centerdot M\centerdot N$,每個卷積核在特征維度上分別對輸入的M個特征進行加權,最終得到N個特征(M≠N時,完成了升維或者降維)。
${{\mathbf{\hat{G}}}_{k,l,m}}=\sum\limits_{i,j}{{{{\mathbf{\hat{K}}}}_{k,l,m}}\centerdot {{\mathbf{F}}_{k+i-1,l+j-1,m}}}$
傳統卷積的計算量為:
${{D}_{K}}\centerdot {{D}_{K}}\centerdot M\centerdot N\centerdot {{D}_{F}}\centerdot {{D}_{F}}$
DSC總共的計算量為:
${{D}_{K}}\centerdot {{D}_{K}}\centerdot M\centerdot {{D}_{F}}\centerdot {{D}_{F}}+M\centerdot N\centerdot {{D}_{F}}\centerdot {{D}_{F}}$
當使用3*3的卷積核時,DSC可將計算量降低為原來的1/8到1/9。
需要說明的是,DWC,PWC后面均有BN和ReLU。如下圖所示,傳統的卷積層為3*3conv+BN+ReLU,Depthwise Separable convolutions為3*3DWC+BN+ReLU+1*1conv+BN+ReLU。
2. 網絡結構
mobileNetV1的網絡結構如下圖所示。其中第一個卷積層為傳統的卷積;前面的卷積層均有bn和relu,最后一個全連接層只有BN,無ReLU。
mobileNetV1使用RMSprop訓練;由於參數很少,DWC使用比較小的或者不使用weight decay(l2 regularization)。
3. 寬度縮放因子(width multiplier)
文中引入了$\alpha $作為寬度縮放因子,其作用是在整體上對網絡的每一層維度(特征數量)進行瘦身。$\alpha $影響模型的參數數量及前向計算時的乘加次數。此時網絡每一層的輸入為$\alpha M$維,輸出為$\alpha N$維。此時DSC的計算量變為:
${{D}_{K}}\centerdot {{D}_{K}}\centerdot \alpha M\centerdot {{D}_{F}}\centerdot {{D}_{F}}+\alpha M\centerdot \alpha N\centerdot {{D}_{F}}\centerdot {{D}_{F}}$
$\alpha \in (0,1]$,典型值為1,0.75,0.5,0.25。
4. 分辨率縮放因子(resolution multiplier)
該因子即為$\rho $,用於降低輸入圖像的分辨率(如將224*224降低到192*192,160*160,128*128)。
此時DSC的計算量變為:
${{D}_{K}}\centerdot {{D}_{K}}\centerdot \alpha M\centerdot \rho {{D}_{F}}\centerdot \rho {{D}_{F}}+\alpha M\centerdot \alpha N\centerdot \rho {{D}_{F}}\centerdot \rho {{D}_{F}}$
5. pytorch代碼
pytorch代碼見參考網址中benchmark.py
1 class MobileNet(nn.Module): 2 def __init__(self): 3 super(MobileNet, self).__init__() 4 5 def conv_bn(inp, oup, stride): # 第一層傳統的卷積:conv3*3+BN+ReLU 6 return nn.Sequential( 7 nn.Conv2d(inp, oup, 3, stride, 1, bias=False), 8 nn.BatchNorm2d(oup), 9 nn.ReLU(inplace=True) 10 ) 11 12 def conv_dw(inp, oup, stride): # 其它層的depthwise convolution:conv3*3+BN+ReLU+conv1*1+BN+ReLU 13 return nn.Sequential( 14 nn.Conv2d(inp, inp, 3, stride, 1, groups=inp, bias=False), 15 nn.BatchNorm2d(inp), 16 nn.ReLU(inplace=True), 17 18 nn.Conv2d(inp, oup, 1, 1, 0, bias=False), 19 nn.BatchNorm2d(oup), 20 nn.ReLU(inplace=True), 21 ) 22 23 self.model = nn.Sequential( 24 conv_bn( 3, 32, 2), # 第一層傳統的卷積 25 conv_dw( 32, 64, 1), # 其它層depthwise convolution 26 conv_dw( 64, 128, 2), 27 conv_dw(128, 128, 1), 28 conv_dw(128, 256, 2), 29 conv_dw(256, 256, 1), 30 conv_dw(256, 512, 2), 31 conv_dw(512, 512, 1), 32 conv_dw(512, 512, 1), 33 conv_dw(512, 512, 1), 34 conv_dw(512, 512, 1), 35 conv_dw(512, 512, 1), 36 conv_dw(512, 1024, 2), 37 conv_dw(1024, 1024, 1), 38 nn.AvgPool2d(7), 39 ) 40 self.fc = nn.Linear(1024, 1000) # 全連接層 41 42 def forward(self, x): 43 x = self.model(x) 44 x = x.view(-1, 1024) 45 x = self.fc(x) 46 return x