[譯] 淺析深度學習神經網絡的卷積層

照片由 mendhak 拍攝,版權全部。html

卷積和卷積層是卷積神經網絡中使用的主要構建模塊。前端

卷積是將輸入簡單經過濾波器進行激活。重複對輸入使用同一個濾波器獲得的激活後的圖稱爲特徵圖/特徵映射(feature map),表示輸入(好比一張圖像)中檢測到的特徵的位置和強度。android

卷積神經網絡在特定的預測建模問題(如圖像分類)的約束下,能創新的針對訓練數據集並行自動學習大量濾波器。結果是能夠在輸入圖像的任何位置檢測到高度特定的特徵。ios

在本教程中,你將瞭解卷積在卷積神經網絡中是如何工做的。git

完成本教程後,你將知道:github

  • 卷積神經網絡使用濾波器從輸入中獲得特徵映射,該特徵映射彙總了輸入中檢測到的特徵的存在。
  • 濾波器能夠手工設計,例如線條檢測器,但卷積神經網絡的創新是,訓練期間在特定預測問題的背景下學習濾波器。
  • 在卷積神經網絡中如何計算一維和二維卷積層的特徵映射。

讓咱們開始吧。後端

教程概述

本教程分爲四個部分,分別爲:bash

  1. 卷積神經網絡中的卷積
  2. 計算機視覺中的卷積
  3. 學習到的濾波器的能力
  4. 卷積層的樣例

卷積神經網絡中的卷積

卷積神經網絡,簡稱 CNN,是一種專門用於處理二維圖像數據的神經網絡模型,儘管其也可用於一維和三維數據。網絡

卷積神經網絡的核心是卷積層,這也是卷積神經網絡命名的由來。該層執行的操做稱爲「卷積」。app

在卷積神經網絡的語境中,卷積是涵蓋了一組權重與輸入相乘的線性操做,很像傳統的神經網絡。因爲該技術是爲二維輸入設計的,這個乘法會在輸入數據陣列和二維權重陣列之間進行,稱爲濾波器或核。

濾波器小於輸入數據,在濾波器大小的輸入區塊和濾波器之間應用的乘法被稱做點積。點積是濾波器大小的輸入區塊和濾波器之間的對應元素相乘,而後求和產生的單一值。由於它產生單一值,因此該操做一般被稱爲「標積」。

咱們故意使用小於輸入的濾波器,由於它容許相同的濾波器(權重集)在輸入的不一樣點處屢次乘以輸入陣列。具體而言,濾波器從左到右、從上到下,系統地應用於輸入數據的每一個重疊部分或濾波器大小的區塊。

在圖像上系統地應用相同的濾波器是一個強大的想法。若是濾波器設計爲檢測輸入中的特定類型的特徵,那麼在整個輸入圖像上系統地應用該濾波器能有機會在圖像中的任何位置發現該特徵。這種能力一般被稱爲平移不變性,好比說,關注該特徵是否存在,而不是在哪裏存在。

若是咱們更關心某個特徵是否存在而不是存在的確切位置,那麼本地平移不變性會是很是有用的屬性。例如,當斷定圖像是否包含面部時,咱們不須要知道眼睛的像素級準確位置,咱們只須要知道面部左側和右側分別有一隻眼睛。

—— 第 342 頁,深度學習,2016。

將濾波器與輸入陣列相乘一次,可獲得單一值。因爲濾波器屢次應用於輸入陣列,所以結果是一個表示輸入濾波後的二維陣列輸出值,這個結果被稱爲「特徵映射」。

特徵映射建立後,咱們能夠經過非線性函數(例如 ReLU )傳遞特徵映射中的每一個值,就像咱們對全鏈接層的輸出所作的那樣。

對二維輸入建立特徵映射的濾波器示例

對二維輸入建立特徵映射的濾波器示例

