Chapter 13. Convolutional Neural Networks

本篇文章是個人翻譯的,如有商業用途,請通知本人謝謝.

Convolutional Layer

CNN最重要的組成部分是卷積層:第一卷積層中的神經元不是連接到輸入圖像中的每一個像素(就像它們在前面的章節中那樣),而是僅僅連接到它們的局部感受野中的像素(參見圖13-2)。 進而,第二卷積層中的每個神經元只與位於第一層中的小矩形內的神經元連接。 這種架構允許網絡專注於第一隱藏層中的低級特徵,然後將其組裝成下一隱藏層中的高級特徵,等等。 這種層次結構在現實世界的圖像中是很常見的,這也是CNN在圖像識別方面效果很好的原因之一。


到目前爲止,我們所看到的所有多層神經網絡都有由一長串神經元組成的層,在輸入到神經網絡之前我們必須將輸入圖像壓縮成1D。 現在,每個圖層都以2D表示,這使得神經元與其相應的輸入進行匹配變得更加容易。


位於給定層的第i行第j列的神經元連接到位於前一層中的神經元的輸出的第i行到第行,第j列到第列.fh和fw是局部感受野的高度和寬度(見圖13-3)。 爲了使圖層具有與前一圖層相同的高度和寬度,通常在輸入周圍添加零,如圖所示。 這被稱爲零填充.


如圖13-4所示,通過將局部感受野隔開,還可以將較大的輸入層連接到更小的層。 兩個連續的感受野之間的距離被稱爲步幅。 在圖中,一個5×7的輸入層(加零填充)連接到一個3×4層,使用3×3的卷積核和一個步幅爲2(在這個例子中,步幅在兩個方向是相同的,但是它並不一定總是如此)。 位於上層第i行第j列的神經元與位於前一層中的神經元的輸出連接的行,第列, Sh和Sw是垂直和水平的步幅。




Filters(卷積核)

神經元的權重可以表示爲局部感受野大小的小圖像。 例如,圖13-5顯示了兩個可能的權重集,稱爲flters(或卷積核)。第一個表示爲中間有一條垂直的白線的黑色正方形(除了中間一列外,這是一個充滿0的7×7矩陣,除了中央垂直線是1)。 使用這些權重的神經元會忽略他們的局部感受野的一切,除了中央垂直線(因爲所有的inputs將得到0乘,除位於中央垂直線的)。第二個卷積核是一個黑色的正方形,中間有一條水平的白線。 再一次,使用這些權重的神經元將忽略除了中心水平線之外的局部感受野中的一切。

現在,如果一個圖層中的所有神經元都使用相同的垂直線濾波器(以及相同的偏置項),並且將網絡輸入到圖13-5(底部圖像)中所示的輸入圖像,則該圖層將輸出左上圖像。 請注意,垂直的白線得到增強,其餘的變得模糊。 類似地,如果所有的神經元都使用水平線濾波器,右上角的圖像就是你所得到的。 注意到水平的白線得到增強,其餘的則被模糊了。因此,使用相同濾波器的一個充滿神經元的圖層將爲您提供一個特徵圖,該特徵圖突出顯示圖像中與濾波器最相似的區域。 在訓練過程中,CNN爲其任務找到最有用的過濾器,並學習將它們組合成更復雜的模式(例如,交叉是圖像中垂直過濾器和水平過濾器都活動的區域)。


Stacking Multiple Feature Maps(疊加的多個特徵圖)


到目前爲止,爲了簡單起見,我們已經將每個卷積層表示爲一個薄的二維層,但是實際上它是由幾個相同大小的特徵圖組成的,所以它在3D中被更精確地表示(見圖13-6)。 在一個特徵映射中,所有神經元共享相同的參數(權值共享)(權重和偏置),但是不同的特徵映射可能具有不同的參數。 神經元的感受野與前面描述的相同,但是它延伸到所有先前的層的特徵圖。 簡而言之,卷積層同時對其輸入應用多個濾波器,使其能夠檢測輸入中的任何位置的多個特徵。

事實上,特徵地圖中的所有神經元共享相同的參數會顯着減少模型中的參數數量,但最重要的是,一旦CNN學會識別一個位置的模式,就可以在任何其他位置識別它。 相比之下,一旦一個常規DNN學會識別一個位置的模式,它只能在該特定位置識別它。

