從MobileNet中的

深度可分卷積

(Depthwise Separable Convolution)講起

看過MobileNet的都知道,MobileNet最主要的加速就是因為深度可分卷積(Depthwise Separable Convolution)的使用。將原本一步到位的卷積操作,分為兩個卷積的級聯,分成的兩個卷積相對於原始的卷積而言,引數大大減少,計算量大大減少。

不用重新訓練,直接將現有模型轉換為MobileNet

1、

標準卷積

假設卷積層的輸入為:

M\times H\times W

,輸出為:

N\times H \times W

,標準卷積的卷積核為:

M\times K \times K\times N

,計算量為:

M\times H\times W\times K\times K\times N

2、深度可分卷積:

深度可分卷積是將原來的一個卷積,分解成兩個不同的卷積,每個卷積的功能不一樣。一個在feature map進行卷積,一個在通道上進行卷積。

Depthwise Conv:首先,對輸入的每個channel使用一個

K \times K

的卷積核進行卷積,因為輸入共有

M

個channel,所以此時卷積核的引數為:

M\times K\times K

,輸出為:

M\times H\times W

,計算量為:

M\times W \times H \times K \times K

Pointwise Conv:然後,使用

N

1\times 1

的卷積核,對上一步輸出的

M

個channel的結果進行卷積,起到通道融合的作用。這裡卷積核的引數為

M\times 1\times 1 \times N

,輸出為

N\times H \times W

,計算量為:

N\times W\times H\times 1\times 1

引數量的比值:

\frac{M\times K\times K \times 1 + M\times 1\times 1\times N}{M\times K\times K \times N} = \frac{1}{N} + \frac{1}{K^2}

計算量的比值:

\frac{M\times W\times H\times K\times K \times 1 + M\times W \times H \times 1\times 1\times N}{M\times W \times H\times K\times K \times N} = \frac{1}{N} + \frac{1}{K^2}

從上面引數量的比值和計算量的比值可以看出,深度可分卷積相對於傳統的標準卷積可以極大的減少引數量和計算量。例如,對於輸出通道

N=64

,卷積核大小為

K=3

的標準卷積,引數數量變成了原來的

\frac{1}{64} + \frac{1}{9}

3、深度可分卷積的pytorch實現:

def

conv_dw

inp

oup

stride

):

return

nn

Sequential

nn

Conv2d

inp

inp

3

stride

1

groups

=

inp

bias

=

False

),

nn

BatchNorm2d

inp

),

nn

ReLU

inplace

=

True

),

nn

Conv2d

inp

oup

1

1

0

bias

=

False

),

nn

BatchNorm2d

oup

),

nn

ReLU

inplace

=

True

將訓練好的卷積模型轉換為深度可分卷積

既然有了深度可分卷積,並且這個卷積方法可以在不改變特徵輸入輸出大小的基礎上極大減少引數量和計算量,那麼我們當然會想著把已有模型中的標準卷積換成深度可分卷積。可是,在替換成深度可分卷積時,實際上模型由原來的一個卷積變成了兩個卷積,模型結構已經發生了變化,所以我們需要對轉換後的

深度可分卷積模型

重新訓練。這就要求我們有足夠的資料,足夠的時間重新訓練。

有沒有什麼方法能夠不重新訓練模型,直接將已有的訓練好的模型,轉換成深度可分卷積呢?

答案是:有!

接下來要講的方法就是出自文章:

文章流程圖:

不用重新訓練,直接將現有模型轉換為MobileNet

文章思想:

文章思想很簡單,透過使用作者提出的DAC方法,直接將一個標準卷積的權植,分解成兩個卷積(

T_d

T_s

)的級聯。

n\times k_w \times k_h\times c

的卷積分解成

rC\times k_w\times k_h \times 1

n\times 1\times 1\times rC

其中

n

是輸出channel,

c

是輸入channel,

k_w, k_h

kernel size

rC=r\times c

r

是一個分解因子,也是設定的SVD分解中去的主成分個數,

r

(文章中

r=1,2,3,4,5

)越大說明保留的資訊越多。

與MobileNet中可分離卷積的區別:

乍一看這種分解出來的結果和可分離卷積形式一樣,實則不然,具體區別有兩點:

MobileNet的深度可分卷積在depthwise和pointwise之間有BN和啟用層,而DAC分解的則沒有。

MobileNet的深度可分卷積在depthwise階段,每個輸入channel,只對應一個卷積核,即depthwise階段卷積核的大小為

c\times k_w \times k_h

,而DAC中每個輸入channel對應了

r

個卷積和,所以此階段總的卷積核大小為

r\times c\times h_w\times h_h

同理,在pointwise階段,兩種方法的卷積核大小也不一樣。

具體方法:

作者在文章中給出了非常清晰的演算法流程,中間用到了SVD分解的方法獲取主成分。具體方法如下:

不用重新訓練,直接將現有模型轉換為MobileNet

計算量的減少:

假設輸入feature為

W\times H\times c

,輸出大小為

W\times H\times n

,則計算量的比值為:

\frac{W\times H\times k_w \times k_h\times rC +W\times H\times rC\times n}{W\times H\times c\times k_w \times k_h\times n} = \frac{r}{n} + \frac{r}{k_wk_h}

實驗分析:

作者做了兩個探究性實驗,探究了分解哪些層對模型的影響最大,並且在物體分類、物體檢測、

pose estimation

上都做了遷移測試。這裡講一下兩個有意思的探究性實驗,其他遷移實驗可以去文章細看。

實驗一:驗證分解單個層並且使用不同的rank(即上面說的分解因子 #FormatImgID_45# )對模型整體效能的影響。

作者對CIFAR-VGG模型的不同卷積層進行DAC分解,每次只分解一個卷積層,得到如下結果:

不用重新訓練,直接將現有模型轉換為MobileNet

結論:

1、使用較小的rank,比如rank=1時,分解前面的層(例如conv2d_

1)會導致模型精度損失特別厲害(93。6->18。6),而分解後面的層(conv2d_

13)則不會損失很多(93。6->92。9)。

2、越大的rank,精度損失的越小。比如在conv2d_1階段,rank5 的精度遠遠高於rank1。

實驗二:驗證分解前k個層和後k個層對模型精度的影響

前k個層就是從第一個到第k個, 後k就是從最後一個到導數第k個

不用重新訓練,直接將現有模型轉換為MobileNet

結論:同等條件下(相同的rank),分解網路後面的層產生的精度損失會小於分解網路前面的層。

總結

方法非常簡單使用,而且又很容易遷移到各種模型上去。最最主要的是,直接對訓練好的model進行分解,不必再重新訓練了。省時有省力,美滋滋。

[1] Howard A G, Zhu M, Chen B, et al。 Mobilenets: Efficient

convolutional neural networks

for mobile vision applications[J]。 arXiv preprint arXiv:1704。04861, 2017。

[2] Li X, Zhang S, Jiang B, et al。 DAC: Data-free Automatic Acceleration of Convolutional Networks[J]。 arXiv preprint arXiv:1812。08374, 2018。