若是你來自數字信號處理領域或相關的數學領域,你可能會將矩陣的卷積運算理解爲不一樣的東西。尤爲應用輸入前先翻轉濾波器(核)。理論上,在卷積神經網絡中說的卷積其實是「互相關」。然而在深度學習中,它被稱爲「卷積」操做。

不少機器學習庫實現的互相關被稱爲卷積。

—— 第 333 頁,深度學習,2016。

總之,咱們有一個輸入,例如一個像素值圖像,咱們還有一個濾波器,它也是一組權重,濾波器系統地應用於輸入數據從而建立出特徵映射

計算機視覺中的卷積

對卷積神經網絡來講,用卷積處理圖像數據的想法並不新穎或獨特,它是計算機視覺中的經常使用技術。

歷史上,濾波器是由計算機視覺專家手工設計的,而後將其應用於圖像以產生特徵映射或濾波後的輸出,這在某種程度上使圖像分析更容易。

例如,下面是一個手工 3×3 元素的濾波器,用於檢測垂直線:

0.0, 1.0, 0.0

0.0, 1.0, 0.0

0.0, 1.0, 0.0
複製代碼

將此濾波器應用於圖像將生成僅包含垂直線的特徵映射。這是一個垂直線檢測器。

你能從濾波器的權重值中看到這一點:中心垂直線上的任何像素值都將被正激活,其它側的任何像素值將被負激活。在圖像的像素值上系統地拖拽此濾波器只能突出顯示垂直線像素。

咱們還能夠建立水平線檢測器並將其應用於圖像,例如:

0.0, 0.0, 0.0

1.0, 1.0, 1.0

0.0, 0.0, 0.0
複製代碼

綜合兩個濾波器的結果,好比綜合兩個特徵映射,將會突出顯示圖像中的全部的線。

能夠設計一套數十甚至數百個其它的小型濾波器來檢測圖像中的其它特徵。

在神經網絡中使用卷積運算的創新之處在於,濾波器的值是網絡訓練中須要學習到的權重。

網絡將學習到從輸入中提取的特徵類型。具體而言,在隨機梯度降低的訓練中,網絡定會學習從圖像中提取特徵,該特徵最小化了網絡被訓練要解決的特定任務的損失,例如,提取將圖像分類爲狗或貓最有用的特徵。

在這種狀況下,你會看到這是一個很強大的想法。

學習到的濾波器的能力

學習針對機器學習任務的單個濾波器是一種強大的技術。

然而,卷積神經網絡在實踐中實現了更多。

多個濾波器

卷積神經網絡不僅學習單個濾波器。事實上,它們對給定輸入並行學習多個特徵。

例如,對於給定輸入,卷積層一般並行地學習 32 到 512 個濾波器。

這樣提供給模型 32 甚至 512 種不一樣的從輸入中提取特徵的方式,或者說「學習看」的許多不一樣方式,以及訓練後「」輸入數據的許多不一樣方式。

這種多樣性容許定製化,好比不只是線條,還有特定訓練數據中的特定線條。

多個通道

彩色圖像具備多個通道,一般每一個顏色通道有一個,例如紅色,綠色和藍色。

從數據的角度來看,這意味着做爲輸入的單個圖像在模型上實際是三個圖像。

濾波器必須始終具備與輸入相同的通道數量,一般稱爲「深度」。若是輸入圖像有 3 個通道(深度爲 3),則應用於該圖像的濾波器也必須有 3 個通道(深度爲3).這種狀況下,一個 3×3 濾波器實際上行、列和深度爲 3x3x3 或 [3, 3, 3]。不管輸入和濾波器的深度如何,都使用點積運算將濾波器應用於輸入來產生單一值。

這意味着若是卷積層具備 32 個濾波器,則這 32 個濾波器對二維圖像輸入不只是二維的,仍是三維的,對於三個通道中的每個都具備特定的濾波器權重。然而,每一個濾波器都會生成一個特徵映射,這意味着對於建立的32個特徵映射,應用 32 個濾波器的卷積層的輸出深度爲 32。

多個層