而且,輸入圖像也由多個子圖層組成:每個顏色通道一個。 通常有三種:紅色,綠色和藍色(RGB)。 灰度圖像只有一個通道,但是一些圖像可能更多 - 例如捕捉額外光頻(如紅外線)的衛星圖像。

具體地,位於給定卷積層L中的特徵映射k的i行,j列中的神經元連接到前一層(L-1)位於行,列的神經元的輸出.請注意,位於同一行第i列和第j列但位於不同特徵映射中的所有神經元都連接到上一層中完全相同神經元的輸出。

公式13-1在一個總結前面解釋的大的數學公式:它展示瞭如何計算卷積層中給定神經元的輸出。它是計算所有投入的加權總並且加上偏置。



  • 是卷積層(L層)特徵映射k中位於第i行第j列的神經元的輸出.
  • 如前所述,是垂直和水平的步幅,是感受野的高度和寬度,是前一層(第l - 1層)的特徵圖的數量。
  • 是位於層L-1,i'行,j'列,特徵圖k'(或者如果前一層是輸入層的通道k')的神經元的輸出。
  • 是特徵映射k的偏置項(在L層中)。 您可以將其視爲調整特徵映射k的整體亮度的旋鈕。
  • 是層L的特徵映射k中的任何神經元與位於行u,列v(相對於神經元的感受野)的輸入之間的連接權重,以及特徵映射k'。

TensorFlow Implementation (TensorFlow實現)
在張量流中,3D張量的每個輸入圖像通常被表示爲形狀。 一個小批量被表示爲四維張量的形狀。 卷積層的權重表示爲形狀的四維張量。 卷積層的偏差項簡單地表示爲一維形狀的張量

我們來看一個簡單的例子。 下面的代碼使用Scikit-Learn的load_sample_images()(加載兩個彩色圖像,一個華人廟宇,另一個是一朵花)加載兩個樣本圖像。 然後創建兩個7×7的卷積核(一箇中間是垂直的白線,另一個是水平的白線),並將他們應用到兩張圖形中,使用TensorFlow的conv2d()函數構建的卷積圖層(使用零填充 且步幅爲2)。 最後,繪製其中一個結果特徵圖(類似於圖13-5中的右上圖)。

from sklearn.datasets import load_sample_image
import matplotlib.pyplot as plt
import numpy as np
import tensorflow as tf


if __name__ == '__main__':


    # Load sample images
    china = load_sample_image("china.jpg")
    flower = load_sample_image("flower.jpg")
    dataset = np.array([china, flower], dtype=np.float32)
    batch_size, height, width, channels = dataset.shape

    # Create 2 filters
    filters = np.zeros(shape=(7, 7, channels, 2), dtype=np.float32)
    filters[:, 3, :, 0] = 1  # vertical line
    filters[3, :, :, 1] = 1  # horizontal line

    # Create a graph with input X plus a convolutional layer applying the 2 filters
    X = tf.placeholder(tf.float32, shape=(None, height, width, channels))
    convolution = tf.nn.conv2d(X, filters, strides=[1,2,2,1], padding="SAME")

    with tf.Session() as sess:
        output = sess.run(convolution, feed_dict={X: dataset})

    plt.imshow(output[0, :, :, 1], cmap="gray") # plot 1st image's 2nd feature map
    plt.show()


大部分代碼是不言而喻的,但conv2d()行值得解釋一下: 
  • X是輸入最小批量(4D張量,如前所述)
  • 卷積核是應用的一組卷積核(也是一個4D張量,如前所述)。
  • 步幅是一個四元素的一維數組,其中兩個中心元素是垂直和水平的步幅(sh和sw)。 第一個和最後一個元素現在必須等於1.他們可能有一天會被用來指定批量步長(跳過一些實例)和頻道步幅(跳過上一層的特徵映射或通道)。
  • padding必須是“VALID”或“SAME”:
- 如果設置爲“VALID”,卷積層不使用零填充,並且可能會忽略輸入圖像底部和右側的某些行和列,具體取決於步幅,如圖13-7所示(爲簡單起見, 這裏只顯示水平尺寸,當然,垂直尺寸也適用相同的邏輯)
- 如果設置爲“SAME”,則卷積層在必要時使用零填充。 在這種情況下,輸出神經元的數量等於輸入神經元的數量除以該步幅,向上舍入(在這個例子中,ceil(13/5)= 3)。 然後在輸入周圍儘可能均勻地添加零。

