Efficient CNN 介紹(一):MobilenetV1

Original article can be found here (source): Deep Learning on Medium

Efficient CNN 介紹(一):MobilenetV1

前言

在這篇文章,主要會大略的介紹 MobilenetV1 透過了什麼樣的方式達到 Efficient CNN 的目的,因此假如想知道更加詳細的話,建議可以閱讀Mobilenet系列的論文,相信可以收穫多多的。

Introduction

在早期的深度學習中,大家普遍都遇到了一個問題:

越深的網路,錯誤率越高

而造成這個問題主要原因是梯度消失以及梯度爆炸(gradient vanishing / gradient exploding),也就是在透過 back propagation 計算梯度的時候,隨著一層一層 chain rule 的計算,梯度也因為不斷的相乘而越來越大或是越來越小,使得到了網路的前幾層時,已經沒有辦法好好更新網路中的 weight 了。

在 2015 年,ResNet 的透過了 residual learning 的方式解決了過去大家普遍遇到的問題,並使得 CNN(Convolution Neural Network) 為了使得準確度提昇到更高的情況下,更深更複雜。

但是隨著 CNN 為了更好的準確度而更深更複雜的情況下,大家開始遇到了一個問題:

太耗資源了!

在實際應用面上,不論是手機攝影機或是其他的嵌入式系統,我們並沒有辦法像一般電腦一樣,隨便都插上幾張 2080Ti 的GPU,因此在這樣的情況下,我們所需要的是:

更小更快同時可以兼顧準確度的 CNN

也就是今天的主題,Efficient CNN

MobilenetV1

在2017年 Google 所提出的 MobilenetV1 中,透過 Depthwise Separable Convolution 將傳統的 Convolution 拆解成了兩個步驟,以大幅的減少傳統 Convolution 的運算量:

  1. Depthwise convolution
  2. 1×1 convolution (pointwise convolution)
左邊為傳統的 Convolution,而右邊為將傳統 Convolution 拆解成兩個步驟的 Depthwise Separable Convolution。

而單純看上面的名詞可能完全沒有辦法了解他們的是如何減少網路的運算量的,因此接下來我們會來做更加詳細的介紹,而在正式開始講解 Depthwise Separable Convolution 之前,先來複習一下傳統 Convolution 是如何運作的。

傳統 Convlution

首先我們先舉個例子,假如我們有一個 input 的尺寸為 32 * 32 * 2 的照片,我們希望透過傳統的 Convolution 使得其輸出為一個尺寸為 32 * 32 * 3 的 feature map,如下圖:

而為了達到這個目的我們需要一個 size 為 K * K * 2 * 3 的 kernel,但其實我們也可以將這個 kernel 想像成為 3 個 K * K * 2 的 kernels,而每個 kernel 對input 做完 convolution 之後會得到 output 的一層 channel feature map,如下圖:

一個 K * K * 2 的 kernel 對於 input 做完 convolution 之後會得到 output 之中的一層feature map(可以看顏色的對應)

因此在這樣的情況下,我們可以計算出傳統 Convolution 做完一次 convolution 的運算量:

K : kernel 的大小
M : Input 的 channel 數量 (e.g., 2)
N : Output 的 channel 數量 (e.g., 3)
F : Output feature 的大小 (e.g., 32)

Depthwise Separable Convolution

在複習完傳統的 Convolution 之後,終於要正式介紹 MobilenetV1 中的主角,也就是 Depthwise Separable Convolution 了,而 Depthwise Separable Convolution 分成了兩個部份,也就是 Depthwise convolution 以及 1×1 convolution (pointwise convolution),首先我們先講解 Depthwise convolution

Depthwise convolution

顧名思義, Depthwise convolution 與傳統 Convolution 的差別就是 “Depthwise,也就是說:

對於 Input 中的每層 channel(depth) 各自單獨做 Convolution

聽起來有點抽象,因此我們看一下下面的示意圖:

將 Input 的每層 channel 切開,並且各自做 convolution

在上圖當中,跟傳統的 Convolution 不一樣的地方在於,我們講一個 32 * 32 * 2 的 Input,切割成了兩個 32 * 32 * 1的 Input,而這樣切割之後原先我們尺寸為 K * K * 2 的 Kernel 就可以簡化為 K * K * 1的尺寸,跟上面傳統的 convolution 相比,應該看得出來 Depthwise 的方式減少了一定的運算量!

但是,不知道大家有沒有發現,經過了 Depthwise convolution 之後,我們的 Output feature map 的尺寸依然是 32 * 32 * 2,而並非我們所想要的尺寸 32 * 32 * 3,因此接下來的工作就是交由 1×1 convolution (pointwise convolution) 了!

1×1 convolution (pointwise convolution)

1×1 convolution (pointwise convolution) 最主要的目的就是將經過 Depthwise convolution 後的 output feature map 轉換成為我們所希望的 output 尺寸(在這個例子中為 32 * 32 * 3),因此我們先來看一下以下的示意圖:

1×1 convolution (pointwise convolution),使得輸出的尺寸跟我們預想的一樣

K * K * M * F * F + M * N * F * F如上述一樣,原先經過 Depthwise convoltion 的 output feature map 32 * 32 * 2,我們利用了 3 個 1 * 1 * 2 的 kernel 進行 convolution 之後,便可以得到一個尺寸為 32 * 32 * 3 的 output feature map,但是到這邊可能大家會發現,這樣做不就跟傳統的 convolution 一樣嗎?

沒錯, 1×1 convolution (pointwise convolution) 所作的事情基本上跟傳統 Convolution 一模一樣,最主要的差別在於 1×1 這個部份:

1×1 相較於傳統 K×K 的 convolution 可以減少 K² 的運算量

因此在經過了 Depthwise convolution 以及 1×1 convolution (pointwise convolution) 之後,我們依然可以得到我們原先所想要的 32 * 32 * 3 的 output feature map

而所需要的運算量:

K * K * M * F * F + M * N * F * F

K : kernel 的大小
M : Input 的 channel 數量 (e.g., 2)
N : Output 的 channel 數量 (e.g., 3)
F : Output feature 的大小 (e.g., 32)

大家有沒有發現,在傳統 Convolution 當中相乘的運算量,在經過了Depthwise Separable Convolution 之後,中間有一項變成了加法,這樣看起來可能看不出來他們的差別,所以我們用剛剛的例子實際算一次

傳統 Convolution 運算量:

K * K * 2 * 3 * 32 * 32 = 6144 * K²

Depthwise Separable Convolution 運算量:

K * K * 2 * 32 * 32 + 3 * 2 * 32 * 32 = 2048 * K² + 6144

這樣看下來,就可以發現 Depthwise Separable Convolution 相比於傳統 Convolution,減少了大量的運算量,卻可以達到一樣的目的了!

Experiments

講了那麼多,可能大家難免會覺得有點空虛,因此我們直接看一下 MobilnetV1的實驗結果:

在 ImageNet 的表現上,相比於 GoogleNet 以及 VGG16 , MobilenetV1 可以在差不多的準確度的情況下,大幅的降低運算量以及參數量!

總結

MobilenetV1 透過利用 Depthwise Separable Convolution 大幅的減少了過去使用傳統 Convolution 的運算量,並且可以達到相同的準確度。

Reference

  • MobileNets: Efficient Convolutional Neural Networks for Mobile Vision Applications. Andrew G. Howard, Menglong Zhu, Bo Chen, Dmitry Kalenichenko, Weijun Wang, Tobias Weyand, Marco Andreetto, Hartwig Adam