卷積層不只應用於輸入數據如原始像素值,也能夠應用於其餘層的輸出。

卷積層的堆疊容許輸入的層次分解。

考慮直接對原始像素值進行操做的濾波器將學習提取低級特徵,例如線條。

在第一線層的輸出上操做的濾波器可能提取綜合低級特徵的特徵,好比可表示形狀的多條線的特徵。

這個過程會一直持續到很是深的層,提取面部、動物、房屋等。

這些正是咱們在實踐中看到的。隨着網絡深度的增長,特徵的抽取會愈來愈高階。

卷積層的樣例

深度學習庫 Keras 提供了一系列卷積層。

經過看一些人爲數據和手工濾波器的樣例,咱們能夠更好地理解卷積運算。

在本節中,咱們將同時研究一維卷積層和二維卷積層的例子,二者都具體化了卷積操做,也提供了使用 Keras 層的示範。

一維卷積層的樣例

咱們能夠定義一個具備八個元素的一維輸入,正中間兩個凸起元素值爲 1.0,其他元素值爲 0.0。

[0, 0, 0, 1, 1, 0, 0, 0]
複製代碼

對於一維卷積層,Keras 的輸入必須是三維的。

第一維指每一個輸入樣本,在本例中咱們只有一個樣本。第二個維度指每一個樣本的長度,在本例中長度是 8。第三維指每一個樣本中的通道數,在本例中咱們只有一個通道。

所以,輸入陣列的 shape 爲 [1, 8, 1]。

# define input data
data  =  asarray([0,  0,  0,  1,  1,  0,  0,  0])
data  =  data.reshape(1,  8,  1)
複製代碼

咱們將定義一個模型,其輸入樣本的 shape 爲 [8, 1]。

該模型將具備一個濾波器,shape 爲 3,或者說三個元素寬。Keras 將濾波器的 shape 稱爲 kernel_size

# create model
model  =  Sequential()
model.add(Conv1D(1,  3,  input_shape=(8,  1)))
複製代碼

默認狀況下,卷積層中的濾波器使用隨機權重進行初始化。在這我的爲例子中,咱們將手動設定單個濾波器的權重。咱們將定義一個可以檢測凸起的濾波器,這是一個由低輸入值包圍的高輸入值,正如咱們在輸入示例中定義的那樣。

咱們將三元素濾波器定義以下:

[0, 1, 0]
複製代碼

卷積層還具備誤差輸入值,該值也須要咱們設置一個爲 0 的權重。

所以,咱們能夠強制咱們的一維卷積層的權重使用以下所示的手工濾波器:

# define a vertical line detector
weights = [asarray([[[0]],[[1]],[[0]]]), asarray([0.0])]
# store the weights in the model
model.set_weights(weights)
複製代碼

權重必須以行、列、通道的三維結構被設定,濾波器有一行、三列、和一個通道。

咱們能夠檢索權重並確認它們被正確設置。

# confirm they were stored
print(model.get_weights())
複製代碼

最後,咱們可將單個濾波器應用於輸入數據。

咱們能夠經過在模型上調用 predict() 函數來實現這一點。這將直接返回特徵映射:這是在輸入序列中系統地應用濾波器的輸出。

# apply filter to input data
yhat  =  model.predict(data)
print(yhat)
複製代碼

將全部這些結合在一塊兒,完整的樣例以下所列。

# example of calculation 1d convolutions
from numpy import asarray
from keras.models import Sequential
from keras.layers import Conv1D
# define input data
data = asarray([0, 0, 0, 1, 1, 0, 0, 0])
data = data.reshape(1, 8, 1)
# create model
model = Sequential()
model.add(Conv1D(1, 3, input_shape=(8, 1)))
# define a vertical line detector
weights = [asarray([[[0]],[[1]],[[0]]]), asarray([0.0])]
# store the weights in the model
model.set_weights(weights)
# confirm they were stored
print(model.get_weights())
# apply filter to input data
yhat = model.predict(data)
print(yhat)
複製代碼