不幸的是,卷積圖層有很多超參數:你必須選擇卷積核的數量,高度和寬度,步幅和填充類型。 與往常一樣,您可以使用交叉驗證來查找正確的超參數值,但這非常耗時。 稍後我們將討論常見的CNN體系結構,以便讓您瞭解超參數值在實踐中的最佳工作方式。


Memory Requirements (內存需求)
CNN的另一個問題是卷積層需要大量的RAM,特別是在訓練期間,因爲反向傳播的反向傳遞需要在正向傳遞期間計算的所有中間值。
例如,考慮具有5×5濾波器的卷積層,輸出200個尺寸爲150×100的特徵圖,步長爲1,使用SAME padding。 如果輸入是150×100 RGB圖像(三個通道),則參數的數量是(5×5×3 + 1)×200 = 15,200(+1對應於偏置項),這跟全連接層比較是相當小的.(具有150×100神經元的全連接層,每個連接到所有150×100×3輸入,將具有150 ^ 2×100 ^ 2×3 = 675,000,000個參數!)然而,200個特徵圖中的每一個包含150×100個神經元,並且這些神經元中的每一個都需要計算其5×5×3 = 75個輸入的權重和:總共2.25億次浮點乘法。不像完全連接的層那麼糟糕,但仍然是計算密集型的。 而且,如果使用32位浮點數來表示特徵映射,則卷積層的輸出將佔用RAM的200×150×100×32 = 9600萬位(大約11.4MB)。 這只是一個例子! 如果培訓批次包含100個實例,則該層將佔用超過1 GB的RAM!
在推理過程中(即對新實例進行預測時),一旦下一層計算完畢,一層所佔用的RAM就可以被釋放,因此只需要兩個連續層所需的RAM數量。 但是在訓練期間,在正向傳遞期間計算的所有內容都需要被保留用於反向傳遞,所以所需的RAM量(至少)是所有層所需的RAM總量。
如果由於內存不足錯誤導致培訓崩潰,則可以嘗試減少小批量大小。 或者,您可以嘗試使用步幅降低維度,或者刪除幾個圖層。 或者你可以嘗試使用16位浮點數而不是32位浮點數。 或者你可以在多個設備上分發CNN。

Pooling Layer (池化層)
一旦你理解了卷積層是如何工作的,池化層很容易掌握。 他們的目標是對輸入圖像進行二次抽樣(即收縮)以減少計算負擔,內存使用量和參數數量(從而限制過度擬合的風險)。 減少輸入圖像的大小也使得神經網絡容忍一點點的圖像移位(位置不變)。
就像在卷積圖層中一樣,池化層中的每個神經元都連接到前一層中有限數量的神經元的輸出,位於一個小的矩形感受域內。 您必須像以前一樣定義其大小,跨度和填充類型。 但是,彙集的神經元沒有權重; 它所做的只是使用聚合函數(如最大值或平均值)來聚合輸入。 圖13-8顯示了最大池層,這是最常見的池化類型。 在這個例子中,我們使用一個2×2的內核,步幅爲2,沒有填充。 請注意,只有每個內核中的最大輸入值纔會進入下一層。 其他輸入被丟棄。

這顯然是一個非常具有破壞性的層次:即使只有一個2×2的內核和一個2的步幅,輸出在兩個方向上都會減小兩倍(所以它的面積將減少四倍),一下減少了75%的輸入值。
池化層通常獨立於每個輸入通道工作,因此輸出深度與輸入深度相同。 接下來可以看到,在這種情況下,圖像的空間維度(高度和寬度)保持不變,但是通道數目可以減少。
在TensorFlow中實現一個最大池層是非常容易的。 以下代碼使用2×2內核創建最大池化層,跨度爲2,沒有填充,然後將其應用於數據集中的所有圖像:

import numpy as np
from sklearn.datasets import load_sample_image
import tensorflow as tf
import matplotlib.pyplot as plt

china = load_sample_image("china.jpg")
flower = load_sample_image("flower.jpg")

dataset = np.array([china, flower], dtype=np.float32)
batch_size, height, width, channels = dataset.shape

# Create 2 filters
filters = np.zeros(shape=(7, 7, channels, 2), dtype=np.float32)
filters[:, 3, :, 0] = 1  # vertical line
filters[3, :, :, 1] = 1  # horizontal line

