1、深度可分離卷積
標準卷積在卷積時,同時考慮了圖像的區域與通道信息,那么為什么不能分開考慮區域與通道呢?
基于此想法,誕生了深度可分離卷積(Depthwise Separable Convolution),將卷積的過程分為逐通道卷積與逐點1×1卷積兩步。
1.1 逐通道卷積
卷積核參數量少。卷積核參數量為Ci×3×3,遠少于標準卷積Ci×3×3×Co的數量;
通道之間相互獨立,沒有各通道間的特征融合,這也是逐通道卷積的核心思想,輸出特征的每一個點只對應輸入特征一個通道上的3×3大小的特征,而不是標準卷積中Ci×3×3大小;
由于只在通道間進行卷積,導致輸入與輸出特征圖的通道數相同,無法改變通道數。
1.2 1x1卷積
由于逐通道卷積通道間缺少特征的融合,并且通道數無法改變,因此后續還需要繼續連接一個逐點的1×1的卷積,有兩個作用:
- 一方面可以融合不同通道間的特征;
- 同時也可以改變特征圖的通道數。
1.3 參數量計算
圖a的標準卷積,使用一個和輸入數據通道數相同的卷積核執行逐個通道卷積后求和獲得一個通道的輸出,計算量為,其中
代表輸入的通道數,
為卷積核的寬和高,一個卷積核處理輸入數據時的計算量為:
,其中
為輸入的寬和高,如果在某一個卷積層使用
個卷積核,那么這一卷積層的計算量為:
。
圖b、c是深度可分離卷積,首先使用一組通道數為1的卷積核,每次只處理一個輸入通道,并且這一組卷積核的個數是和輸入通道數相同的。執行完上面的深度卷積后,再使用通道數為輸入數據通道數的大小為1x1的卷積來組合之前輸出的特征圖,將最終輸出通道數變為一個指定的數量。
- 理論計算
一組和輸入通道數相同的2D卷積核(通道數為1,即深度卷積或者說分組卷積)的運算量為: ;
而3D(標準卷積)的卷積核1x1的運算量為: ,因此這種組合方式的總計算量為:
;
因此,深度可分離卷積相比于標準卷積計算量的比例為:
- 舉例計算
假設輸入特征圖尺寸為112x112,輸入通道數64,卷積核大小3x3,卷積核個數128。
標準卷積計算:3 * 3 * 64 * 112 * 112 * 128 = 924844032
深度可分離卷積計算:3 * 3 * 64 * 112 * 112 + 1 * 1 * 64 * 112 * 112 * 128 = 109985792
二者的比例為:
可以看到將一個標準卷積換成深度可分離卷積之后模型的計算量減少了9倍。
2、網絡結構
特點:
- 除了第一層為標準卷積外都采用深度可分離卷積;
- 最后一層全連接沒有激活函數直接送入到 Softmax 層,其他的標準卷積和深度可分離卷積都接入BN和ReLU;
- 在深度可分離卷積的兩層后面都要引入 BN 和 ReLU,
- 第一層標準卷積和深度可分離卷積通過stride=2的卷積實現下采樣;
- 最后一個平均池化層將空間分辨率減小為1;
- 如果將Depthwise卷積層和Pointwise卷積層算成不同層的話,MobileNet V1一共有28層。
MobileNet網絡的有效性:
僅僅通過上文中減少網絡乘加操作對于網絡加速是不夠的,同時要確保這些乘加操作能夠高效實現也很重要。例如,非結構化的稀疏矩陣操作通常不比密集矩陣運算快,除非是非常稀疏的矩陣。
MobileNet V1的模型結構幾乎將全部的計算復雜度放到了1x1卷積中。
可以看到,95% 的計算時間都花費在 1×1 卷積上,75% 的參數量也都集中在 1×1 卷積層,其余的參數則主要來自全連接層。
- 1 x 1卷積 、3 x 3卷積、5 x 5卷積都可以通過高度優化的通用矩陣乘法(GEMM)來實現,但是3x3卷積和5x5卷積等需要使用im2col在內存中對數據進行重排,以將其映射到GEMM可以使用的方式。而1x1卷積不需要在內存中重排就可以直接被GEMM(最優化的數值線性代數算法之一)實現。MobileNet絕大部分使用1x1卷積,因此可以充分利用GEMM算法,來實現高效計算,加速網絡。
3、寬度乘子:更瘦的模型
盡管基本的 MobileNet 結構已經非常小、時延很低,但具體的使用場景可能需要模型更小更快。為了構建這些計算量更少更小的模型,作者引入了一個簡單的參數,稱之為寬度乘子(width multiplier),它的作用是統一讓網絡中的每一層都更瘦。
針對某一層網絡和,輸入通道數從
變成
,輸出通道數從
變成
,這樣這一層的計算代價就變為:
寬度乘子可以以大致的速率減少計算代價和參數量,可以用來設計一個更小的網絡來平衡準確率、時延和模型大小這三者。
4、分辨率乘子:減弱表示能力
另一個減少計算代價的超參數是分辨率乘子(resolution multiplier)
將它應用在輸入圖像上,然后每一層的表示能力都相應減少。實際中,作者是通過設置輸入分辨率來確定這個參數的。
寬度乘子和分辨率乘子結合在一起,某一層網絡的計算代價就變為了:
分辨率乘子可以以的速率減少計算代價。下面的例子可以很好地展示深度可分離卷積以及兩個超參數是怎么減少網絡的計算代價和參數量的。
5、實驗結果
采用深度卷積的網絡相對于標準卷積節省了巨大的計算代價和參數量,但準確率卻僅僅降低了 1%。
相較于移除表一中特征圖大小為 14×14×512 的五層網絡,寬度因子的更瘦網絡比更淺的網絡準確率高出 3 個百分點。
隨著寬度因子的降低,模型的準確率平滑降低,直到值太小 時才有顯著下降。
隨著分辨率因子的降低,模型的準確率始終保持平滑降低。
相較于 GoogleNet 和 VGG,MobileNet 的準確率接近于 VGG ,超越了 GoogleNet,但模型大小的計算代價都小了很多。
可以使用PyTorch來搭建一個MobileNet V1網絡。
6、代碼
class MobileNetV1(nn.Module):
def __init__(self):
super(MobileNet, self).__init__()
def conv_bn(dim_in, dim_out, stride):
return nn.Sequential(
nn.Conv2d(dim_in, dim_out, 3, stride, 1, bias=False),
nn.BatchNorm2d(dim_out),
nn.ReLU(inplace=True)
)
def conv_dw(dim_in, dim_out, stride):
return nn.Sequential(
nn.Conv2d(dim_in, dim_in, 3, stride, 1,
groups= dim_in, bias=False),
nn.BatchNorm2d(dim_in),
nn.ReLU(inplace=True),
nn.Conv2d(dim_in, dim_out, 1, 1, 0, bias=False),
nn.BatchNorm2d(dim_out),
nn.ReLU(inplace=True),
)
self.model = nn.Sequential(
conv_bn( 3, 32, 2),
conv_dw( 32, 64, 1),
conv_dw( 64, 128, 2),
conv_dw(128, 128, 1),
conv_dw(128, 256, 2),
conv_dw(256, 256, 1),
conv_dw(256, 512, 2),
conv_dw(512, 512, 1),
conv_dw(512, 512, 1),
conv_dw(512, 512, 1),
conv_dw(512, 512, 1),
conv_dw(512, 512, 1),
conv_dw(512, 1024, 2),
conv_dw(1024, 1024, 1),
nn.AvgPool2d(7),
)
self.fc = nn.Linear(1024, 1000)
def forward(self, x):
x = self.model(x)
x = x.view(-1, 1024)
x = self.fc(x)
return x
總體上,MobileNet v1利用深度可分離的結構犧牲了較小的精度,帶來了計算量與網絡層參數的大幅降低,從而也減小了模型的大小,方便應用于移動端。
但MobileNet v1也有其自身結構帶來的缺陷,主要有以下兩點:
模型結構較為復古,采用了與VGGNet類似的卷積簡單堆疊,沒有采用殘差、特征融合等先進的結構。
深度分解卷積中各通道相互獨立,卷積核維度較小,輸出特征中只有較少的輸入特征,再加上ReLU激活函數,使得輸出很容易變為0,難以恢復正常訓練,因此在訓練時部分卷積核容易被訓練廢掉。