運行該樣例,首先打印網絡的權重,這證明了咱們的手工濾波器在模型中是按照咱們的預期設置的。

接下來,濾波器應用到輸入模式,計算並顯示出特徵映射。咱們能夠從特徵映射的值中看到凸起被正確檢測到。

[array([[[0.]],
       [[1.]],
       [[0.]]], dtype=float32), array([0.], dtype=float32)]

[[[0.]
  [0.]
  [1.]
  [1.]
  [0.]
  [0.]]]
複製代碼

讓咱們仔細看看發生了什麼。

回想一下,輸入是一個八元素向量,其值爲:[0, 0, 0, 1, 1, 0, 0, 0]。

首先,經過計算點積(「.」運算符)將三元素濾波器 [0, 1, 0] 應用於輸入的前三個輸入 [0, 0, 0],獲得特徵映射中的單個輸出值 0。

回想一下,點積是對應元素相乘的總和,在這它是 (0 x 0) + (1 x 0) + (0 x 0) = 0。在 NumPy 中,這能夠手動實現爲:

from numpy import asarray
print(asarray([0, 1, 0]).dot(asarray([0, 0, 0])))
複製代碼

在咱們的手動示例中,具體以下:

[0, 1, 0] . [0, 0, 0] = 0
複製代碼

而後濾波器沿着輸入序列的一個元素移動,並重復該過程。具體而言,在索引 1,2 和 3 處對輸入序列應用相同的濾波器,獲得特徵映射中的輸出爲 0。

[0, 1, 0] . [0, 0, 1] = 0
複製代碼

咱們是系統的,因此再一次,濾波器沿着輸入的另外一個元素移動,並應用於索引 二、3 和 4 處的輸入。此次在特徵映射中輸出值是 1。咱們檢測到該特徵並相應的激活。

[0, 1, 0] . [0, 1, 1] = 1
複製代碼

重複該過程,直到咱們計算出整個特徵映射。

[0, 0, 1, 1, 0, 0]
複製代碼

請注意,特徵映射有六個元素,而咱們的輸入有八個元素。這是濾波器應用於輸入序列的手工結果。還有其它方法能夠將濾波器應用於輸入序列可獲得不一樣 shape 的特徵映射,例如填充,但咱們不會在本文中討論這些方法。

你能夠想象,經過不一樣的輸入,咱們能夠檢測到具備不一樣強度的特徵,且在濾波器中具備不一樣的權重,那麼咱們將檢測到輸入序列中的不一樣特徵。

二維卷積層的樣例

咱們能夠將上一節的凸起檢測樣例擴展爲二維圖像的垂直線檢測器。

一樣的,咱們能夠約束輸入,在這裏爲一個具備單個通道(如灰度)的正方形 8×8 像素的輸入圖像,其中間有一個垂直線。

[0, 0, 0, 1, 1, 0, 0, 0]
[0, 0, 0, 1, 1, 0, 0, 0]
[0, 0, 0, 1, 1, 0, 0, 0]
[0, 0, 0, 1, 1, 0, 0, 0]
[0, 0, 0, 1, 1, 0, 0, 0]
[0, 0, 0, 1, 1, 0, 0, 0]
[0, 0, 0, 1, 1, 0, 0, 0]
[0, 0, 0, 1, 1, 0, 0, 0]
複製代碼

Conv2D(二維卷積層)的輸入必須是四維的。

第一個維度定義樣本,在本例中只有一個樣本。第二個維度定義行數,在本例中是 8。第三維定義列數,在本例中仍是 8。最後定義通道數,本例中是 1。

所以,輸入必須具備四維 shape [樣本,列,行,通道],在本例中是 [1, 8, 8, 1]。