X = tf.placeholder(tf.float32, shape=(None, height, width, channels))
max_pool = tf.nn.max_pool(X, ksize=[1,2,2,1], strides=[1,2,2,1],padding="VALID")

with tf.Session() as sess:
    output = sess.run(max_pool, feed_dict={X: dataset})

plt.imshow(output[0].astype(np.uint8))  # plot the output for the 1st image
plt.show()

ksize參數包含沿輸入張量的所有四個維度的內核形狀:[批量大小,高度,寬度,通道]。 TensorFlow目前不支持在多個實例上合併,因此ksize的第一個元素必須等於1.此外,它不支持在空間維度(高度和寬度)和深度維度上合併,因此ksize [1] 和ksize [2]都必須等於1,否則ksize [3]必須等於1。
要創建一個平均池層,只需使用avg_pool()函數而不是max_pool()。
現在你知道所有的構建模塊來創建一個卷積神經網絡。 我們來看看如何組裝它們。


CNN Architectures

典型的CNN體系結構將一些卷積層(每一個通常跟着一個ReLU層),然後是一個合併層,然後是另外幾個卷積層(+ ReLU),然後是另一個池化層,等等。 隨着網絡的進展,圖像變得越來越小,但是由於卷積層的緣故,圖像通常也會越來越深(即更多的特徵圖)(見圖13-9)。 在堆棧的頂部,添加由幾個完全連接的層(+ ReLU)組成的常規前饋神經網絡,並且最終層輸出預測(例如,輸出估計類別概率的softmax層)。

一個常見的錯誤是使用太大的卷積內核。 通常可以通過將兩個3×3內核堆疊在一起來獲得與9×9內核相同的效果,計算量更少。
多年來,這種基礎架構的變體已經被開發出來,導致了該領域的驚人進步。 這種進步的一個很好的衡量標準是比賽中的錯誤率,比如ILSVRC ImageNet的挑戰。 在這個比賽中,圖像分類的五大誤差率在五年內從26%下降到僅僅3%以上。 前五位錯誤率是系統前5位預測未包含正確答案的測試圖像的數量。 圖像很大(256像素高),有1000個類,其中一些非常微妙(嘗試區分120個品種)。 查看獲獎作品的演變是瞭解CNN如何工作的好方法。
我們先來看看經典的LeNet-5架構(1998年),然後是ILSVRC挑戰賽的三名獲勝者AlexNet(2012),GoogLeNet(2014)和ResNet(2015)

其他視覺任務
在其他視覺任務中,如物體檢測和定位以及圖像分割,也取得了驚人的進展。 在物體檢測和定位中,神經網絡通常輸出圖像中各種物體周圍的一系列邊界框。 例如,參見Maxine Oquab等人的2015年論文,該論文爲每個客體類別輸出熱圖,或者Russell Stewart等人的2015年論文,該論文結合使用CNN來檢測人臉,並使用遞歸神經網絡來輸出 圍繞它們的一系列邊界框。 在圖像分割中,網絡輸出圖像(通常與輸入大小相同),其中每個像素指示相應輸入像素所屬的對象的類別。 例如,查看Evan Shelhamer等人的2016年論文。

LeNet-5
LeNet-5架構也許是最廣爲人知的CNN架構。 如前所述,它是由Yann LeCun於1998年創建的,廣泛用於手寫數字識別(MNIST)。 它由表13-1所示的層組成。

這裏有一些額外的細節要注意:
  • MNIST圖像是28×28像素,但是它們被補零到32×32像素,並且在被喂到網絡之前被歸一化。 網絡的其餘部分不使用任何填充,這就是爲什麼隨着圖像在網絡中的進展,大小不斷縮小。
  • 平均池化層比平常稍微複雜一些:每個神經元計算輸入的平均值,然後將結果乘以一個可學習的係數(每個特徵圖一個),並添加一個可學習的偏差項(每個特徵圖一個),然後最後應用激活函數。
  • C3地圖中的大多數神經元僅在三個或四個S2地圖(而不是全部六個S2地圖)中連接到神經元。 有關詳細信息,請參閱原始紙張中的表1。
  • 輸出層有點特殊:每個神經元不是計算輸入和權向量的點積,而是輸出其輸入向量和其權向量之間的歐幾里德距離的平方。 每個輸出測量圖像屬於特定數字類別的多少。 交叉熵損失函數現在是首選,因爲它更多地懲罰不好的預測,產生更大的梯度,從而更快地收斂。
