任何看過MobileNet架構的人都會遇到可分離卷積(separable convolutions)這個概念。但什麼是「可分離卷積」,它與標準的卷積又有什麼區別?可分離卷積主要有兩種類型:網絡
空間可分離卷積(spatial separable convolutions)架構
深度可分離卷積(depthwise separable convolutions)ide
從概念上講,這是二者中較容易的一個,並說明了將一個卷積分紅兩部分(兩個卷積核)的想法,因此我將從這開始。 不幸的是,空間可分離卷積具備一些顯着的侷限性,這意味着它在深度學習中沒有被大量使用。函數
空間可分卷積之因此如此命名,是由於它主要處理圖像和卷積核(kernel)的空間維度:寬度和高度。 (另外一個維度,「深度」維度,是每一個圖像的通道數)。學習
空間可分離卷積簡單地將卷積核劃分爲兩個較小的卷積核。 最多見的狀況是將3x3的卷積核劃分爲3x1和1x3的卷積 核,以下所示:spa
圖1:在空間上分離3x3內核視頻
如今,咱們不是用9次乘法進行一次卷積,而是進行兩次卷積,每次3次乘法(總共6次),以達到相同的效果。 乘法較少,計算複雜性降低,網絡運行速度更快。blog
圖2:簡單且空間可分離的卷積ci
最著名的可在空間上分離的卷積是用於邊緣檢測的sobel卷積核:get
圖3:分離的Sobel卷積核
空間可分卷積的主要問題是並不是全部卷積核均可以「分離」成兩個較小的卷積核。 這在訓練期間變得特別麻煩,由於網絡可能採用全部可能的卷積核,它最終只能使用能夠分紅兩個較小卷積核的一小部分。
與空間可分離卷積不一樣,深度可分離卷積與卷積核沒法「分解」成兩個較小的內核。 所以,它更經常使用。 這是在keras.layers.SeparableConv2D或tf.layers.separable_conv2d中看到的可分離卷積的類型。
深度可分離卷積之因此如此命名,是由於它不只涉及空間維度,還涉及深度維度(信道數量)。 輸入圖像能夠具備3個信道:R、G、B。 在幾回卷積以後,圖像能夠具備多個信道。 你能夠將每一個信道想象成對該圖像特定的解釋說明(interpret); 例如,「紅色」信道解釋每一個像素的「紅色」,「藍色」信道解釋每一個像素的「藍色」,「綠色」信道解釋每一個像素的「綠色」。 具備64個通道的圖像具備對該圖像的64種不一樣解釋。
相似於空間可分離卷積,深度可分離卷積將卷積核分紅兩個單獨的卷積核,這兩個卷積核進行兩個卷積:深度卷積和逐點卷積。 但首先,讓咱們看看正常的卷積是如何工做的。
若是你不知道卷積如何在一個二維的角度下進行工做,請閱讀本文或查看此站點。
然而,典型的圖像並非2D的; 它在具備寬度和高度的同時還具備深度。 讓咱們假設咱們有一個12x12x3像素的輸入圖像,即一個大小爲12x12的RGB圖像。
讓咱們對圖像進行5x5卷積,沒有填充(padding)且步長爲1.若是咱們只考慮圖像的寬度和高度,卷積過程就像這樣:12x12 - (5x5) - > 8x8。 5x5卷積核每25個像素進行標量乘法,每次輸出1個數。 咱們最終獲得一個8x8像素的圖像,由於沒有填充(12-5 + 1 = 8)。
然而,因爲圖像有3個通道,咱們的卷積核也須要有3個通道。 這就意味着,每次卷積核移動時,咱們實際上執行5x5x3 = 75次乘法,而不是進行5x5 = 25次乘法。
和二維中的狀況同樣,咱們每25個像素進行一次標量矩陣乘法,輸出1個數字。通過5x5x3的卷積核後,12x12x3的圖像將成爲8x8x1的圖像。
圖4:具備8x8x1輸出的標準卷積
若是咱們想增長輸出圖像中的信道數量呢?若是咱們想要8x8x256的輸出呢?
好吧,咱們能夠建立256個卷積核來建立256個8x8x1圖像,而後將它們堆疊在一塊兒即可建立8x8x256的圖像輸出。
圖5:擁有8x8x256輸出的標準卷積
這就是標準卷積的工做原理。我喜歡把它想象成一個函數:12x12x3-(5x5x3x256)->12x12x256(其中5x5x3x256表示內核的高度、寬度、輸入信道數和輸出信道數)。並非說這不是矩陣乘法;咱們不是將整個圖像乘以卷積核,而是將卷積核移動到圖像的每一個部分,並分別乘以圖像的一小部分。
深度可分離卷積的過程能夠分爲兩部分:深度卷積(depthwise convolution)和逐點卷積(pointwise convolution)。
在第一部分,深度卷積中,咱們在不改變深度的狀況下對輸入圖像進行卷積。咱們使用3個形狀爲5x5x1的內核。
視頻1:經過一個3通道的圖像迭代3個內核:
https://www.youtube.com/watch?v=D_VJoaSew7Q
圖6:深度卷積,使用3個內核將12x12x3圖像轉換爲8x8x3圖像
每一個5x5x1內核迭代圖像的一個通道(注意:一個通道,不是全部通道),獲得每25個像素組的標量積,獲得一個8x8x1圖像。將這些圖像疊加在一塊兒能夠建立一個8x8x3的圖像。
記住,原始卷積將12x12x3圖像轉換爲8x8x256圖像。目前,深度卷積已經將12x12x3圖像轉換爲8x8x3圖像。如今,咱們須要增長每一個圖像的通道數。
逐點卷積之因此如此命名是由於它使用了一個1x1核函數,或者說是一個遍歷每一個點的核函數。該內核的深度爲輸入圖像有多少通道;在咱們的例子中,是3。所以,咱們經過8x8x3圖像迭代1x1x3內核,獲得8x8x1圖像。
圖7:逐點卷積,將一個3通道的圖像轉換爲一個1通道的圖像
咱們能夠建立256個1x1x3內核,每一個內核輸出一個8x8x1圖像,以獲得形狀爲8x8x256的最終圖像。
圖8:256個核的逐點卷積,輸出256個通道的圖像
就是這樣!咱們把卷積分解成兩部分:深度卷積和逐點卷積。更抽象地說,若是原始卷積函數是12x12x3 - (5x5x3x256)→12x12x256,咱們能夠將這個新的卷積表示爲12x12x3 - (5x5x1x1) - > (1x1x3x256) - >12x12x256。
咱們來計算一下計算機在原始卷積中要作的乘法的個數。有256個5x5x3內核能夠移動8x8次。這是256 x3x5x5x8x8 = 1228800乘法。
可分離卷積呢?在深度卷積中,咱們有3個5x5x1的核它們移動了8x8次。也就是3x5x5x8x8 = 4800乘以。在點態卷積中,咱們有256個1x1x3的核它們移動了8x8次。這是256 x1x1x3x8x8 = 49152乘法。把它們加起來,就是53952次乘法。
52,952比1,228,800小不少。計算量越少,網絡就能在更短的時間內處理更多的數據。
然而,這是如何實現的呢?我第一次遇到這種解釋時,個人直覺並無真正理解它。這兩個卷積不是作一樣的事情嗎?在這兩種狀況下,咱們都經過一個5x5內核傳遞圖像,將其縮小到一個通道,而後將其擴展到256個通道。爲何一個的速度是另外一個的兩倍多?
通過一段時間的思考,我意識到主要的區別是:在普通卷積中,咱們對圖像進行了256次變換。每一個變換都要用到5x5x3x8x8=4800次乘法。在可分離卷積中,咱們只對圖像作一次變換——在深度卷積中。而後,咱們將轉換後的圖像簡單地延長到256通道。不須要一遍又一遍地變換圖像,咱們能夠節省計算能力。
值得注意的是,在Keras和Tensorflow中,都有一個稱爲「深度乘法器」的參數。默認設置爲1。經過改變這個參數,咱們能夠改變深度卷積中輸出通道的數量。例如,若是咱們將深度乘法器設置爲2,每一個5x5x1內核將輸出8x8x2的圖像,使深度卷積的總輸出(堆疊)爲8x8x6,而不是8x8x3。有些人可能會選擇手動設置深度乘法器來增長神經網絡中的參數數量,以便更好地學習更多的特徵。
深度可分離卷積的缺點是什麼?固然!由於它減小了卷積中參數的數量,若是你的網絡已經很小,你可能會獲得太少的參數,你的網絡可能沒法在訓練中正確學習。然而,若是使用得當,它能夠在不顯著下降效率的狀況下提升效率,這使得它成爲一個很是受歡迎的選擇。
最後,因爲逐點卷積使用了這個概念,我想討論一下1x1內核的用法。
一個1x1內核——或者更確切地說,n個1x1xm內核,其中n是輸出通道的數量,m是輸入通道的數量——能夠在可分離卷積以外使用。1x1內核的一個明顯目的是增長或減小圖像的深度。若是你發現卷積有太多或太少的通道,1x1核能夠幫助平衡它。
然而,對我來講,1x1核的主要目的是應用非線性。在神經網絡的每一層以後,咱們均可以應用一個激活層。不管是ReLU、PReLU、Softmax仍是其餘,與卷積層不一樣,激活層是非線性的。直線的線性組合仍然是直線。非線性層擴展了模型的可能性,這也是一般使「深度」網絡優於「寬」網絡的緣由。爲了在不顯著增長參數和計算量的狀況下增長非線性層的數量,咱們能夠應用一個1x1內核並在它以後添加一個激活層。這有助於給網絡增長一層深度。