# define input data
data = [[0, 0, 0, 1, 1, 0, 0, 0],
		[0, 0, 0, 1, 1, 0, 0, 0],
		[0, 0, 0, 1, 1, 0, 0, 0],
		[0, 0, 0, 1, 1, 0, 0, 0],
		[0, 0, 0, 1, 1, 0, 0, 0],
		[0, 0, 0, 1, 1, 0, 0, 0],
		[0, 0, 0, 1, 1, 0, 0, 0],
		[0, 0, 0, 1, 1, 0, 0, 0]]
data = asarray(data)
data = data.reshape(1, 8, 8, 1)
複製代碼

咱們將用單個濾波器定義 Conv2D,就像咱們在上一節對 Conv1D 樣例所作的那樣。

濾波器將是二維的,一個 shape 3×3 的正方形。該層將指望輸入樣本具備 shape [列,行,通道],在本例中爲 [8, 8, 1]。

# create model
model = Sequential()
model.add(Conv2D(1, (3,3), input_shape=(8, 8, 1)))
複製代碼

咱們將定義一個垂直線檢測器的濾波器來檢測輸入數據中的單個垂直線。

濾波器以下所示:

0, 1, 0
0, 1, 0
0, 1, 0
複製代碼

咱們能夠實現以下:

# define a vertical line detector
detector = [[[[0]],[[1]],[[0]]],
            [[[0]],[[1]],[[0]]],
            [[[0]],[[1]],[[0]]]]
weights = [asarray(detector), asarray([0.0])]
# store the weights in the model
model.set_weights(weights)
# confirm they were stored
print(model.get_weights())
複製代碼

最後,咱們將濾波器應用於輸入圖像,將獲得一個特徵映射,代表對輸入圖像中垂直線的檢測,如咱們但願的那樣。

# apply filter to input data
yhat = model.predict(data)
複製代碼

特徵映射的輸出 shape 將是四維的,[批,行,列,濾波器]。咱們將執行單個批處理,而且咱們有一個濾波器(一個濾波器和一個輸入通道),所以輸出 shape 爲 [1, ?, ?, 1]。咱們能夠完美打印出單個特徵映射的內容,以下所示:

for r in range(yhat.shape[1]):
	# print each column in the row
	print([yhat[0,r,c,0] for c in range(yhat.shape[2])])
複製代碼

將全部這些結合在一塊兒,完整的樣例以下所列。

# example of calculation 2d convolutions
from numpy import asarray
from keras.models import Sequential
from keras.layers import Conv2D
# define input data
data = [[0, 0, 0, 1, 1, 0, 0, 0],
		[0, 0, 0, 1, 1, 0, 0, 0],
		[0, 0, 0, 1, 1, 0, 0, 0],
		[0, 0, 0, 1, 1, 0, 0, 0],
		[0, 0, 0, 1, 1, 0, 0, 0],
		[0, 0, 0, 1, 1, 0, 0, 0],
		[0, 0, 0, 1, 1, 0, 0, 0],
		[0, 0, 0, 1, 1, 0, 0, 0]]
data = asarray(data)
data = data.reshape(1, 8, 8, 1)
# create model
model = Sequential()
model.add(Conv2D(1, (3,3), input_shape=(8, 8, 1)))
# define a vertical line detector
detector = [[[[0]],[[1]],[[0]]],
            [[[0]],[[1]],[[0]]],
            [[[0]],[[1]],[[0]]]]
weights = [asarray(detector), asarray([0.0])]
# store the weights in the model
model.set_weights(weights)
# confirm they were stored
print(model.get_weights())
# apply filter to input data
yhat = model.predict(data)
for r in range(yhat.shape[1]):
	# print each column in the row
	print([yhat[0,r,c,0] for c in range(yhat.shape[2])])
複製代碼

運行該樣例,首先確認手工濾波器已在層權重中被正肯定義。

接下來,打印計算出的特徵映射。從數字的規模咱們能夠看到,濾波器確實在特徵映射的中間檢測到具備單個強激活的垂直線。

[array([[[[0.]],
        [[1.]],
        [[0.]]],
       [[[0.]],
        [[1.]],
        [[0.]]],
       [[[0.]],
        [[1.]],
        [[0.]]]], dtype=float32), array([0.], dtype=float32)]