Yann LeCun的網站(“LENET”部分)展示了LeNet-5分類數字的很好的演示。

AlexNet 
AlexNet CNN架構贏得了2012年的ImageNet ILSVRC挑戰賽:它實現了前5%的17%的錯誤率,而且後一位錯誤率有26%! 它由Alex Krizhevsky(因此而得名),Ilya Sutskever和Geoffrey Hinton開發。 它與LeNet-5非常相似,只是更大更深,它是第一個將卷積層直接堆疊在一起,而不是在每個卷積層頂部堆疊一個池化層。 表13-2介紹了這種架構。

爲了減少過擬合,作者使用了前面章節中討論的兩種正則化技術:首先他們在訓練期間將丟失率(dropout率爲50%)應用於層F8和F9的輸出。其次,他們通過隨機移動訓練圖像的各種偏移,水平翻轉和改變照明條件來執行數據增強。
AlexNet還在層C1和C3的ReLU步驟之後立即使用競爭標準化步驟,稱爲局部響應標準化。 這種歸一化形式使得在相同的位置的神經元被最強烈的激活但是在相鄰的特徵圖中抑制神經元(在生物神經元中觀察到了這種競爭激活)。 這鼓勵不同的特徵映射專業化,推它們分開,並迫使他們探索更廣泛的功能,最終提升泛化能力。 公式13-2顯示瞭如何應用LRN。

  • 是位於特徵映射i的神經元的標準化輸出,在某行u和列v(注意,在這個等式中我們只考慮位於這個行和列的神經元,所以u和v沒有顯示)。
  • 是在ReLU步驟之後,但在歸一化之前的那個神經元的激活。
  • k,α,β和r是超參數。 k稱爲偏置,r稱爲深度半徑。
  • 是特徵圖的數量。
例如,如果r = 2且神經元具有強激活,則將抑制位於其上下的特徵圖中的神經元的激活。
在AlexNet中,超參數設置如下:r = 2,α= 0.00002,β= 0.75,k = 1。這個步驟可以使用TensorFlow的local_response_normalization()操作來實現。
AlexNet的一個名爲ZF Net的變體由Matthew Zeiler和Rob Fergus開發,贏得了2013年ILSVRC的挑戰。 它基本上是AlexNet的一些調整的超參數(特徵映射的數量,內核大小,步幅等)。

GoogLeNet 
GoogLeNet架構是由Christian Szegedy等人開發的。 來自Google Research,通過低於前5名7%的錯誤率,贏得了ILSVRC 2014的挑戰賽。 這個偉大的表現很大程度上來自《盜夢空間》模塊,它是比以前CNN更深的網絡(見圖13-11)。 這是通過稱爲初始模塊的子網絡實現的,這使得GoogLeNet比以前的架構更有效地使用參數:實際上,GoogLeNet的參數比AlexNet少了10倍(約600萬而不是6000萬)。

盜夢空間模塊的架構如圖13-10所示。
啓動模塊的架構如圖13-10所示。 符號“3×3 + 2(S)”表示該層使用3×3內核,步幅2和相同填充。 輸入信號首先被複制並饋送到四個不同的層。 所有卷積層都使用ReLU激活功能。 請注意,第二組卷積層使用不同的內核大小(1×1,3×3和5×5),允許它們以不同的比例捕獲圖案。 還要注意,每一層都使用1和SAME填充的跨度(即使是最大的池化層),所以它們的輸出全都具有與其輸入相同的高度和寬度。 這使得有可能連接最終深度連續層中沿着深度維度的所有輸出(即,堆疊來自所有四個頂部卷積層的特徵映射)。 這個連接層可以在TensorFlow中使用concat()操作實現,其中axis = 3(axis 3是深度)。
您可能想知道爲什麼初始模塊具有1×1內核的卷積層。 當然這些圖層不能捕獲任何功能,因爲他們一次只能看一個像素? 實際上,這些層次有兩個目的:
首先,它們被配置爲輸出比輸入少得多的特徵圖,所以它們作爲瓶頸層,意味着它們降低了維度。 在3×3和5×5卷積之前,這是特別有用的,因爲這些在計算上是非常耗費內存的層。
簡而言之,您可以將整個“盜夢空間”模塊視爲類固醇卷積層,能夠輸出捕捉各種尺度複雜模式的特徵映射。
每個卷積層的卷積核的數量是一個超參數。 不幸的是,這意味着你有六個超參數來調整你添加的每個初始層。



