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