(第一部分 機器學習基礎)
第01章 機器學習概覽
第02章 一個完整的機器學習項目(上)
第02章 一個完整的機器學習項目(下)
第03章 分類
第04章 訓練模型
第05章 支持向量機
第06章 決策樹
第07章 集成學習和隨機森林
第08章 降維
(第二部分 神經網絡和深度學習)
第9章 啟動和運行TensorFlow
第10章 人工神經網絡
第11章 訓練深度神經網絡(上)
第11章 訓練深度神經網絡(下)
第12章 設備和服務器上的分布式 TensorFlow
第13章 卷積神經網絡
第14章 循環(huán)神經網絡
第15章 自編碼器
第16章 強化學習(上)
第16章 強化學習(下)
盡管 IBM 的深藍超級計算機在1996年擊敗了國際象棋世界冠軍 Garry Kasparvo,直到近幾年計算機都不能可靠地完成一些看起來較為復雜的任務,比如判別照片中是否有狗以及識別語音。為什么這些任務對于人類而言如此簡單?答案在于感知主要發(fā)生在我們意識領域之外,在我們大腦中的專門視覺,聽覺和其他感官模塊內。當感官信息達到我們的意識時,它已經被裝飾了高級特征;例如,當你看著一只可愛的小狗的照片時,你不能選擇不看這只小狗,或不注意它的可愛。你也不能解釋你如何認出這是一只可愛的小狗,這對你來說很明顯。因此,我們不能相信我們的主觀經驗:感知并不是微不足道的,理解它我們必須看看感官模塊是如何工作的。
?卷積神經網絡(CNN)是從大腦視覺皮層的研究中出現(xiàn)的,自 20 世紀 80 年代以來它們一直用于圖像識別。在過去的幾年里,由于計算能力的增加,可用訓練數(shù)據(jù)的數(shù)量以及第 11 章介紹的訓練深度網絡的技巧,CNN 致力于在某些復雜的視覺任務中做出超出人類的表現(xiàn)。他們使圖像搜索服務,自動駕駛汽車,視頻自動分類系統(tǒng)等變得強大。此外,CNN 并不局限于視覺感知:它們在其他任務中也很成功,如語音識別或自然語言處理(NLP); 然而,我們現(xiàn)在將專注于視覺應用。
?在本章中,我們將介紹 CNN 的起源,構建它們模塊的外觀以及如何使用 TensorFlow 實現(xiàn)它們。然后我們將介紹一些最好的 CNN 架構。
?
視覺皮層的結構
?David H.Hubel 和 Torsten Wiesel 在 1958 年和 1959 年對貓進行了一系列實驗(以及幾年后在猴子上的實驗),對視覺皮層的結構提供了重要的見解(1981 年作者因此獲得了諾貝爾生理和醫(yī)學獎)。具體來說,他們發(fā)現(xiàn)視皮層中的許多神經元有一個小的局部感受野,這意味著它們只對位于視野中有限的一部分區(qū)域的視覺刺激起作用(見圖 13-1,五個神經元的局部感受野由虛線圓圈表示)。不同神經元的感受野可能重疊,并且它們一起平鋪了整個視野。此外,作者表明,一些神經元只對水平線方向的圖像作出反應,而另一些神經元只對不同方向的線作出反應(兩個神經元可能具有相同的感受野,但對不同方向的線作出反應)。他們還注意到一些神經元具有較大的感受野,并且它們對較復雜的模式作出反應,這些模式是較低層模式的組合。這些觀察結果讓我們想到:更高級別的神經元是基于相鄰低級神經元的輸出(在圖 13-1 中,請注意,每個神經元只與來自前一層的少數(shù)神經元相連)。這個強大的結構能夠檢測視野中任何區(qū)域的各種復雜圖案。
?這些對視覺皮層的研究啟發(fā)了 1980 年推出的新認知機(neocognitron),后者逐漸演變?yōu)槲覀儸F(xiàn)在稱之為卷積神經網絡。一個重要的里程碑是 Yann LeCun,LéonBottou,Yoshua Bengio 和 Patrick Haffner 于 1998 年發(fā)表的一篇論文,該論文引入了著名的 LeNet-5 架構,廣泛用于識別手寫支票號碼。這個架構有一些你已經知道的構建塊,比如完全連接層和 Sigmoid 激活函數(shù),但是它還引入了兩個新的構建塊:卷積層和池化層。現(xiàn)在我們來看看他們。
卷積層
?CNN 最重要的組成部分是卷積層:第一卷積層中的神經元不是連接到輸入圖像中的每一個像素(就像它們在前面的章節(jié)中那樣),而是僅僅連接到它們的局部感受野中的像素(參見圖 13-2)。 進而,第二卷積層中的每個神經元只與位于第一層中的小矩形內的神經元連接。 這種架構允許網絡專注于第一隱藏層中的低級特征,然后將其組裝成下一隱藏層中的高級特征,等等。 這種層次結構在現(xiàn)實世界的圖像中是很常見的,這也是 CNN 在圖像識別方面效果很好的原因之一。
注意:
到目前為止,我們所看到的所有多層神經網絡都有由一長串神經元組成的層,在輸入到神經網絡之前我們必須將輸入圖像壓縮成 1D。 現(xiàn)在,每個圖層都以 2D 表示,這使得神經元與其相應的輸入進行匹配變得更加容易。
?位于給定層的第i
行第j
列的神經元連接到位于前一層中的神經元的輸出的第i行到第 i + fh – 1 行,第j
列到第 j + fw – 1 列。fh
和fw
是局部感受野的高度和寬度(見圖 13-3)。 為了使圖層具有與前一圖層相同的高度和寬度,通常在輸入周圍添加零,如圖所示。 這被稱為零填充.
?如圖 13-4 所示,通過將局部感受野隔開,還可以將較大的輸入層連接到更小的層。 兩個連續(xù)的感受野之間的距離被稱為步幅。 在圖中,一個5×7
的輸入層(加零填充)連接到一個3×4
層,使用3×3
的卷積核和一個步幅為 2(在這個例子中,步幅在兩個方向是相同的,但是它并不一定總是如此)。 位于上層第i
行第j
列的神經元與位于前一層中的神經元的輸出連接的第 i × sh 至 i × sh + fh – 1 行,第 j × sw + fw – 1 列, Sh
和Sw
是垂直和水平的步幅。
過濾器
?神經元的權重可以表示為局部感受野大小的小圖像。 例如,圖 13-5 顯示了兩個可能的權重集,稱為過濾器(或卷積核)。第一個表示為中間有一條垂直的白線的黑色正方形(除了中間一列外,這是一個充滿 0 的7×7
矩陣,除了中央垂直線是 1)。 使用這些權重的神經元會忽略除了中央垂直線以外感受野的一切(因為除位于中央垂直線以外,所有的輸入都將乘 0)。第二個卷積核是一個黑色的正方形,中間有一條水平的白線。 再一次,使用這些權重的神經元將忽略除了中心水平線之外的局部感受野中的一切。
?現(xiàn)在,如果一個圖層中的所有神經元都使用相同的垂直線卷積核(以及相同的偏置項),并且將網絡輸入到圖 13-5(底部圖像)中所示的輸入圖像,則該圖層將輸出左上圖像。 請注意,垂直的白線得到增強,其余的變得模糊。 類似地,如果所有的神經元都使用水平線卷積核,右上角的圖像就是你所得到的。 注意到水平的白線得到增強,其余的則被模糊了。因此,使用相同卷積和的一個充滿神經元的圖層將為您提供一個特征映射,該特征映射突出顯示圖像中與卷積和最相似的區(qū)域。 在訓練過程中,CNN 為其任務找到最有用的卷積和,并學習將它們組合成更復雜的模式(例如,交叉是圖像中垂直卷積和和水平卷積和都激活的區(qū)域)。
疊加的多個特征映射
?到目前為止,為了簡單起見,我們已經將每個卷積層表示為一個薄的二維層,但是實際上它是由幾個相同大小的特征映射組成的,所以使用3D圖表示其會更加準確(見圖 13-6)。 在一個特征映射中,所有神經元共享相同的參數(shù)(權重和偏置,權值共享),但是不同的特征映射可能具有不同的參數(shù)。 神經元的感受野與前面描述的相同,但是它延伸到所有先前的層的特征映射。 簡而言之,卷積層同時對其輸入應用多個卷積核,使其能夠檢測輸入中的任何位置的多個特征。
注意:
?事實上,特征映射中的所有神經元共享相同的參數(shù)會顯著減少模型中的參數(shù)數(shù)量,但最重要的是,一旦 CNN 學會識別一個位置的模式,就可以在任何其他位置識別它。 相比之下,一旦一個常規(guī) DNN 學會識別一個位置的模式,它只能在該特定位置識別它。
?而且,輸入圖像也由多個子圖層組成:每個顏色通道一個。 通常有三種:紅色,綠色和藍色(RGB)。 灰度圖像只有一個通道,但是一些圖像可能更多 - 例如捕捉額外光頻(如紅外線)的衛(wèi)星圖像。
?具體地,位于給定卷積層L中的特征映射k的i行,j列中的神經元連接到前一層(L-1)位于 i × sw 到 i × sw + fw – 1 行,j × sh 到 j × sh + fh – 1 列的神經元的輸出。請注意,位于同一行第i
列和第j
列但位于不同特征映射中的所有神經元都連接到上一層中完全相同神經元的輸出。
?公式 13-1 用一個大數(shù)學公式對前面的內容作了解釋:它展示了如何計算卷積層中給定神經元的輸出。它是計算所有輸入的加權總和,并且加上偏置項。
zi, j, k 是卷積層(L層)特征映射k中位于第
i
行第j
列的神經元的輸出。如前所述,sh 和 sw 是垂直和水平的步幅,fh 和 fw 是感受野的高度和寬度,fn′ 是前一層(第
l - 1
層)的特征映射的數(shù)量。xi′, j′, k′ 是位于層
L-1
,i'
行,j'
列,特征映射k'
(或者如果前一層是輸入層的通道k'
)的神經元的輸出。bk 是特征映射
k
的偏置項(在L
層中)。您可以將其視為調整特征映射k
的整體亮度的旋鈕。
- wu, v, k′ ,k 是層
L
的特征映射k
中的任何神經元與位于行u
,列v
(相對于神經元的感受野)的輸入之間的連接權重,以及特征映射k'。
TensorFlow 實現(xiàn)
?在 Tensorflow 中,每個輸入圖像的通常被表示為三維張量 shape [height, width, channels]。 一個小批次被表示為四維張量 shape [mini-batch size, height, width, channels]。 卷積層的權重被表示為四維張量 [fh, fw, fn, fn′]。 卷積層的偏差項簡單地表示為一維形狀的張量 [fn]。我們來看一個簡單的例子。 下面的代碼使用 Scikit-Learn 的load_sample_images()
(加載兩個彩色圖像,一個中國廟宇,另一個是一朵花)加載兩個樣本圖像。 然后創(chuàng)建兩個7×7
的卷積核(一個中間是垂直的白線,另一個是水平的白線),并將他們應用到兩張圖形中,使用 TensorFlow 的conv2d()
函數(shù)構建的卷積圖層(使用零填充且步幅為 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ù)組,其中兩個中間的值是垂直和水平的步幅(
sh
和sw
)。 第一個和最后一個元素現(xiàn)在必須等于 1。他們可能有一天會被用來指定批量步長(跳過一些實例)和頻道步幅(跳過上一層的特征映射或通道)。-
padding
必須是"VALID"
或"SAME"
:- 如果設置為
"VALID"
,卷積層不使用零填充,并且可能會忽略輸入圖像底部和右側的某些行和列,具體取決于步幅,如圖 13-7 所示(為簡單起見, 這里只顯示水平尺寸,當然,垂直尺寸也適用相同的邏輯) - 如果設置為
"SAME"
,則卷積層在必要時使用零填充。 在這種情況下,輸出神經元的數(shù)量等于輸入神經元的數(shù)量除以該步幅,向上舍入(在這個例子中,ceil(13/5)= 3
)。 然后在輸入周圍盡可能均勻地添加零。
- 如果設置為
不幸的是,卷積圖層有很多超參數(shù):你必須選擇卷積核的數(shù)量,高度和寬度,步幅和填充類型。 與往常一樣,您可以使用交叉驗證來查找正確的超參數(shù)值,但這非常耗時。 稍后我們將討論常見的 CNN 體系結構,以便讓您了解超參數(shù)值在實踐中的最佳工作方式。
內存需求
?CNN 的另一個問題是卷積層需要大量的 RAM,特別是在訓練期間,因為反向傳播需要在正向傳遞期間計算的所有中間值。
?例如,考慮具有5×5
卷積核的卷積層,輸出 200 個尺寸為150×100
的特征映射,步長為 1,使用SAME
填充。 如果輸入是150×100
RGB 圖像(三個通道),則參數(shù)的數(shù)量是(5×5×3 + 1)×200 = 15,200
(+1
對應于偏置項),這跟全連接層比較是相當小的。(具有150×100
神經元的全連接層,每個連接到所有150×100×3
輸入,將具有150 ^ 2×100 ^ 2×3 = 675,000,000
個參數(shù)!)然而,200 個特征映射中的每一個包含150×100
個神經元,并且這些神經元中的每一個都需要計算其5×5×3 = 75
個輸入的權重和:總共 2.25 億次浮點乘法。不像全連接層那么糟糕,但仍然是計算密集型的。 而且,如果使用 32 位浮點數(shù)來表示特征映射,則卷積層的輸出將占用 RAM 的200×150×100×32 = 9600萬
位(大約 11.4MB)。 這只是一個例子! 如果訓練批次包含 100 個實例,則該層將占用超過 1 GB 的 RAM!
?在推理過程中(即對新實例進行預測時),一旦下一層計算完畢,一層所占用的 RAM 就可以被釋放,因此只需要兩個連續(xù)層所需的 RAM 數(shù)量。 但是在訓練期間,在正向傳遞期間計算的所有內容都需要被保留用于反向傳遞,所以所需的 RAM 量(至少)是所有層所需的 RAM 總量。
提示:
?如果由于內存不足錯誤導致訓練崩潰,則可以嘗試減少小批量大小。 或者,您可以嘗試使用步幅降低維度,或者刪除幾個圖層。 或者你可以嘗試使用 16 位浮點數(shù)而不是 32 位浮點數(shù)。 或者你可以在多個設備上分發(fā) CNN。
池化層
?一旦你理解了卷積層是如何工作的,池化層很容易掌握。 他們的目標是對輸入圖像進行二次抽樣(即收縮)以減少計算負擔,內存使用量和參數(shù)數(shù)量(從而限制過度擬合的風險)。 減少輸入圖像的大小也使得神經網絡容忍一點點的圖像變換(位置不變)。
?就像在卷積圖層中一樣,池化層中的每個神經元都連接到前一層中有限數(shù)量的神經元的輸出,位于一個小的矩形感受野內。 您必須像以前一樣定義其大小,跨度和填充類型。 但是,匯集的神經元沒有權重; 它所做的只是使用聚合函數(shù)(如最大值或平均值)來聚合輸入。 圖 13-8 顯示了最大池層,這是最常見的池化類型。 在這個例子中,我們使用一個2×2的核,步幅為 2,沒有填充。 請注意,只有每個核中的最大輸入值才會進入下一層。 其他輸入被丟棄。
?這顯然是一個非常具有破壞性的層:即使只有一個2×2
的核和 2 的步幅,輸出在兩個方向上都會減小兩倍(所以它的面積將減少四倍),一下減少了 75% 的輸入值
?池化層通常獨立于每個輸入通道工作,因此輸出深度與輸入深度相同。 接下來可以看到,在這種情況下,圖像的空間維度(高度和寬度)保持不變,但是通道數(shù)目可以減少。
?在 TensorFlow 中實現(xiàn)一個最大池層是非常容易的。 以下代碼使用2×2
核創(chuàng)建最大池化層,步幅為2,沒有填充,然后將其應用于數(shù)據(jù)集中的所有圖像:
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
參數(shù)包含沿輸入張量的所有四維的核形狀:[min-batch, height, width, channels]
。 TensorFlow 目前不支持在多個實例上合并,因此ksize
的第一個元素必須等于 1。此外,它不支持在空間維度(高度和寬度)和深度維度上合并,因此ksize[1]
和ksize[2]
都必須等于 1,否則ksize[3]
必須等于 1。
?要創(chuàng)建一個平均池化層,只需使用avg_pool()
函數(shù)而不是max_pool()
。
?現(xiàn)在你知道所有的構建模塊來創(chuàng)建一個卷積神經網絡。 我們來看看如何組裝它們。
CNN 架構
?典型的 CNN 體系結構有一些卷積層(每一個通常跟著一個 ReLU 層),然后是一個池化層,然后是另外幾個卷積層(+ ReLU),然后是另一個池化層,等等。 隨著網絡的進展,圖像變得越來越小,但是由于卷積層的緣故,圖像通常也會越來越深(即更多的特征映射)(見圖 13-9)。 在堆棧的頂部,添加由幾個全連接層(+ ReLU)組成的常規(guī)前饋神經網絡,并且最終層輸出預測(例如,輸出估計類別概率的 softmax 層)。
提示:
?一個常見的錯誤是使用太大的卷積核。 通常可以通過將兩個3×3
內核堆疊在一起來獲得與9×9
內核相同的效果,計算量更少。
?多年來,這種基礎架構的變體已經被開發(fā)出來,導致了該領域的驚人進步。 這種進步的一個很好的衡量標準是比賽中的錯誤率,比如 ILSVRC ImageNet(http://image-net.org) 的挑戰(zhàn)。 在這個比賽中,圖像分類的五大誤差率在五年內從 26% 下降到僅僅 3% 左右。 前五位錯誤率是系統(tǒng)前5位預測未包含正確答案的測試圖像的數(shù)量。 圖像很大(256 像素),有 1000 個類,其中一些非常微妙(嘗試區(qū)分 120 個狗的品種)。 查看獲獎作品的演變是了解 CNN 如何工作的好方法。
?我們先來看看經典的 LeNet-5 架構(1998 年),然后是 ILSVRC 挑戰(zhàn)賽的三名獲勝者 AlexNet(2012),GoogLeNet(2014)和 ResNet(2015)。
在其他視覺任務中,如物體檢測和定位以及圖像分割,也取得了驚人的進展。 在物體檢測和定位中,神經網絡通常輸出圖像中各種物體周圍的一系列邊界框。 例如,參見Maxine Oquab 等人的 2015 年論文,該論文為每個客體類別輸出熱圖,或者 Russell Stewart 等人的 2015 年論文,該論文結合使用 CNN 來檢測人臉,并使用遞歸神經網絡來輸出 圍繞它們的一系列邊界框。 在圖像分割中,網絡輸出圖像(通常與輸入大小相同),其中每個像素指示相應輸入像素所屬的對象的類別。 例如,查看 Evan Shelhamer 等人的 2016 年論文。
LeNet-5
?LeNet-5 架構也許是最廣為人知的 CNN 架構。 如前所述,它是由 Yann LeCun 于 1998 年創(chuàng)建的,廣泛用于手寫數(shù)字識別(MNIST)。 它由表 13-1 所示的層組成。
有一些額外的細節(jié)要注意:
- MNIST 圖像是
28×28
像素,但是它們被零填充到32×32
像素,并且在被輸入到網絡之前被歸一化。 網絡的其余部分不使用任何填充,這就是為什么隨著圖像在網絡中的進展,大小不斷縮小。 - 平均池化層比平常稍微復雜一些:每個神經元計算輸入的平均值,然后將結果乘以一個可學習的系數(shù)(每個特征映射一個),并添加一個可學習的偏差項(每個特征映射一個),然后最后應用激活函數(shù)。
- C3 圖中的大多數(shù)神經元僅在三個或四個 S2 圖(而不是全部六個 S2 圖)中連接到神經元。有關詳細信息,請參閱原始論文中的表 1。
- 輸出層有點特殊:每個神經元不是計算輸入和權向量的點積,而是輸出其輸入向量和其權向量之間的歐幾里德距離的平方。 每個輸出測量圖像屬于特定數(shù)字類別的多少。 交叉熵損失函數(shù)現(xiàn)在是首選,因為它更多地懲罰不好的預測,產生更大的梯度,從而更快地收斂。
Yann LeCun 的網站(http://yann.lecun.com)(“LENET”部分)展示了 LeNet-5 分類數(shù)字的很好的演示。
AlexNet
?AlexNet CNN 架構贏得了 2012 年的 ImageNet ILSVRC 挑戰(zhàn)賽:它達到了 17% 的 top-5 的錯誤率,而第二名錯誤率有 26%! 它由 Alex Krizhevsky(因此而得名),Ilya Sutskever 和 Geoffrey Hinton 開發(fā)。 它與 LeNet-5 非常相似,只是更大更深,它是第一個將卷積層直接堆疊在一起,而不是在每個卷積層頂部堆疊一個池化層。 表 13-2 介紹了這種架構。
?為了減少過擬合,作者使用了前面章節(jié)中討論的兩種正則化技術:首先他們在訓練期間將丟失率(dropout 率為 50%)應用于層 F8 和 F9 的輸出。其次,他們通過隨機對訓練圖像進行各種偏移,水平翻轉和改變照明條件來進行數(shù)據(jù)增強。
?AlexNet 還在層 C1 和 C3 的 ReLU 步驟之后立即使用競爭標準化步驟,稱為局部響應標準化(local response normalization)。 這種標準化形式使得在相同的位置的神經元被最強烈的激活但是在相鄰的特征映射中抑制神經元(在生物神經元中觀察到了這種競爭激活)。 這鼓勵不同的特征映射特殊化,迫使它們分開,并讓他們探索更廣泛的特征,最終提升泛化能力。 公式 13-2 顯示了如何應用 LRN。
- bi 是位于特征映射
i
的神經元的標準化輸出,在某行u
和列v
(注意,在這個等式中我們只考慮位于這個行和列的神經元,所以u
和v
沒有顯示)。 - ai 是在 ReLU 步驟之后,但在歸一化之前的那個神經元的激活。
-
k
,α
,β
和r
是超參數(shù)。k
稱為偏置,r
稱為深度半徑。 - fn 是特征映射的數(shù)量。
?例如,如果r = 2
且神經元具有強激活,則將抑制位于其上下的特征映射中的神經元的激活。
?在 AlexNet 中,超參數(shù)設置如下:r = 2
,α= 0.00002
,β= 0.75
,k = 1
。這個步驟可以使用 TensorFlow 的local_response_normalization()
操作來實現(xiàn)。
?AlexNet 的一個名為 ZF Net 的變體由 Matthew Zeiler 和 Rob Fergus 開發(fā),贏得了 2013 年 ILSVRC 的挑戰(zhàn)。 它本質上是 AlexNet,只做了一些超參數(shù)調整(特征映射的數(shù)量,內核大小,步幅等)。
GoogLeNet
?GoogLeNet 架構是由 Christian Szegedy 等人開發(fā)的。 來自 Google Research,通過低于 7% 的 top-5 錯誤率,贏得了 ILSVRC 2014 的挑戰(zhàn)賽。 這個偉大的表現(xiàn)很大程度上因為它比以前的 CNN 網絡更深(見圖 13-11)。 這是通過稱為初始模塊(inception modules)的子網絡實現(xiàn)的,這使得 GoogLeNet 比以前的架構更有效地使用參數(shù):實際上,GoogLeNet 的參數(shù)比 AlexNet 少了 10 倍(約 600 萬而不是 6000 萬)。
?初始模塊的架構如圖 13-10 所示。 符號3×3 + 2(S)
表示該層使用3×3
內核,步幅 2 和SAME
填充。 輸入信號首先被復制并饋送到四個不同的層。 所有卷積層都使用 ReLU 激活功能。 請注意,第二組卷積層使用不同的內核大小(1×1
,3×3
和5×5
),允許它們以不同的比例捕獲圖案。 還要注意,每一層都使用了跨度為1和SAME填充的(即使是最大的池化層),所以它們的輸出全都具有與其輸入相同的高度和寬度。這使得將所有輸出在最后的深度連接層(depth concat layer)上沿著深度方向堆疊成為可能(即,堆疊來自所有四個頂部卷積層的特征映射)。 這個連接層可以在 TensorFlow 中使用concat()
操作實現(xiàn),其中axis = 3
(軸 3 是深度)。
?您可能想知道為什么初始模塊具有1×1
內核的卷積層。 當然這些圖層不能捕獲任何功能,因為他們一次只能看一個像素? 實際上,這些層次有兩個目的:
?首先,它們被配置為輸出比輸入少得多的特征映射,所以它們作為瓶頸層,意味著它們降低了維度。 在3×3
和5×5
卷積之前,這是特別有用的,因為這些在計算上是非常耗費內存的層。
?其次,每一個卷積層對([1 × 1, 3 × 3]
和[1 × 1, 5 × 5]
表現(xiàn)地像一個強大的卷積層,可以捕捉到更多的復雜的模式。事實上,這一對卷積層不是在圖像上掃過一個簡單的線性分類器(就像單個卷積層一樣),而是在圖像上掃描一個雙層神經網絡。
?簡而言之,您可以將整個初始模塊視為類固醇卷積層,能夠輸出捕捉各種尺度復雜模式的特征映射。
警告:
?每個卷積層的卷積核的數(shù)量是一個超參數(shù)。 不幸的是,這意味著你有六個超參數(shù)來調整你添加的每個初始層。
?現(xiàn)在讓我們來看看 GoogLeNet CNN 的架構(見圖 13-11)。 它非常深,我們不得不將它分成三列,但是 GoogLeNet 實際上是一列,包括九個初始模塊(帶有旋轉頂端的框),每個模塊實際上包含三層。每個卷積層和池化層輸出的特征映射的數(shù)量顯示在內核大小前。 初始模塊中的六個數(shù)字表示模塊中每個卷積層輸出的特征映射的數(shù)量(與圖 13-10 中的順序相同)。 請注意,所有的卷積層都使用 ReLU 激活函數(shù)。
讓我們來過一遍這個網絡:
- 前兩層將圖像的高度和寬度除以 4(使其面積除以 16),以減少計算負擔。
- 然后,局部響應標準化層確保前面的層學習各種各樣的功能(如前所述)
- 接下來是兩個卷積層,其中第一個像瓶頸層一樣。 正如前面所解釋的,你可以把這一對看作是一個單一的更智能的卷積層。
- 再次,局部響應標準化層確保了先前的層捕捉各種各樣的模式。
- 接下來,最大池化層將圖像高度和寬度減少 2,再次加快計算速度。
- 然后是九個初始模塊的堆疊,與幾個最大池層交織,以降低維度并加速網絡。
- 接下來,平均池化層使用具有
VALID
填充的特征映射的大小的內核,輸出1×1
特征映射:這種令人驚訝的策略被稱為全局平均池化。 它有效地強制以前的圖層產生特征映射,這些特征映射實際上是每個目標類的置信圖(因為其他類型的功能將被平均步驟破壞)。 這樣在 CNN 的頂部就不必有有幾個全連接層(如 AlexNet),大大減少了網絡中的參數(shù)數(shù)量,并減少了了過度擬合的風險。 - 最后一層是不言自明的:正則化 drop out,然后是具有 softmax 激活函數(shù)的完全連接層來輸出估計類的概率。
?這個圖略有簡化:原來的 GoogLeNet 架構還包括兩個插在第三和第六個初始模塊之上的輔助分類器。 它們都由一個平均池層,一個卷積層,兩個全連接層和一個 softmax 激活層組成。 在訓練期間,他們的損失(縮小了 70%)加在了整體損失上。 目標是解決消失梯度問題,正則化網絡。 但是,結果顯示其效果相對小。
ResNet
?最后是,2015 年 ILSVRC 挑戰(zhàn)賽的贏家 Kaiming He 等人開發(fā)的 Residual Network(或 ResNet),該網絡的 top-5 誤率低到驚人的 3.6%,它使用了一個非常深的 CNN,由 152 層組成。 能夠訓練如此深的網絡的關鍵是使用跳過連接(skip connection,也稱為快捷連接):一個層的輸入信號也被添加到位于下一層的輸出。 讓我們看看為什么這是有用的。
?當訓練一個神經網絡時,目標是使其模擬一個目標函數(shù)h(x)
。 如果將輸入x添加到網絡的輸出中(即添加跳過連接),那么網絡將被迫模擬f(x)= h(x) - x
而不是h(x)
。 這被稱為殘留學習(見圖 13-12)。
?當你初始化一個普通的神經網絡時,它的權重接近于零,所以網絡只輸出接近零的值。 如果添加跳過連接,則生成的網絡只輸出其輸入的副本; 換句話說,它最初對身份函數(shù)進行建模。 如果目標函數(shù)與身份函數(shù)非常接近(常常是這種情況),這將大大加快訓練速度。
?而且,如果添加了許多跳轉連接,即使幾個層還沒有開始學習,網絡也可以開始進行(見圖 13-13)。 由于跳過連接,信號可以很容易地通過整個網絡。 深度剩余網絡可以看作是一堆剩余單位,其中每個剩余單位是一個有跳過連接的小型神經網絡。
?現(xiàn)在讓我們看看 ResNet 的架構(見圖 13-14)。 這實際上是令人驚訝的簡單。 它的開始和結束與GoogLeNet完全一樣(除了沒有 dropout 層),而在兩者之間只是一堆很簡單的殘余單位。 每個殘差單元由兩個卷積層組成,使用3×3
的內核和保存空間維度(步幅 1,SAME
填充),批量歸一化(BN)和 ReLU 激活。
?需要注意的是特征映射的數(shù)量每隔幾個殘差單位會加倍,同時它們的高度和寬度減半(使用步幅 2 卷積層)。 發(fā)生這種情況時,輸入不能直接添加到剩余單元的輸出中,因為它們不具有相同的形狀(例如,此問題影響圖 13-14 中的虛線箭頭表示的跳過連接)。 為了解決這個問題,輸入通過一個1×1
卷積層,步長2和正確數(shù)量的輸出特征映射(見圖 13-15)。
?ResNet-34 是具有 34 個層(僅計算卷積層和完全連接層)的 ResNet,包含 3 個剩余單元輸出 64 個特征映射,4 個剩余單元輸出 128 個特征映射,6 個剩余單元輸出 256 個特征映射,3 個剩余單元輸出 512 個特征映射。
?ResNet-152 更深,使用稍微不同的剩余單位。 他們使用三個卷積層,而不是兩個 256 個特征映射的3×3
的卷積層,它們使用三個卷積層:第一個卷積層只有 64 個特征映射(少 4 倍),這是一個瓶頸層(已經討論過) ,然后是具有 64 個特征映射的3×3
層,最后是具有 256 個特征映射(4×64
)的另一個1×1
卷積層,以恢復原始深度。ResNet-152 包含三個這樣的剩余單位,輸出 256 個特征映射,然后是 8 個剩余單位,輸出 512 個特征映射,高達 36 個剩余單位,輸出 1024 個特征映射,最后是 3 個剩余單位,輸出 2048 個特征映射。
?正如你所看到的,這個領域正在迅速發(fā)展,每年都會有各種各樣的架構出現(xiàn)。 一個明顯的趨勢是 CNN 越來越深入。 他們也越來越輕量,需要越來越少的參數(shù)。 目前,ResNet 架構既是最強大的,也是最簡單的,所以它現(xiàn)在應該是你應該使用的,但是每年都要繼續(xù)關注 ILSVRC 的挑戰(zhàn)。 2016 年獲獎者是來自中國的 Trimps-Soushen 團隊,他們的出錯率驚人的縮減到 2.99%。 為了達到這個目標,他們訓練了以前模型的組合,并將它們合并為一個整體。 根據(jù)任務的不同,降低的錯誤率可能會或可能不值得額外的復雜性。
?還有其他一些架構可供您參考,特別是 VGGNet(2014 年 ILSVRC 挑戰(zhàn)賽的亞軍)和 Inception-v4(將 GooLeNet 和 ResNet 的思想融合在一起,實現(xiàn)了接近 3% 的 top-5 誤差 ImageNet 分類率)。
?實施我們剛剛討論的各種CNN架構真的沒什么特別的。 我們之前看到如何構建所有的獨立構建模塊,所以現(xiàn)在您只需要組裝它們來創(chuàng)建所需的構架。 我們將在即將開始的練習中構建 ResNet-34,您將在 Jupyter 筆記本中找到完整的工作代碼。
TensorFlow 卷積操作
TensorFlow 還提供了一些其他類型的卷積層:
-
conv1d()
為 1D 輸入創(chuàng)建一個卷積層。 例如,在自然語言處理中這是有用的,其中句子可以表示為一維單詞陣列,并且接受場覆蓋一些鄰近單詞。 -
conv3d()
創(chuàng)建一個 3D 輸入的卷積層,如 3D PET 掃描。 -
atrous_conv2d()
創(chuàng)建了一個 atrous 卷積層(“àtrous”是法語“with holes”)。 這相當于使用具有通過插入行和列(即,孔)而擴大的卷積核的普通卷積層。 例如,等于[[1,2,3]]
的1×3
卷積核可以以4的擴張率擴張,導致擴張的卷積核[[1,0,0,0,2,0,0,0,3]]
。 這使得卷積層在沒有計算價格的情況下具有更大的局部感受野,并且不使用額外的參數(shù)。 -
conv2d_transpose()
創(chuàng)建了一個轉置卷積層,有時稱為去卷積層,它對圖像進行上采樣(這個名稱是非常具有誤導性的,因為這個層并不執(zhí)行去卷積,這是一個定義良好的數(shù)學運算(卷積的逆)) 。這是通過在輸入之間插入零來實現(xiàn)的,所以你可以把它看作是一個使用分數(shù)步長的普通卷積層。例如,在圖像分割中,上采樣是有用的:在典型的CNN中,特征映射越來越小當通過網絡時,所以如果你想輸出一個與輸入大小相同的圖像,你需要一個上采樣層。 -
depthwise_conv2d()
創(chuàng)建一個深度卷積層,將每個卷積核獨立應用于每個單獨的輸入通道。 因此,如果有fn
卷積核和fn'
輸入通道,那么這將輸出fn×fn'
特征映射。 -
separable_conv2d()
創(chuàng)建一個可分離的卷積層,首先像深度卷積層一樣工作,然后將1×1
卷積層應用于結果特征映射。 這使得可以將卷積核應用于任意的輸入通道組。
練習
(這章的負責人沒有翻譯練習題,之后我補上)
(第一部分 機器學習基礎)
第01章 機器學習概覽
第02章 一個完整的機器學習項目(上)
第02章 一個完整的機器學習項目(下)
第03章 分類
第04章 訓練模型
第05章 支持向量機
第06章 決策樹
第07章 集成學習和隨機森林
第08章 降維
(第二部分 神經網絡和深度學習)
第9章 啟動和運行TensorFlow
第10章 人工神經網絡
第11章 訓練深度神經網絡(上)
第11章 訓練深度神經網絡(下)
第12章 設備和服務器上的分布式 TensorFlow
第13章 卷積神經網絡
第14章 循環(huán)神經網絡
第15章 自編碼器
第16章 強化學習(上)
第16章 強化學習(下)
***?
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
- 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
- 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
- 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
- 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
- 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...