現在讓我們來看看GoogLeNet CNN的架構(見圖13-11)。 它非常深,我們不得不將它分成三列,但是GoogLeNet實際上是一個高堆棧,包括九個“盜夢空間”模塊(帶有旋轉頂端的框),每個模塊實際上包含三層。 在內核大小之前顯示每個卷積層和每個池化層輸出的特徵映射的數量。 “盜夢空間”模塊中的六個數字表示模塊中每個卷積層輸出的特徵映射的數量(與圖13-10中的順序相同)。 請注意,所有的卷積層都使用ReLU激活功能。
讓我們來過一遍這個網絡:
  • 前兩層將圖像的高度和寬度除以4(使其面積除以16),以減少計算負擔。
  • 然後,局部響應規範化層確保前面的層學習各種各樣的功能(如前所述)
  • 接下來是兩個卷積層,其中第一個像瓶頸層一樣。 正如前面所解釋的,你可以把這一對看作是一個單一的更智能的卷積層。
  • 再次,局部響應標準化層確保了先前的層捕捉各種各樣的模式。
  • 接下來,最大池化層將圖像高度和寬度減少2,再次加快計算速度。
  • 然後是九個“盜夢空間”模塊的高堆棧,與幾個最大池層交織,以降低維度並加速網絡。
  • 接下來,平均池化層使用具有VALID填充的特徵映射的大小的內核,輸出1×1特徵映射:這種令人驚訝的策略被稱爲全局平均共享。 它有效地強制以前的圖層產生特徵圖,這些特徵圖實際上是每個目標類的置信圖(因爲其他類型的功能將被平均步驟破壞)。 這樣就不必在CNN的頂部有幾個完全連接的層(如AlexNet),大大減少了網絡中的參數數量,並限制了過度擬合的風險。
  • 最後一層是不言自明的:正則化drop out,然後是具有softmax激活函數的完全連接層來輸出估計類的概率。
這個圖略有簡化:原來的GoogLeNet架構還包括兩個插在第三和第六個啓動模塊之上的輔助分類器。 它們都由一個平均池層,一個卷積層,兩個完全連接的層和一個softmax激活層組成。 在訓練期間,他們的損失(縮小了70%)加在了整體損失上。 我們的目標是解決消失梯度問題,規範網絡。 但是,結果顯示其效果相對較小。

ResNet
最後但並非最不重要的是,2015年ILSVRC挑戰賽的贏家Kaiming He等人開發的剩餘網絡(或ResNet),該網絡的打敗前5錯誤率低到3.6%,它使用了一個非常深的CNN,由152層組成。 能夠訓練如此深的網絡的關鍵是使用跳過連接(也稱爲快捷連接):喂到一個層的信號也被添加到位於比堆棧高一點的層的輸出。 讓我們看看爲什麼這是有用的.
當訓練一個神經網絡時,目標是使其模擬一個目標函數h(x)。 如果將輸入x添加到網絡的輸出中(即添加跳過連接),那麼網絡將被迫模擬f(x)= h(x) - x而不是h(x)。 這被稱爲殘留學習(見圖13-12)。

當你初始化一個規則的神經網絡時,它的權重接近於零,所以網絡只輸出接近零的值。 如果添加跳過連接,則生成的網絡只輸出其輸入的副本; 換句話說,它最初對身份函數進行建模。 如果目標函數與身份函數非常接近(常常是這種情況),這將大大加快訓練速度。
而且,如果添加了許多跳轉連接,即使幾個層還沒有開始學習,網絡也可以開始進行(見圖13-13)。 由於跳過連接,信號可以很容易地通過整個網絡。 深度剩餘網絡可以看作是一堆剩餘單位,其中每個剩餘單位是一個有跳過連接的小型神經網絡。

現在讓我們看看ResNet的架構(見圖13-14)。 這實際上是令人驚訝的簡單。 它的開始和結束與GoogLeNet完全一樣(除了沒有dropout層),而在兩者之間只是一堆很簡單的殘餘單位。 每個殘差單元由兩個卷積層組成,使用3×3的內核和保存空間維度(步幅1,SAME填充),批量歸一化(BN)和ReLU激活。