[0.0, 0.0, 3.0, 3.0, 0.0, 0.0]
[0.0, 0.0, 3.0, 3.0, 0.0, 0.0]
[0.0, 0.0, 3.0, 3.0, 0.0, 0.0]
[0.0, 0.0, 3.0, 3.0, 0.0, 0.0]
[0.0, 0.0, 3.0, 3.0, 0.0, 0.0]
[0.0, 0.0, 3.0, 3.0, 0.0, 0.0]
複製代碼

讓咱們仔細看看計算了什麼。

首先,將濾波器應用於圖像的左上角,或者說 3×3 元素的圖像區塊。理論上,圖像區塊是三維的,具備單個通道,濾波器具備相同的尺寸。在 NumPy 中咱們不能使用 dot() 函數實現它,咱們必須使用 tensordot() 函數代替,以便咱們能夠適當地對全部維度求和,例如:

from numpy import asarray
from numpy import tensordot
m1 = asarray([[0, 1, 0],
			  [0, 1, 0],
			  [0, 1, 0]])
m2 = asarray([[0, 0, 0],
			  [0, 0, 0],
			  [0, 0, 0]])
print(tensordot(m1, m2))
複製代碼

該計算獲得單個輸出值 0.0,也就是未檢測到特徵。這給了咱們特徵映射左上角的第一個元素。

手動以下所示:

0, 1, 0     0, 0, 0
0, 1, 0  .  0, 0, 0 = 0
0, 1, 0     0, 0, 0
複製代碼

濾波器沿着一列向左移動,並重復該過程。一樣的,未檢測到該特徵。

0, 1, 0     0, 0, 1
0, 1, 0  .  0, 0, 1 = 0
0, 1, 0     0, 0, 1
複製代碼

再向左移動到下一列,第一次檢測到該特徵並強激活。

0, 1, 0     0, 1, 1
0, 1, 0  .  0, 1, 1 = 3
0, 1, 0     0, 1, 1
複製代碼

重複此過程,直到濾波器的邊緣位於輸入圖像的邊緣或最後一列上。這給出了特徵映射的第一個完整行中的最後一個元素。

[0.0, 0.0, 3.0, 3.0, 0.0, 0.0]
複製代碼

而後濾波器向下移動一行並返回到第一列,從左到右重複如上過程,給出特徵映射的第二行。直到濾波器的底部位於輸入圖像的底部或最後一行。

與上一節同樣,咱們能夠看到特徵映射是一個 6×6 矩陣,比 8×8 的輸入圖像小,由於濾波器應用於輸入圖像的限制。

延伸閱讀

若是你但願更深刻,本節將提供此主題的更多資源。

文章

API

總結

在本教程中,你瞭解到卷積在卷積神經網絡中是如何工做的。

具體來講,你學到了:

  • 卷積神經網絡使用濾波器從輸入中獲得特徵映射,該特徵映射彙總了輸入中檢測到的特徵的存在。
  • 濾波器能夠手工設計,例如線條檢測器,但卷積神經網絡的創新是,在訓練期間在特定預測問題的背景下學習濾波器。
  • 在卷積神經網絡中如何計算一維和二維卷積層的特徵映射。

你有什麼問題? 在下面的評論中提出您的問題,我會盡力回答。

若是發現譯文存在錯誤或其餘須要改進的地方,歡迎到 掘金翻譯計劃 對譯文進行修改並 PR,也可得到相應獎勵積分。文章開頭的 本文永久連接 即爲本文在 GitHub 上的 MarkDown 連接。


掘金翻譯計劃 是一個翻譯優質互聯網技術文章的社區,文章來源爲 掘金 上的英文分享文章。內容覆蓋 AndroidiOS前端後端區塊鏈產品設計人工智能等領域,想要查看更多優質譯文請持續關注 掘金翻譯計劃官方微博知乎專欄

相關文章
相關標籤/搜索