需要注意的是特徵圖的數量每隔幾個殘差單位會加倍,同時它們的高度和寬度減半(使用步幅2卷積層)。 發生這種情況時,輸入不能直接添加到剩餘單元的輸出中,因爲它們不具有相同的形狀(例如,此問題影響圖13-14中的虛線箭頭表示的跳過連接)。 爲了解決這個問題,輸入通過一個1×1卷積層,步長2和右側數量的輸出特徵映射(見圖13-15)。


ResNet-34是具有34個層(僅計算卷積層和完全連接層)的ResNet,包含3個剩餘單元輸出64個特徵圖,4個剩餘單元輸出128個特徵圖,6個剩餘單元輸出256個特徵圖,3個剩餘單元輸出512個特徵圖
ResNet比ResNet-152更深,使用稍微不同的剩餘單位。 他們使用三個卷積層,而不是兩個3×3的卷積層(比如說),它們使用三個卷積層:第一個卷積層只有64個特徵映射(少4倍),這是一個瓶頸層(已經討論過) ,然後是具有64個特徵圖的3×3層,最後是具有256個特徵圖(4×64)的另一個1×1卷積層,以恢復原始深度。 ResNet-152包含三個這樣的RU,輸出256個地圖,然後是8個RU,512個地圖,高達36 RU,1024個地圖,最後是3個RU,共2048個地圖。
正如你所看到的,這個領域正在迅速發展,每年都會有各種各樣的架構出現。 一個明顯的趨勢是CNN越來越深入。 他們也越來越輕,需要越來越少的參數。 目前,ResNet架構既是最強大的,也是最簡單的,所以它現在應該是你應該使用的,但是每年都要繼續關注ILSVRC的挑戰。 2016年獲獎者是來自中國的Trimps-Soushen團隊,他們的出錯率驚人的縮減到2.99%。 爲了達到這個目標,他們訓練了以前模型的組合,並將它們合併爲一個整體。 根據任務的不同,降低的錯誤率可能會或可能不值得額外的複雜性。還有其他一些架構可供您參考,特別是VGGNet13(2014年ILSVRC挑戰賽的亞軍)和Inception-v414(將GoGoLeNet和ResNet的思想融合在一起,實現了接近3%的5大誤差 ImageNet分類率)。
實施我們剛剛討論的各種CNN架構真的沒什麼特別的。 我們之前看到如何構建所有的獨立構建模塊,所以現在您只需要組裝它們來創建所需的構架。 我們將在即將開始的練習中構建ResNet-34,您將在Jupyter筆記本中找到完整的工作代碼。

TensorFlow Convolution Operations
TensorFlow還提供了一些其他類型的卷積層:
  • conv1d()爲1D輸入創建一個卷積層。 例如,在自然語言處理中這是有用的,其中句子可以表示爲一維單詞陣列,並且接受場覆蓋一些鄰近單詞。
  • conv3d()創建一個3D輸入的卷積層,如3D PET掃描。
  • atrous_conv2d()創建了一個有趣的卷積層(“àtrous”是法語“with holes”)。 這相當於使用具有通過插入行和列(即,孔)而擴大的濾波器的規則卷積層。 例如,等於[[1,2,3]]的1×3濾波器可以以4的擴張率擴張,導致擴張的濾波器[[1,0,0,0,2,0,0,0,3]]。 這使得卷積層在沒有計算價格的情況下具有更大的局部感受野,並且不使用額外的參數。
  • conv2d_transpose()創建了一個轉置卷積層,有時稱爲去卷積層,它對圖像進行上採樣(這個名稱是非常具有誤導性的,因爲這個層並不執行去卷積,這是一個定義良好的數學運算(卷積的逆)) 。這是通過在輸入之間插入零來實現的,所以你可以把它看作是一個使用分數步長的規則卷積層。例如,在圖像分割中,上採樣是有用的:在典型的CNN中,特徵映射越來越小當通過網絡時,所以如果你想輸出一個與輸入大小相同的圖像,你需要一個上採樣層。
  • depthwise_conv2d()創建一個深度卷積層,將每個濾波器獨立應用於每個單獨的輸入通道。 因此,如果有fn濾波器和fn'輸入通道,那麼這將輸出fn×fn'特徵映射。
  • separable_conv2d()創建一個可分離的卷積層,首先像深度卷積層一樣工作,然後將1×1卷積層應用於結果特徵映射。 這使得可以將濾波器應用於任意的輸入通道組。















發佈了77 篇原創文章 · 獲贊 25 · 訪問量 14萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章