第六章:圖像識(shí)別與卷積神經(jīng)網(wǎng)絡(luò)
* 6.1
圖像識(shí)別問(wèn)題簡(jiǎn)介&經(jīng)典數(shù)據(jù)集
* 6.2
卷積神經(jīng)網(wǎng)絡(luò)簡(jiǎn)介
* 6.3
卷積神經(jīng)網(wǎng)絡(luò)常用結(jié)構(gòu)
? ? ? ?* 6.3.1
卷積層
? ? ? ?* 6.3.2
池化層
* 6.4
經(jīng)典卷積網(wǎng)絡(luò)模型
? ? ? ?* 6.4.1
LeNet-5模型
? ? ? ?* 6.4.2
Inception-v3模型
* 6.5
卷積神經(jīng)網(wǎng)絡(luò)遷移學(xué)習(xí)
? ? ? ?* 6.5.1
遷移學(xué)習(xí)介紹
? ? ? ?* 6.5.2
TensorFlow實(shí)現(xiàn)遷移學(xué)習(xí)
在第 5 章中辽俗,通過(guò) MNIST 數(shù)據(jù)集驗(yàn)證了第 4 章介紹的神經(jīng)網(wǎng)絡(luò)設(shè)計(jì)與優(yōu)化的方法蘸劈。
從實(shí)驗(yàn)的結(jié)果可以看出,神經(jīng)網(wǎng)絡(luò)的結(jié)構(gòu)
會(huì)對(duì)神經(jīng)網(wǎng)絡(luò)的準(zhǔn)確率產(chǎn)生巨大的影響。
本章將介 紹一個(gè)非常常用的神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu) 一一卷積神經(jīng)網(wǎng)絡(luò) (CNN: Convolutional Neural Network)
。
卷積神經(jīng)網(wǎng)絡(luò)的應(yīng)用非常廣泛,在自然語(yǔ)言處理展鸡、醫(yī)藥發(fā)現(xiàn)、災(zāi)難氣候發(fā)現(xiàn)甚至圍棋人工智能程序中都有應(yīng)用埃难。
本章將主要通過(guò)卷積神經(jīng)網(wǎng)絡(luò)在圖像識(shí)別上的應(yīng)用來(lái)講解卷積神經(jīng)網(wǎng)絡(luò)的基本原理以及如何使用 TensorFlow 實(shí)現(xiàn)卷積神經(jīng)網(wǎng)絡(luò) 莹弊。
-6.1- 圖像識(shí)別問(wèn)題簡(jiǎn)介&經(jīng)典數(shù)據(jù)集
本節(jié)中,將:
*
介紹圖像識(shí)別領(lǐng)域中需要解決的問(wèn)題
*
介紹圖像識(shí)別領(lǐng)域中經(jīng)典的數(shù)據(jù)集
視覺(jué)是人類認(rèn)識(shí)世界非常重要的一種知覺(jué)涡尘。對(duì)于人類來(lái)說(shuō)忍弛,通過(guò)視覺(jué)來(lái)識(shí)別手寫(xiě)體數(shù) 字、識(shí)別圖片中的 物體或者找出圖片中人臉的輪廓都是非常簡(jiǎn)單的任務(wù)考抄。
然而對(duì)于計(jì)算機(jī)而言细疚,讓計(jì)算機(jī)識(shí)別圖片中的內(nèi)容就不是一件容易的事情了。圖像識(shí)別問(wèn)題希望借助計(jì)算機(jī)程序來(lái)處理川梅、分析和理解圖片中的內(nèi)容疯兼,使得計(jì)算機(jī)可以從圖片中自動(dòng)識(shí)別各種不同模式的目標(biāo)和對(duì)象。比如在第5章中介紹的MNIST數(shù)據(jù)集就是通過(guò)計(jì)算機(jī)來(lái)識(shí)別圖片中的手寫(xiě)體數(shù)字贫途。
圖像識(shí)別問(wèn)題作為人工智能的一個(gè)重要領(lǐng)域吧彪,在最近幾年己經(jīng)取得了很多突破性的進(jìn)展。本章將要介紹的卷積神經(jīng)網(wǎng)絡(luò)就是這些突破性進(jìn)展背后的最主要技術(shù)支持丢早。
MNIST
數(shù)據(jù)集
圖中顯示了圖像識(shí)別的主流技術(shù)在 MNIST 數(shù)據(jù)集上的錯(cuò)誤率隨著年份的發(fā)展趨勢(shì)圖来氧。
圖6-1中最下方的虛線表示人工標(biāo)注的錯(cuò)誤率,其他不同的線段表示了不同算法的錯(cuò)誤率香拉。
從圖6-1上可以看出啦扬,相比其他算法,
卷積神經(jīng)網(wǎng)絡(luò)
可以得到更低的錯(cuò)誤率凫碌。
而且通過(guò)卷積神經(jīng)網(wǎng)絡(luò)達(dá)到的錯(cuò)誤率已經(jīng)非常接近人工標(biāo)注的錯(cuò)誤率了扑毡。
在MNIST數(shù)據(jù)集的一萬(wàn)個(gè)測(cè)試數(shù)據(jù)上,最好的深度學(xué)習(xí)算法只會(huì)比人工識(shí)別多錯(cuò)一張圖片盛险。
CIFAR
數(shù)據(jù)集
MNIST手寫(xiě)體識(shí)別數(shù)據(jù)集是一個(gè)相對(duì)簡(jiǎn)單的數(shù)據(jù)集瞄摊,在其他更加復(fù)雜的圖像識(shí)別數(shù)據(jù)集上勋又,卷積神經(jīng)網(wǎng)絡(luò)
有更加突出的表現(xiàn)。CIFAR數(shù)據(jù)集就是一個(gè)影響力很大的圖像分類數(shù)據(jù)集换帜。
CIFAR數(shù)據(jù)集分為了
CIFAR-10
和CIFAR-100
兩個(gè)問(wèn)題楔壤,它們都是圖像詞典項(xiàng)目(Visual Dictionary)中800萬(wàn)張圖片的一個(gè)子集。
CIFAR數(shù)據(jù)集中的圖片為32×32的彩色圖片惯驼,這些圖片是由Alex Krizhevsky教授蹲嚣、Vinod Nair博士和Geoffrey Hinton教授整理的。
CIFAR-10
問(wèn)題收集了來(lái)自10
個(gè)不同種類的60000張圖片祟牲。
圖6-2的左側(cè)顯示了CIFAR-10數(shù)據(jù)集中的每一個(gè)種類中的一些樣例圖片以及這些種類的類別名稱 隙畜,
圖6-2的右側(cè)給出CIFAR-10中一張飛機(jī)的圖像。因?yàn)閳D像的像素僅為32×32说贝,所以放大之后圖片是比較模糊的议惰,但隱約還是可以看出飛機(jī)的輪廓。
CIFAR官網(wǎng)https://www.cs.toronto.edu/~kriz/cifar.html提供了不同格式的CIFAR數(shù)據(jù)集下載乡恕,具體的數(shù)據(jù)格式這里不再贅述言询。
*
和MNIST數(shù)據(jù)集類似,CIFAR-10中的圖片大小都是固定的且每一張圖片中僅包含一個(gè)種類的實(shí)體傲宜。
*
但和MNIST相比倍试,CIFAR數(shù)據(jù)集最大的區(qū)別在于圖片由黑白變成的彩色,且分類的難度也相對(duì)更高蛋哭。在CIFAR-10數(shù)據(jù)集上县习,人工標(biāo)注的正確率大概為94%,這比MNIST數(shù)據(jù)集上的人工表現(xiàn)要低很多谆趾。
圖6-3給出了MNIST和CIFAR-10數(shù)據(jù)集中比較難以分類的圖片樣例躁愿。
在圖6-3左側(cè)的4張圖片給出了CIFAR-10數(shù)據(jù)集中比較難分類的圖片,直接從圖片上看沪蓬,人類也很難判斷圖片上實(shí)體的類別彤钟。
圖6-3右側(cè)的4張圖片給出了MNIST數(shù)據(jù)集中難度較高的圖片。在這些難度高的圖片上跷叉,人類還是可以有一個(gè)比較準(zhǔn)確的猜測(cè)逸雹。
目前在CIFAR-10數(shù)據(jù)集上最好的圖像識(shí)別算法正確率為 95.59%
達(dá)到這個(gè)正確率的算法同樣使用了卷積神經(jīng)網(wǎng)絡(luò)
ImageNet
數(shù)據(jù)集
無(wú)論是MNIST數(shù)據(jù)集還是CIFAR數(shù)據(jù)集,相比真實(shí)環(huán)境下的圖像識(shí)別問(wèn)題云挟,有2個(gè)最大的問(wèn)題梆砸。
*
第一,現(xiàn)實(shí)生活中的圖片分辨率要遠(yuǎn)高于32×32园欣,而且圖像的分辨率也不會(huì)是同定的帖世。
*
第二,現(xiàn)實(shí)生活中的物體類別很多沸枯,無(wú)論是10種還是100種都遠(yuǎn)遠(yuǎn)不夠日矫,而且一張圖片中不會(huì)只出現(xiàn)一個(gè)種類的物體赂弓。
為了更加貼近真實(shí)環(huán)境下的圖像識(shí)別問(wèn)題,由斯坦福大學(xué)(Stanford University)的李飛飛(Feifei Li)教授帶頭整理的ImageNet
很大程度地解決了這兩個(gè)問(wèn)題哪轿。
ImageNet是一個(gè)基于WordNet(大型英語(yǔ)語(yǔ)義網(wǎng))的大型圖像數(shù)據(jù)庫(kù)盈魁。在ImageNet中,將近1500萬(wàn)圖片被關(guān)聯(lián)到了WordNet的大約20000個(gè)名詞
同義詞集上窃诉。目前每一個(gè)與ImageNet相關(guān)的WordNet同義詞集都代表了現(xiàn)實(shí)世界中的一個(gè)實(shí)體
杨耙,可以被認(rèn)為是分類問(wèn)題中的一個(gè)類別。
ImageNet中的圖片都是從互聯(lián)網(wǎng)上爬取下來(lái)的褐奴,井且通過(guò)亞馬遜的人工標(biāo)注服務(wù)(Amazon Mechanical Turk)將圖片分類到WordNet的同義詞集上按脚。在ImageNet的圖片中于毙,一張圖片中可能出現(xiàn)多個(gè)同義詞集所代表的實(shí)體敦冬。
圖6-4展示了ImageNet中的一張圖片,在這張圖片上用幾個(gè)矩形框出了不同實(shí)體的輪廓唯沮。在物體識(shí)別問(wèn)題中脖旱,一般將用于框出實(shí)體的矩形稱為Bounding Box
。在圖6-4中總共可以找到4個(gè)實(shí)體介蛉,其中有兩把椅子萌庆、一個(gè)人和一條狗。類似圖6-4中所示币旧,ImageNet的部分圖片中的實(shí)體輪廓也被標(biāo)注了出來(lái)践险,以用于更加精確的圖像識(shí)別。
ImageNet每年都舉辦圖像識(shí)別相關(guān)的競(jìng)賽ILSVRC
(lmageNet Large Scale Visual Recognition Challenge)吹菱,而且每年的競(jìng)賽都會(huì)有一些不同的問(wèn)題巍虫,這些問(wèn)題基本涵蓋了圖像識(shí)別的主要研究方向。ImageNet的官網(wǎng)http://www.image-net.org/challenges/LSVRC列出了歷屆ILSVRC競(jìng)賽的題目和數(shù)據(jù)集鳍刷。不同年份的ImageNet比賽提供了不同的數(shù)據(jù)集占遥,本書(shū)將著重介紹使用得最多的ILSVRC2012圖像分類數(shù)據(jù)集。ILSVRC2012圖像分類數(shù)據(jù)集的任務(wù)和CIFAR數(shù)據(jù)集是基本一致的输瓜,也是識(shí)別圖像中的主要物體瓦胎。ILSVRC2012圖像分類數(shù)據(jù)集包含了來(lái)自1000個(gè)類別的120萬(wàn)張圖片,其中每張圖片屬于且只屬于一個(gè)類別尤揣。因?yàn)镮LSVRC2012圖像分類數(shù)據(jù)集中的圖片是直接從互聯(lián)網(wǎng)上爬取得到搔啊,所以圖片的大小從幾千字節(jié)到幾百萬(wàn)字節(jié)不等。
圖6-5給出了不同算法在ImageNet圖像分類數(shù)據(jù)集上的top-5正確率北戏。top-N正確率指的是圖像識(shí)別算法給出前N個(gè)答案中有一個(gè)是正確的概率坯癣。在圖像分類問(wèn)題上,很多學(xué)術(shù)論文都將前N個(gè)答案的正確率作為比較的方法最欠,其中N的取值一般為3或5示罗。
從圖6-5中可以看出惩猫,在更加復(fù)雜的ImageNet問(wèn)題上,基于卷積神經(jīng)網(wǎng)絡(luò)
的圖像識(shí)別算法可以遠(yuǎn)遠(yuǎn)超過(guò)人類的表現(xiàn)蚜点。
在圖6-5的左側(cè)對(duì)比了傳統(tǒng)算法與深度學(xué)習(xí)算法的正確率轧房。從圖中可以看出,深度學(xué)習(xí)绍绘,特別是卷積神經(jīng)網(wǎng)絡(luò)奶镶,給圖像識(shí)別問(wèn)題帶來(lái)了質(zhì)的飛躍。2013年之后陪拘,基本上所有的研究都集中到了深度學(xué)習(xí)算法上厂镇。從6.2節(jié)開(kāi)始將具體介紹卷積神經(jīng)網(wǎng)絡(luò)的基本原理,以及如何通過(guò)TensorFlow實(shí)現(xiàn)卷積神經(jīng)網(wǎng)絡(luò)左刽。
-6.2- 卷積神經(jīng)網(wǎng)絡(luò)簡(jiǎn)介
本節(jié)中捺信,將:
*
介紹卷積神經(jīng)網(wǎng)絡(luò)的主體思想
*
介紹卷積神經(jīng)網(wǎng)絡(luò)的整體架構(gòu)
全連接網(wǎng)絡(luò)
& 卷積網(wǎng)絡(luò)
在6.1節(jié)中介紹圖像識(shí)別問(wèn)題時(shí),已經(jīng)多次提到了卷積神經(jīng)網(wǎng)絡(luò)欠痴。卷積神經(jīng)網(wǎng)絡(luò)在6.1節(jié)中介紹的所有圖像分類數(shù)據(jù)集上有非常突出的表現(xiàn)迄靠。
在前面的章節(jié)中所介紹的神經(jīng)網(wǎng)絡(luò)每?jī)蓪又g的所有結(jié)點(diǎn)都是有邊相連的,所以本書(shū)稱這種網(wǎng)絡(luò)結(jié)構(gòu)為全連接層網(wǎng)絡(luò)
結(jié)構(gòu)喇辽。為了將只包含全連接層的神經(jīng)網(wǎng)絡(luò)與卷積神經(jīng)網(wǎng)絡(luò)
掌挚、循環(huán)神經(jīng)網(wǎng)絡(luò)
區(qū)分開(kāi),本書(shū)將只包含全連接層的神經(jīng)網(wǎng)絡(luò)稱之為全連接神經(jīng)網(wǎng)絡(luò)菩咨。在第4章和第5章中介紹的神經(jīng)網(wǎng)絡(luò)都為全連接神經(jīng)網(wǎng)絡(luò)吠式。
在這一節(jié)中將講解卷積神經(jīng)網(wǎng)絡(luò)與全連接神經(jīng)網(wǎng)絡(luò)的差異,并介紹組成一個(gè)卷積神經(jīng)網(wǎng)絡(luò)的基本網(wǎng)絡(luò)結(jié)構(gòu)抽米。
圖6-6顯示了全連接神經(jīng)網(wǎng)絡(luò)與卷積神經(jīng)網(wǎng)絡(luò)的結(jié)構(gòu)對(duì)比圖特占。
雖然圖6-6中顯示的全連接神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)和卷積神經(jīng)網(wǎng)絡(luò)的結(jié)構(gòu)直觀上差異比較大,但實(shí)際上它們的整體架構(gòu)是非常相似的缨硝。
從圖6-6中可以看出摩钙,卷積神經(jīng)網(wǎng)絡(luò)也是通過(guò)一層一層的節(jié)點(diǎn)組織起來(lái)的。和全連接神經(jīng)網(wǎng)絡(luò)一樣查辩,卷積神經(jīng)網(wǎng)絡(luò)中的每一個(gè)節(jié)點(diǎn)都是一個(gè)神經(jīng)元胖笛。
*
在全連接神經(jīng)網(wǎng)絡(luò)中,每相鄰兩層之間的節(jié)點(diǎn)都
有邊相連宜岛,于是一般會(huì)將每一層全連接層中的節(jié)點(diǎn)組織成一列废恋,這樣方便顯示連接結(jié)構(gòu)界阁。
*
而對(duì)于卷積神經(jīng)網(wǎng)絡(luò)谒撼,相鄰兩層之間只有部分
節(jié)點(diǎn)相連娃弓,為了展示每一層神經(jīng)元的維度,一般會(huì)將每一層卷積層的節(jié)點(diǎn)組織成一個(gè)三維矩陣。
除了結(jié)構(gòu)相似阱佛,卷積神經(jīng)網(wǎng)絡(luò)的輸入輸出以及訓(xùn)練流程與全連接神經(jīng)網(wǎng)絡(luò)也基本一致帖汞。
以圖像分類為例,卷積神經(jīng)網(wǎng)絡(luò)的輸入層就是圖像的原始像素凑术,而輸出層中的每一個(gè)節(jié)點(diǎn)代表了不同類別的可信度翩蘸。這和全連接神經(jīng)網(wǎng)絡(luò)的輸入輸出是一致的。
類似的淮逊,第4章中介紹的損失函數(shù)以及參數(shù)的優(yōu)化過(guò)程也都適用于卷積神經(jīng)網(wǎng)絡(luò)催首。
在后面的章節(jié)中會(huì)看到,在TensorFlow中訓(xùn)練一個(gè)卷積神經(jīng)網(wǎng)絡(luò)的流程和訓(xùn)練一個(gè)全連接神經(jīng)網(wǎng)絡(luò)沒(méi)有任何區(qū)別泄鹏。
卷積神經(jīng)網(wǎng)絡(luò)和全連接神經(jīng)網(wǎng)絡(luò)的唯一區(qū)別就在于神經(jīng)網(wǎng)絡(luò)中相鄰兩層
的連接方式郎任。
圖像數(shù)據(jù)
& 模型參數(shù)
在進(jìn)一步介紹卷積神經(jīng)網(wǎng)絡(luò)的連接結(jié)構(gòu)之前,本節(jié)將先介紹為什么全連接神經(jīng)網(wǎng)絡(luò)無(wú)法很好地處理圖像數(shù)據(jù)备籽。
使用全連接神經(jīng)網(wǎng)絡(luò)處理圖像的最大問(wèn)題在于全連接層的參數(shù)太多
舶治。
對(duì)于MNIST數(shù)據(jù),每一張圖片的大小是28×28×1胶台,其中28×28為圖片的大小歼疮,×1表示圖像是黑白的杂抽,只有一個(gè)色彩通道诈唬。假設(shè)第一層隱藏層的節(jié)點(diǎn)數(shù)為500個(gè),那么一個(gè)全連接層的神經(jīng)網(wǎng)絡(luò)將有28×28×500+500=392500個(gè)參數(shù)缩麸。
當(dāng)圖片更大時(shí)铸磅,比如在CIFAR-10數(shù)據(jù)集中,圖片的大小為32×32×3杭朱,其中32×32表示圖片的大小阅仔,×3表示圖片是通過(guò)紅綠藍(lán)三個(gè)色彩通道(channel)表示的。這樣輸入層就有3072個(gè)節(jié)點(diǎn)弧械,如果第一層全連接層仍然是500個(gè)節(jié)點(diǎn)八酒,那么這一層全鏈接神經(jīng)網(wǎng)絡(luò)將有3072x500+500≈150萬(wàn)個(gè)參數(shù)。
參數(shù)增多除了導(dǎo)致計(jì)算速度減慢刃唐,還很容易導(dǎo)致過(guò)擬合問(wèn)題羞迷。
所以需要一個(gè)更合理的神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)來(lái)有效地減少神經(jīng)網(wǎng)絡(luò)中參數(shù)個(gè)數(shù)。
卷積神經(jīng)網(wǎng)絡(luò)
就可以達(dá)到這個(gè)目的画饥。
卷積神經(jīng)網(wǎng)絡(luò)模型
の架構(gòu)
圖6-7給出了一個(gè)更加具體的卷積神經(jīng)網(wǎng)絡(luò)模型架構(gòu)圖衔瓮。
在卷積神經(jīng)網(wǎng)絡(luò)的前幾層中,每一層的節(jié)點(diǎn)都被組織成一個(gè)三維矩陣抖甘。比如處理CIFAR-10數(shù)據(jù)集中的圖片時(shí)热鞍,可以將輸入層組織成一個(gè)32×32維的三維矩陣。
圖6-7中虛線部分展示了卷積神經(jīng)網(wǎng)絡(luò)的一個(gè)連接示意圖,從圖中可以看出卷積神經(jīng)網(wǎng)絡(luò)中前幾層中每一個(gè)節(jié)點(diǎn)只和上一層中部分的節(jié)點(diǎn)相連薇宠。卷積神經(jīng)網(wǎng)絡(luò)的具體連接方式將在6.3節(jié)中介紹偷办。
一個(gè)卷積神經(jīng)網(wǎng)絡(luò)模型架構(gòu)主要由以下5種結(jié)構(gòu)組成:
*
輸入層
輸入層是整個(gè)神經(jīng)網(wǎng)絡(luò)的輸入,在處理圖像的卷積神經(jīng)網(wǎng)絡(luò)中澄港,它一般代表了一張圖片的像素矩陣爽篷。比如在圖6-7中慢睡,最左側(cè)的三維矩陣就可以代表一張圖片纬纪。其中三維矩陣的長(zhǎng)和寬代表了圖像的大小护姆,而三維矩陣的深度代表了圖像的色彩通道(channel)族阅。比如黑白圖片的深度為1,而在RGB色彩模式下,圖像的深度為3。
從輸入層開(kāi)始腰懂,卷積神經(jīng)網(wǎng)絡(luò)模型通過(guò)不同的神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)將上一層的三維矩陣轉(zhuǎn)化為下一層的三維矩陣,直到最后的全連接層炼列。
*
卷積層
從名字就可以看出,卷積層是一個(gè)卷積神經(jīng)網(wǎng)絡(luò)中最為重要的部分音比。和傳統(tǒng)全連接層不同俭尖,卷積層中每一個(gè)節(jié)點(diǎn)的輸入只是上一層神經(jīng)網(wǎng)絡(luò)的一小塊,這個(gè)小塊常用的大小有3×3或者5×5洞翩。卷積層試圖將神經(jīng)網(wǎng)絡(luò)中的每一小塊進(jìn)行更加深入地分析從而得到抽象程度更高的特征稽犁。
一般來(lái)說(shuō),通過(guò)卷積層處理過(guò)的節(jié)點(diǎn)矩陣會(huì)變得更深骚亿,所以在圖6-7中可以看到經(jīng)過(guò)卷積層之后的節(jié)點(diǎn)矩陣的深度會(huì)增加缭付。
*
池化層(Pooling)
池化層神經(jīng)網(wǎng)絡(luò)不會(huì)改變?nèi)S矩陣的深度,但是它可以縮小矩陣的大小循未。池化操作可以認(rèn)為是將一張分辨率較高的圖片轉(zhuǎn)化為分辨率較低的圖片陷猫。通過(guò)池化層,可以進(jìn)一步縮小最后全連接層中節(jié)點(diǎn)的個(gè)數(shù)的妖,從而達(dá)到減少整個(gè)神經(jīng)網(wǎng)絡(luò)中參數(shù)的目的绣檬。
*
全連接層
如圖6-7所示,在經(jīng)過(guò)多輪卷積層和池化層的處理之后嫂粟,在卷積神經(jīng)網(wǎng)絡(luò)的最后一般會(huì)是由1到2個(gè)全連接層來(lái)給出最后的分類結(jié)果娇未。
經(jīng)過(guò)幾輪卷積層和池化層的處理之后,可以認(rèn)為圖像中的信息已經(jīng)被抽象成了信息含量更高的特征星虹。我們可以將卷積層
和池化層
看成自動(dòng)圖像特征提取
的過(guò)程零抬。
在特征提取完成之后,仍然需要使用全連接層
來(lái)完成分類任務(wù)
宽涌。
*
Softmax層
和第4章中介紹的一樣平夜,Softmax層主要用于分類問(wèn)題。通過(guò)Softmax層卸亮,可以得到當(dāng)前樣例屬于不同種類的概率分布情況忽妒。
在卷積神經(jīng)網(wǎng)絡(luò)中使用到的輸入層、全連接層和Softmax層在第4章中都有過(guò)詳細(xì)的介紹兼贸,這里不再贅述段直。在下面的6.3節(jié)中將詳細(xì)介紹卷積神經(jīng)網(wǎng)絡(luò)中特殊的兩個(gè)網(wǎng)絡(luò)結(jié)構(gòu)一一卷積層
和池化層
。
-6.3- 卷積神經(jīng)網(wǎng)絡(luò)常用結(jié)構(gòu)
本節(jié)中溶诞,將:
*
介紹卷積層
和池化層
的網(wǎng)絡(luò)結(jié)構(gòu)
*
介紹卷積層
和池化層
的前向傳播過(guò)程
*
通過(guò)TensorFlow實(shí)現(xiàn)卷積層
和池化層
鸯檬,(不介紹優(yōu)化卷積神經(jīng)網(wǎng)絡(luò)的數(shù)學(xué)公式)
-6.3.1- 卷積層
本小節(jié)將詳細(xì)介紹卷積層的結(jié)構(gòu)以及其前向傳播的算法
圖6-8中顯示了卷積層神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)中最重要的部分,這個(gè)部分被稱之為過(guò)濾器(filter)
或者內(nèi)核(kernel)
螺垢。因?yàn)門(mén)ensorFlow文檔中將這個(gè)結(jié)構(gòu)稱之為過(guò)濾器(filter)喧务,所以在本書(shū)中將統(tǒng)稱這個(gè)結(jié)構(gòu)為過(guò)濾器颜及。
如圖6-8所示,過(guò)濾器可以將當(dāng)前層神經(jīng)網(wǎng)絡(luò)上的一個(gè)子節(jié)點(diǎn)矩陣轉(zhuǎn)化為
下一層神經(jīng)網(wǎng)絡(luò)上的一個(gè)單位節(jié)點(diǎn)矩陣
蹂楣。單位節(jié)點(diǎn)矩陣指的是一個(gè)長(zhǎng)和寬都為1俏站,但深度不限的節(jié)點(diǎn)矩陣。
filter/kernel的尺寸
&深度
在一個(gè)卷積層中痊土,過(guò)濾器所處理的節(jié)點(diǎn)矩陣的長(zhǎng)和寬
都是由人工指定的肄扎,這個(gè)節(jié)點(diǎn)矩陣的尺寸也被稱之為過(guò)濾器的尺寸
。常用的過(guò)濾器尺寸有3×3或5×5赁酝。因?yàn)檫^(guò)濾器處理的矩陣深度和當(dāng)前層神經(jīng)網(wǎng)絡(luò)節(jié)點(diǎn)矩陣的深度是一致的犯祠,所以雖然節(jié)點(diǎn)矩陣是三維的,但過(guò)濾器的尺寸只需要指定兩個(gè)維度酌呆。
過(guò)濾器中另外一個(gè)需要人工指定的設(shè)置是處理得到的單位節(jié)點(diǎn)矩陣的深度
衡载,這個(gè)設(shè)置稱為過(guò)濾器的深度
。
注意過(guò)濾器的尺寸指的是一個(gè)過(guò)濾器輸入節(jié)點(diǎn)矩陣的大小隙袁,
而深度指的是輸出單位節(jié)點(diǎn)矩陣的深度痰娱。
如圖6-8所示,左側(cè)小矩陣的尺寸為過(guò)濾器的尺寸菩收,而右側(cè)單位矩陣的深度為過(guò)濾器的深度梨睁。
6.4節(jié)將通過(guò)一些經(jīng)典卷積神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)來(lái)了解如何設(shè)置每一層卷積層過(guò)濾器的尺寸和深度坡贺。
filter/kernel的前向傳播過(guò)程
如圖6-8所示箱舞,過(guò)濾器的前向傳播過(guò)程就是通過(guò)左側(cè)小矩陣中的節(jié)點(diǎn)計(jì)算出右側(cè)單位矩陣中節(jié)點(diǎn)的過(guò)程遍坟。為了直觀地解釋過(guò)濾器的前向傳播過(guò)程晴股,在下面的篇幅中將給出一個(gè)具體的樣例。在這個(gè)樣例中將展示如何通過(guò)過(guò)濾器將一個(gè)2×2×3的節(jié)點(diǎn)矩陣變化為一個(gè)1×1×5的單位節(jié)點(diǎn)矩陣队魏。一個(gè)過(guò)濾器的前向傳播過(guò)程和全連接層相似公般,它總共需要個(gè)參數(shù)胡桨,其中最后的+5為偏置項(xiàng)參數(shù)的個(gè)數(shù)昧谊。
假設(shè):
*
使用叫來(lái)表示對(duì)于輸出單位節(jié)點(diǎn)矩陣中的第個(gè)節(jié)點(diǎn)酗捌,過(guò)濾器輸入節(jié)點(diǎn)的權(quán)重,
*
使用表示第個(gè)輸出節(jié)點(diǎn)對(duì)應(yīng)的偏置項(xiàng)參數(shù)
那么:?jiǎn)挝痪仃囍蟹Щ?img class="math-inline" src="https://math.jianshu.com/math?formula=i" alt="i" mathimg="1">個(gè)節(jié)點(diǎn)的取值為:
其中:
*
為激活函數(shù)
*
a_{x,y,z}為filter節(jié)點(diǎn)的取值
圖6-9展示了在給定初烘,和的情況下肾筐,使用ReLU
作為激活函數(shù)時(shí)的計(jì)算過(guò)程缸剪。
*
在圖6-9的左側(cè)給出了和的取值杏节,這里通過(guò)3個(gè)二維矩陣來(lái)表示一個(gè)三維矩陣的取值奋渔,其中每一個(gè)二維矩陣表示三維矩陣在某一個(gè)深度上的取值。
*
圖6-9中·
符號(hào)表示點(diǎn)積蹋半,也就是矩陣中對(duì)應(yīng)元素乘積的和减江。
*
圖6-9的右側(cè)顯示了的計(jì)算過(guò)程辈灼。如果給出 ~ 和 ~ 也榄,那么也可以類似地計(jì)算出 ~ 的取值甜紫。
如果將和組織成兩個(gè)向量囚霸,那么一個(gè)過(guò)濾器的計(jì)算過(guò)程完全可以通過(guò)第3章中介紹的向量乘法來(lái)完成。
以上樣例已經(jīng)介紹了在卷積層中計(jì)算一個(gè)過(guò)濾器的前向傳播過(guò)程额嘿。卷積層結(jié)構(gòu)的前向傳播過(guò)程就是通過(guò)將一個(gè)過(guò)濾器從神經(jīng)網(wǎng)絡(luò)當(dāng)前層的左上角
移動(dòng)到右下角
册养,并且在移動(dòng)中計(jì)算每一個(gè)對(duì)應(yīng)的單位矩陣得到的球拦。
圖6-10展示了卷積層結(jié)構(gòu)前向傳播的過(guò)程刘莹。為了更好地可視化過(guò)濾器的移動(dòng)過(guò)程,圖6-10中使用的節(jié)點(diǎn)矩陣深度都為1扇调。在圖6-10中狼钮,展示了在3×3矩陣上使用2×2過(guò)濾器的卷積層前向傳播過(guò)程熬芜。在這個(gè)過(guò)程中福稳,首先將這個(gè)過(guò)濾器用于左上角子矩陣的圆,然后移動(dòng)到右上角矩陣越妈,再到左下角矩陣,最后到右下角矩陣酌住。過(guò)濾器每移動(dòng)一次酪我,可以計(jì)算得到一個(gè)值(當(dāng)深度為k時(shí)會(huì)計(jì)算出k個(gè)值)祭示。將這些數(shù)值拼接成一個(gè)新的矩陣谴古,就完成了卷積層前向傳播的過(guò)程掰担。圖6-10的右側(cè)顯示了過(guò)濾器在移動(dòng)過(guò)程中計(jì)算得到的結(jié)果與新矩陣中節(jié)點(diǎn)的對(duì)應(yīng)關(guān)系带饱。
當(dāng)過(guò)濾器的大小不為1×1時(shí)勺疼,卷積層前向傳播得到的矩陣的尺寸要小于當(dāng)前層矩陣的尺寸。如圖6-10所示酪耕,當(dāng)前層矩陣的大小為3×3(圖6-10左側(cè)矩陣)迂烁,而通過(guò)卷積層前向傳播算法之后盟步,得到的矩陣大小為2×2(圖6-10右側(cè)矩陣)却盘。
為了避免尺寸的變化黄橘,可以在當(dāng)前層矩陣的邊界上加入全0填充(zero-padding)禀挫。這樣可以使得卷積層前向傳播結(jié)果矩陣的大小和當(dāng)前層矩陣保持一致语婴。圖6-11顯示了使用全0填充后卷積層前向傳播過(guò)程示意圖砰左,從圖中可以看出缠导,加入一層全0填充后,得到的結(jié)構(gòu)矩陣大小就為3×3了憋他。
除了使用全0填充竹挡,還可以通過(guò)設(shè)置過(guò)濾器移動(dòng)的步長(zhǎng)來(lái)調(diào)整結(jié)果矩陣的大小揪罕。在圖6-10和圖6-11中好啰,過(guò)濾器每次都只移動(dòng)一格框往。圖6-12中顯示了當(dāng)移動(dòng)步長(zhǎng)為2且使用全0填充時(shí),卷積層前向傳播的過(guò)程嘁酿。
從圖6-12上可以看出闹司,當(dāng)長(zhǎng)和寬的步長(zhǎng)均為2時(shí)游桩,過(guò)濾器每隔2步計(jì)算一次結(jié)果借卧,所以得到的結(jié)果矩陣的長(zhǎng)和寬也就都只有原來(lái)的一半铐刘。以下公式給出了在同時(shí)使用全0填充時(shí)結(jié)果矩陣的大小影晓。
在圖6-10挂签、圖6-11以及圖6-12中饵婆,只講解了移動(dòng)過(guò)濾器的方式,沒(méi)有涉及過(guò)濾器中的參數(shù)如何設(shè)定灌灾,所以在這些圖片中結(jié)果矩陣中并沒(méi)有填上具體的值紧卒。
filter/kernel的參數(shù)共享
在卷積神經(jīng)網(wǎng)絡(luò)中,每一個(gè)卷積層中使用的過(guò)濾器中的參數(shù)都是一樣的直颅。這是卷積神經(jīng)網(wǎng)絡(luò)一個(gè)非常重要的性質(zhì)功偿。
*
從直觀上理解往堡,共享過(guò)濾器的參數(shù)可以使得圖像上的內(nèi)容不受位置的影響虑灰。以MNIST手寫(xiě)體數(shù)字識(shí)別為例穆咐,無(wú)論數(shù)字“1”出現(xiàn)在左上角還是右下角对湃,圖片的種類都是不變的拍柒。因?yàn)樵谧笊辖呛陀蚁陆鞘褂玫倪^(guò)濾器參數(shù)相同拆讯,所以通過(guò)卷積層之后無(wú)論數(shù)字在圖像上的哪個(gè)位置往果,得到的結(jié)果都一樣。
*
共享每一個(gè)卷積層の過(guò)濾器中的參數(shù)可以巨幅減少神經(jīng)網(wǎng)絡(luò)上的參數(shù)堕油。以CIFAR-10問(wèn)題為例掉缺,輸入層矩陣的維度是32x32x3眶明。假設(shè)第一層卷積層使用尺寸為5x5搜囱,深度為16的過(guò)濾器蜀肘,那么這個(gè)卷積層的參數(shù)個(gè)數(shù)為個(gè)扮宠。6.2節(jié)中提到過(guò)坛增,使用500個(gè)隱藏節(jié)點(diǎn)的全連接層將有1.5 百萬(wàn)個(gè)參數(shù)收捣。相比之下,卷積層的參數(shù)個(gè)數(shù)要遠(yuǎn)遠(yuǎn)小于全連接層萝玷。而且卷積層的參數(shù)個(gè)數(shù)和圖片的大小無(wú)關(guān)球碉,它只和過(guò)濾器的尺寸睁冬、深度以及當(dāng)前層節(jié)點(diǎn)矩陣的深度有關(guān)豆拨。這使得卷積神經(jīng)網(wǎng)絡(luò)可以很好地?cái)U(kuò)展到更大的圖像數(shù)據(jù)上施禾。
結(jié)合過(guò)濾器的使用方法和參數(shù)共享的機(jī)制弥搞,圖6-13給出了使用了全0填充攀例、步長(zhǎng)為2的卷積層前向傳播的計(jì)算流程粤铭。圖6-13給出了過(guò)濾器上權(quán)重的取值以及偏置項(xiàng)的取值梆惯,通過(guò)圖6-9中所示的計(jì)算方法加袋,可以得到每一個(gè)格子的具體取值职烧。以下公式給出了左上角格子取值的計(jì)算方法蚀之,其他格子可以依次類推足删。
Tensorflow實(shí)現(xiàn)了卷積層的前向傳播
TensorFlow 對(duì)卷積神經(jīng)網(wǎng)絡(luò)提供非常好的支持失受,以下程序?qū)崿F(xiàn)了一個(gè)卷積層的前向傳播過(guò)程拂到。從以下代碼可以看出兄旬,通過(guò)TensorFlow實(shí)現(xiàn)卷積層是非常方便的领铐。
# 通過(guò)tf.get_variable的方式創(chuàng)建過(guò)濾器的權(quán)重變量和偏置項(xiàng)變量绪撵。
# 上面介紹了卷積層的參數(shù)個(gè)數(shù)只和過(guò)濾器的尺寸音诈、深度以及當(dāng)前層節(jié)點(diǎn)矩陣的深度有關(guān)
# 所以這里聲明的參數(shù)變量是一個(gè)4維矩陣:
# * 前面兩個(gè)維度代表了過(guò)濾器的尺寸
# * 第三個(gè)維度表示當(dāng)前層的深度
# * 第四個(gè)維度表示過(guò)濾器的深度
filter_weight = tf.get_variables(
'weight',
[5, 5, 3, 16],
initializer=tf.truncated_normal_initializer(stddev=0.1)
)
# 和卷積層的權(quán)重類似改艇,當(dāng)前層矩陣上不同位置的偏置項(xiàng)也是共享的
# 所以總有[下一層深度個(gè)]不同的偏置項(xiàng)
# 本樣例代碼中谒兄,16為過(guò)濾器的深度承疲,也是神經(jīng)網(wǎng)絡(luò)中下一層節(jié)點(diǎn)矩陣的深度
biases = tf.get_variable(
'biases',
[16],
initializer=tf.constant_initializer(0.1)
)
# tf.nn.conv2d 提供了一個(gè)非常方便的函數(shù)來(lái)實(shí)現(xiàn)卷積層的前向傳播算法燕鸽。
# * tf.nn.conv2d函數(shù)的第一個(gè)輸入為當(dāng)前層的節(jié)點(diǎn)矩陣
# 注意啊研,這個(gè)矩陣是一個(gè)四維矩陣
# * 后面三個(gè)維度對(duì)應(yīng)一個(gè)節(jié)點(diǎn)矩陣
# * 第一維對(duì)應(yīng)一個(gè)輸入batch党远,比如在輸入層沟娱,input[0,:,:,:]表示第一張圖片input[1,:,:,:]表示第二張圖片济似,以此類推
# * tf.nn.conv2d函數(shù)的第二個(gè)輸入提供了卷積層的參數(shù)
# * tf.nn.conv2d函數(shù)的第三個(gè)輸入為不同維度上的步長(zhǎng)
# 雖然第三個(gè)參數(shù)提供的是一個(gè)長(zhǎng)度為4的數(shù)組砰蠢,但是第一維娩脾、第四維的數(shù)字要求一定是1
# 這是因?yàn)榫矸ekernel的步長(zhǎng)只對(duì)圖片的長(zhǎng)俩功、寬起作用诡蜓,在batch蔓罚、像素通道上的步長(zhǎng)為1
# * tf.nn.conv2d函數(shù)的第四個(gè)輸入是填充(padding)的方法
# TensorFlow 中提供SAME或是VALID兩種選擇
# * SAME表示添加全0填充(如圖6-11所示)
# * VALID表示不添加(如圖6-10所示)
conv = tf.nn.connv2d(
input,
filter_weight,
strides=[1,1,1,1],
padding='SAME'
)
# tf.nn.bias_add提供了一個(gè)方便的函數(shù)給每一個(gè)節(jié)點(diǎn)添加上偏置項(xiàng)
# 注意??這里不能直接用加法豺谈,因?yàn)榫仃嚿喜煌恢蒙系墓?jié)點(diǎn)都要加上同樣的偏置項(xiàng)
# 如圖6-13所示茬末,雖然下一層神經(jīng)網(wǎng)絡(luò)的大小為2×2丽惭,但是偏置項(xiàng)只有一個(gè)數(shù)(因?yàn)樯疃葹?)责掏,而2×2矩陣中的每一個(gè)值都需要加上這個(gè)偏置項(xiàng)换衬。
bias = tf.nn.bias_add(cone, biases)
# 將計(jì)算結(jié)果通過(guò)RELU完成去線性化
actived_conv = tf.nn.relu(bias)
-6.3.2- 池化層
6.2 節(jié)介紹過(guò)卷積神經(jīng)網(wǎng)絡(luò)的大致架構(gòu)萄唇。
從圖6-7中可以看出,在卷積層之間往往會(huì)加上一個(gè)池化層(pooling layer)诅挑。
本節(jié)將具體介紹池化層的結(jié)構(gòu)及作用拔妥,
池化層可以非常有效地縮小矩陣的尺寸没龙,從而減少最后全連接層中的參數(shù)硬纤。
使用池化層既可以加快計(jì)算
速度筝家,也有防止過(guò)擬合
問(wèn)題的作用溪王。
和6.3.1節(jié)中介紹的卷積層類似移国,池化層前向傳播的過(guò)程也是通過(guò)移動(dòng)一個(gè)類似過(guò)濾器的結(jié)構(gòu)完成的迹缀。不過(guò)池化層過(guò)濾器中的計(jì)算不是節(jié)點(diǎn)的加權(quán)和裹芝,而是采用更加簡(jiǎn)單的最大值或者平均值運(yùn)算嫂易。使用最大值操作的池化層被稱之為最大池化層(max pooling)
怜械,這是被使用得最多的池化層結(jié)構(gòu)缕允。使用平均值操作的池化層被稱之為平均池化層(average pooling)
障本。其他池化層在實(shí)踐中使用的比較少驾霜,本書(shū)不做過(guò)多的介紹买置。
與卷積層的過(guò)濾器類似粪糙,池化層的過(guò)濾器也需要人工設(shè)定過(guò)濾器的尺寸、是否使用全0填充以及過(guò)濾器移動(dòng)的步長(zhǎng)等設(shè)置忿项,而且這些設(shè)置的意義也是一樣的蓉冈。卷積層和池化層中過(guò)濾器移動(dòng)的方式是相似的,唯一的區(qū)別在于卷積層使用的過(guò)濾器是橫跨整個(gè)深度的轩触,而池化層使用的過(guò)濾器只影響一個(gè)深度上的節(jié)點(diǎn)。所以池化層的過(guò)濾器除了在長(zhǎng)和寬兩個(gè)維度移動(dòng)怕膛,它還需要在深度這個(gè)維度移動(dòng)熟嫩。
圖6-14展示了一個(gè)最大池化層前向傳播計(jì)算過(guò)程。在圖6-14中褐捻,不同顏色或者不同線段(虛線或者實(shí)線)代表了不同的池化層過(guò)濾器掸茅。從圖6-14中可以看出椅邓,池化層的過(guò)濾器除了在長(zhǎng)和寬的維度上移動(dòng),它還需要在深度的維度上移動(dòng)昧狮。
以下TensorFlow程序?qū)崿F(xiàn)了最大池化層的前向傳播算法:
# tf.nn.max_pool 實(shí)現(xiàn)了最大池化層的前向傳播過(guò)程
# tf.nn.max_pool的參數(shù)和tf.nn.conv2d函數(shù)類似
# ksize提供過(guò)濾器的尺寸
# strides提供步長(zhǎng)信息
# padding提供了是否使用全0填充
pool = tf.nn.max_pool(
actived_conv,
ksize=[1, 3, 3, 1],
strides=[1, 2, 2, 1],
padding='SAME'
)
對(duì)比池化層和卷積層前向傳播在tf中的實(shí)現(xiàn)景馁,可以發(fā)現(xiàn)函數(shù)的參數(shù)形式是相似的。在tf.nn.max_pool()
函數(shù)中:
*
首先需要傳入當(dāng)前層的節(jié)點(diǎn)矩陣
逗鸣,這個(gè)矩陣是一個(gè)四維矩陣合住,格式和tf.nn.conv2d()函數(shù)中的第一個(gè)參數(shù)一致。
*
第二個(gè)參數(shù)為過(guò)濾器的尺寸
撒璧。雖然給出的是一個(gè)長(zhǎng)度為4的一維數(shù)組透葛,但是這個(gè)數(shù)組的第一個(gè)和最后一個(gè)數(shù)必須為1。這意味著池化層的過(guò)濾器是不可以跨不同輸入樣例或者節(jié)點(diǎn)矩陣深度的卿樱。在實(shí)際應(yīng)用中使用得最多的池化層過(guò)濾器尺寸為[1, 2, 2, 1]或者[1, 3, 3, 1]俄烁。
*
第三個(gè)參數(shù)為步長(zhǎng)
哭靖,它和tf.nn.conv2d()函數(shù)中步長(zhǎng)的意義是一樣的,而且第一維和最后一維也只能為1停士。這意味著在TensorFlow中竹观,池化層不能減少節(jié)點(diǎn)矩陣的深度或者輸入樣例的個(gè)數(shù)循捺。
*
最后一個(gè)參數(shù)指定了是否使用全0填充
擂涛。這個(gè)參數(shù)也只有兩種取值:VALID
或者SAME
丢氢,其中VALID表示不使用全0填充,SAME表示使用全0填充裕寨。
TensorFlow還提供了tf.nn.avg_pool()
來(lái)實(shí)現(xiàn)平均池化層浩蓉。tf.nn.avg_pool函數(shù)的調(diào)用格式和tf.nn.max_pool()函數(shù)是一致的。
-6.4- 經(jīng)典卷積網(wǎng)絡(luò)模型
本節(jié)中宾袜,將:
*
介紹兩個(gè)經(jīng)典的卷積神經(jīng)網(wǎng)絡(luò)模型:LeNet-5 模型
妻往、Inception-v3 模型
*
介紹如何設(shè)計(jì)卷積神經(jīng)網(wǎng)絡(luò)的架構(gòu)
,以及如何設(shè)置神經(jīng)網(wǎng)絡(luò)每一層的配置
*
介紹實(shí)現(xiàn)LeNet-5模型的完整的TensorFlow程序
*
介紹TensorFlow-Slim工具试和,來(lái)實(shí)現(xiàn)更加復(fù)雜的Inception-v3模型中的Inception模塊
在6.3節(jié)中介紹了卷積神經(jīng)網(wǎng)絡(luò)特有的兩種網(wǎng)絡(luò)結(jié)構(gòu)一一卷積層和池化層。
然而纫普,通過(guò)這些網(wǎng)絡(luò)結(jié)構(gòu)任意組合得到的神經(jīng)網(wǎng)絡(luò)有無(wú)限多種阅悍,怎樣的神經(jīng)網(wǎng)絡(luò)更有可能解決真實(shí)的圖像處理問(wèn)題呢?
這一節(jié)將介紹一些經(jīng)典的卷積神經(jīng)網(wǎng)絡(luò)的網(wǎng)絡(luò)結(jié)構(gòu)昨稼。通過(guò)這些經(jīng)典的卷積神經(jīng)網(wǎng)絡(luò)的網(wǎng)絡(luò)結(jié)構(gòu)可以總結(jié)出卷積神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)設(shè)計(jì)的一些模式节视。
-6.4.1- LeNet-5
模型
本節(jié)中將
*
具體介紹 LeNet-5 模型
*
并給出 一個(gè)完整的TensorFlow程序來(lái)實(shí)現(xiàn)LeNet-5模型。
*
通過(guò)這個(gè)模型假栓,將給出卷積神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)設(shè)計(jì)的一個(gè)通用模式寻行。
LeNet-5模型
是Yann LeCun教授于1998年在論文《Gradient-based learning applied to document recognition》中提出的,它是第一個(gè)成功應(yīng)用于數(shù)字識(shí)別問(wèn)題的卷積神經(jīng)網(wǎng)絡(luò)匾荆。在MNIST數(shù)據(jù)集上拌蜘,LeNet-5模型可以達(dá)到大約99.2%的正確率杆烁。
LeNet-5模型總共有7層,圖6-15展示了LeNet-5模型的架構(gòu)简卧。在下面的篇幅中將詳細(xì)介紹LeNet-5模型每一層的結(jié)構(gòu)兔魂。
*
第一層,卷積層
這一層的輸入就是原始的圖像像素举娩,LeNet-5模型接受的輸入層大小為32x32x1析校。第一個(gè)卷積層過(guò)濾器的尺寸為5×5,深度為6铜涉,不使用全0填充智玻,步長(zhǎng)為1。因?yàn)闆](méi)有使用全0填充芙代,所以這一層的輸出的尺寸為32-5+1=28吊奢,深度為6。
這一個(gè)卷積層總共有5x5x1x6+6=156個(gè)參數(shù)链蕊,其中 6個(gè)為偏置項(xiàng)參數(shù)事甜。
因?yàn)橄乱粚拥墓?jié)點(diǎn)矩陣有28x28x6=4704個(gè)節(jié)點(diǎn),每個(gè)節(jié)點(diǎn)和5×5=25個(gè)當(dāng)前層節(jié)點(diǎn)相連滔韵,所以本層卷積層總共有4704x(25+1)=122304個(gè)連接逻谦。
*
第二層,池化層
這一層的輸入為第一層的輸出陪蜻,是一個(gè)28x28x6的節(jié)點(diǎn)矩陣邦马。
本層采用的過(guò)濾器大小為2×2,長(zhǎng)和寬的步長(zhǎng)均為2宴卖,所以本層的輸出矩陣大小為14×14×6滋将。
原始的LeNet-5模型中使用的過(guò)濾器和6.3.2節(jié)介紹的有些細(xì)微差別,本書(shū)不做具體介紹症昏。
*
第三層随闽,卷積層
本層的輸入矩陣大小為14×14×6,使用的過(guò)濾器大小為5x5肝谭,深度為16掘宪。
本層不使用全0填充,步長(zhǎng)為1攘烛。本層的輸出矩陣大小為10x10×16魏滚。
按照標(biāo)準(zhǔn)的卷積層,本層應(yīng)該有5x5x6x16+16=2416個(gè)參數(shù)坟漱,10×10x16x(25+1)=41600個(gè)連接鼠次。
*
第四層,池化層
本層的輸入矩陣大小為10x10x16,采用的過(guò)濾器大小為2×2腥寇,步長(zhǎng)為2成翩。本層的輸出矩陣大小為5×5x16。
*
第五層花颗,全連接層
本層的輸入矩陣大小為5×5x16捕传,在LeNet-5模型的論文中將這一層稱為卷積層,但是因?yàn)檫^(guò)濾器的大小就是5×5扩劝,所以和全連接層沒(méi)有區(qū)別庸论,在之后的TensorFlow程序?qū)崿F(xiàn)中也會(huì)將這一層看成全連接層。如果將5x5×16矩陣中的節(jié)點(diǎn)拉成一個(gè)向量棒呛,那么這一層和在第4章中介紹的全連接層輸入就一樣了聂示。本層的輸出節(jié)點(diǎn)個(gè)數(shù)為120,總共有5x5x16x120+120=48120 個(gè)參數(shù)簇秒。
*
第六層鱼喉,全連接層
本層的輸入節(jié)點(diǎn)個(gè)數(shù)為120個(gè),輸出節(jié)點(diǎn)個(gè)數(shù)為84個(gè)趋观,總共參數(shù)為120x84+84=10164 個(gè)扛禽。
*
第七層,全連接層
本層的輸入節(jié)點(diǎn)個(gè)數(shù)為84個(gè)皱坛,輸出節(jié)點(diǎn)個(gè)數(shù)為10個(gè)编曼,總共參數(shù)為84×10+10=850個(gè)。
上面介紹了LeNet-5模型每一層結(jié)構(gòu)和設(shè)置剩辟,下面給出一個(gè)TensorFlow的程序來(lái)實(shí)現(xiàn)一個(gè)類似LeNet-5模型的卷積神經(jīng)網(wǎng)絡(luò)來(lái)解決MNIST數(shù)字識(shí)別問(wèn)題掐场。通過(guò)TensorFlow訓(xùn)練卷積神經(jīng)網(wǎng)絡(luò)的過(guò)程和第5章中介紹的訓(xùn)練全連接神經(jīng)網(wǎng)絡(luò)是完全一樣的。損失函數(shù)的計(jì)算贩猎、反向傳播過(guò)程的實(shí)現(xiàn)都可以復(fù)用5.5節(jié)中給出的mnist_train.py程序熊户。
唯一的區(qū)別在于因?yàn)榫矸e神經(jīng)網(wǎng)絡(luò)的輸入層為一個(gè)三維矩陣,所以需要調(diào)整一下輸入數(shù)據(jù)的格式:
# 調(diào)整輸入數(shù)據(jù)placeholder的格式吭服,輸入為一個(gè)四維矩陣嚷堡。
x = tf.placeholder(
tf.float32,
[
BATCH_SIZE, # 第一維表示batch中樣例個(gè)數(shù)
mnist_inference.IMAGE_SIZE, # 第二維 & 第三維 表示圖片的尺寸
mnist_inference.IMAGE_SIZE,
mnist_inference.NUM_CHANELS # 第四維表示圖片的深度,對(duì)于RGB格式的圖片艇棕,深度為3
],
name='x-input'
)
# 類似地麦到,將輸入的訓(xùn)練數(shù)據(jù)格式調(diào)整為一個(gè)四維矩陣,并將這個(gè)調(diào)整后的數(shù)據(jù)傳入se ss.run()過(guò)程
reshape_xs = np.reshspe(
xs,
(
BATCH_SIZE,
mnist_inference.IMAGE_SIZE,
mnist_inference.IMAGE_SIZE,
mnist_inference.NUM_CHANNELS
)
)
在調(diào)整完輸入格式之后欠肾,只需要在程序mnist_inference.py 中實(shí)現(xiàn)類似LeNet-5模型結(jié)構(gòu)的前向傳播過(guò)程即可。
下面給出了修改后的mnist_inference.py程序:
# -*- coding: utf-8 -*-
import tensorflow as tf
# 配置神經(jīng)網(wǎng)絡(luò)的參數(shù)
INPUT_NODE = 784
OUTPUT_NODE = 10
IMAGE_SIZE = 28
NUM_CHANNELS = 1
NUM_LABELS = 10
# 第一層卷積層的尺寸和深度
CONV1_DEEP = 32
CONV1_SIZE = 5
# 第二層卷積層的尺寸和深度
CONV2_DEEP = 64
CONV2_SIZE = 5
# 全連接層的節(jié)點(diǎn)個(gè)數(shù)
FC_SIZE = 512
# 定義卷積神經(jīng)網(wǎng)絡(luò)的前向傳播過(guò)程拟赊,這里面添加了一個(gè)新的參數(shù)train刺桃,用于區(qū)分訓(xùn)練過(guò)程和測(cè)試過(guò)程。
# 在這個(gè)過(guò)程中將用到dropout方法吸祟,dropout可以進(jìn)一步提升模型可靠性并防止過(guò)擬合瑟慈,dropout只在訓(xùn)練時(shí)使用桃移。
def inference(input_tensor, train, regularizer):
# 聲明第一層卷積層的變量并非前向傳播過(guò)程。
# 這個(gè)過(guò)程和6.3.1節(jié)中介紹的一致
# 通過(guò)使用不同命名空間來(lái)隔離不同層的變量葛碧,這可以讓每一層中的變量命名只需要考慮在當(dāng)前層的作用借杰,而不需要擔(dān)心重名的問(wèn)題。
# 和標(biāo)準(zhǔn)LeNet-5模型大不一樣进泼,這里定義的卷積層輸入為28x28x1的原始MNIST圖片像素蔗衡。
# 因?yàn)榫矸e層中使用了全0填充,所以輸出為28x28x32的矩陣
with tf.variables_scope('layer1-conv1'):
conv1_weights = tf.get_variable(
"weight",
[CONV1_SIZE, CONV1_SIZE, NUM_CHANNELS, CONV1_DEEP],
initializer=tf.truncated_normal_initializer(stddev=0.1)
)
conv1_biases = tf.get_variable(
"bias",
[CONV1_DEEP]
initializer=tf.constant_initializer(0.0)
)
# 使用變長(zhǎng)為5乳绕,深度為32的過(guò)濾器绞惦,過(guò)濾器移動(dòng)的步長(zhǎng)為1,且使用全0填充洋措。
conv1 = tf.nn.conv2d(
input_tensor,
conv1_weights,
strides=[1, 1, 1, 1],
padding='SAME'
)
relu1 = tf.nn.relu(
tf.nn.bias_add(conv1, conv1_biases)
)
# 實(shí)現(xiàn)第二層池化層的前向傳播過(guò)程
# 這里選用最大池化層济蝉,池化層過(guò)濾器的邊長(zhǎng)為2,使用全0填充且移動(dòng)的步長(zhǎng)為2菠发。
# 這一層的輸入是上一層的輸出王滤,也就是28x28x32的矩陣。
# 輸出為14x14x32的矩陣
with tf.name_scope('layer2-pool'):
pool1 = tf.nn.max_pool(
relu1,
ksize=[1, 2, 2, 1],
strides=[1, 2, 2, 1],
padding='SAME'
)
# 聲明第三層卷積層的變量并實(shí)現(xiàn)前向傳播過(guò)程滓鸠。
# 這一層的輸入為14x14x32的矩陣
# 輸出為14x14x64的矩陣
with tf.variable_scope('layer3-conv2'):
conv2_weights = tf.get_variable(
"weight",
[CONV2_SIZE, CONV2_SIZE, CONV1_DEEP, CONV2_DEEP],
initializer=tf.truncated_normal_innitializer(stddev=0.1)
)
conv2_biases = tf.get_varibale(
"bias",
[CONV2_DEEP],
initializer=tf.constant_initializer(0.0)
)
# 使用邊長(zhǎng)為5雁乡,深度為64的過(guò)濾器,過(guò)濾器移動(dòng)的步長(zhǎng)為1哥力,且使用全0填充
conv2 = tf.nn.conv2d(
pool1,
conv2_weights,
strides=[1, 1, 1, 1],
padding='SAME'
)
relu2 = tf.nn.relu(
tf.nn.bias_add(conv2, co nv2_biases)
)
# 實(shí)現(xiàn)第四層池化層的前向傳播過(guò)程。
# 這一層和第二層的結(jié)構(gòu)是一樣的吩跋。
# 這一層的輸入為14x14x64矩陣,輸出為7x7x64矩陣
with tf.name_scope('layer4-pool2'):
pool2 = tf.nn.max_pool(
relu2,
ksize=[1, 2, 2, 1],
strides=[1, 2, 2, 1],
padding='SAME'
)
# 將第四層池化層的輸出作為第五層全連接層的輸入格式掏觉。
# 第四層的輸出為7x7x64的矩陣
# 然而第五層全連接層需要的輸入格式為向量澳腹,所以在這里需要將這個(gè)7x7x64的矩陣?yán)背梢粋€(gè)向量。
# pool2.get_shape()函數(shù)可以得到第四層輸出矩陣的維度而不需要手工計(jì)算。
# 注意??因?yàn)槊恳粚由窠?jīng)網(wǎng)絡(luò)的輸入輸出都為一個(gè)batch的矩陣酱塔,所以這里得到的維度也包含了一個(gè)batch中數(shù)據(jù)的個(gè)數(shù)沥邻。
pool_shape = pool2.get_shape().as_list()
# 計(jì)算將矩陣?yán)背上蛄恐蟮拈L(zhǎng)度,這個(gè)長(zhǎng)度就是矩陣長(zhǎng)寬以濟(jì)深度的乘積羊娃。
# 注意??這里pool_shape[0]為一個(gè)batch中數(shù)據(jù)的個(gè)數(shù)
nodes = pool_shape[1] * pool_shape[2] * pool_shape[3]
# 通過(guò) tf.reshape() 函數(shù)將第四層的輸出變成一個(gè)batch的向量
reshaped = tf.reshape(pool2, [pool_shape[0], nodes])
# 聲明第五層全連接層的變量并實(shí)現(xiàn)前向傳播過(guò)程唐全。
# 這一層的輸入是拉直之后的一組向量,向量長(zhǎng)度為3136蕊玷,輸出是一組長(zhǎng)為512的向量邮利。
# 這一層和之前在第5章中介紹的基本一致,唯一的區(qū)別就是引入了dropout的概念集畅。
# dropout在訓(xùn)練時(shí)會(huì)隨機(jī)將部分節(jié)點(diǎn)的輸出改為0近弟。
# dropout可以避免過(guò)擬合的問(wèn)題,從而使得模型在測(cè)試數(shù)據(jù)上的效果更好挺智。
# dropout一般只在全連接層祷愉,而不是卷積層、池化層使用赦颇。
with tf.variable_scope('layer5-fc1'):
fc1_weights = tf.get_variable(
"weigth",
[nodes, FC_SIZE],
initializer=tf.truncated_normal_initializer(stddev=0.1)
)
# 只有全連接層的權(quán)重需要加入正則化
if regularizer != None:
tf.add_to_collection(
'losses',
regularizer(fc1_weights)
)
fc1_biases = tf.get_variable(tf.constant_initializer(0.1))
fc1 = tf.nn.relu(tf.matmal(reshaped, fc1_weights) + fc1_biases)
if train: fc1 = tf.nn.dropout(fc1, 0.5)
# 聲明第六層全連接層的變量并實(shí)現(xiàn)前向傳播過(guò)程二鳄。
# 這一層的輸入為一組長(zhǎng)度為512的向量,輸出為一組長(zhǎng)度為10的向量媒怯。
# 這一層的輸出通過(guò)Softmax之后订讼,就得到了最后的分類結(jié)果。
with tf.variable_scope('layer6-fc2'):
fc2_weigths = tf.get_variable(
"weight",
[FC_SIZE, NUM_LABELS],
initializer=tf.truncated_normal_initializer(stddev=0.1)
)
if regularizer != None:
tf.add_to_collection(
'losses',
regularizer(fc2_weights)
)
fc2_biases = tf.get_variable(
"bias",
[NUM_LABLES],
initializer=tf.constant_initializer(0.1)
)
logit = tf.matmul(fc1, fc2_weights) + fc2_biases
# 返回第六層的輸出
return logit
運(yùn)行修改后的mnist_train.py扇苞,可以得到類似第5章中的輸出:
~/mnist$ python mnist_train.py
Extracting /tmp/data/train-images-idx3-ubyte.gz
Extracting /tmp/data/train-labels-idxl-ubyte.gz
Extracting /tmp/data/t10k-images-idx3-ubyte .gz
Extracting /tmp/data/t10k-labels-idxl-ubyte.gz
After 1 training step(s), loss on training batch is 6.45373.
After 1001 training step(s), loss on training batch is 0.824825.
After 2001 training step(s) , loss on training batch is 0.646993.
After 3001 training step(s), loss on training batch is 0.759975.
After 4001 training step(s), loss on training batch is 0.68468.
After 5001 training step(s) , loss on training batch is 0.630368.
...
類似地修改第5章中給出的mnist_eval.py程序輸入部分欺殿,就可以測(cè)試這個(gè)卷積神經(jīng)網(wǎng)絡(luò)在MNIST數(shù)據(jù)集上的正確率了。在MNIST測(cè)試數(shù)據(jù)上鳖敷,上面給出的卷積神經(jīng)網(wǎng)絡(luò)可以達(dá)到大約99.4%的正確率脖苏。相比第5章中最高的98.4%的正確率,卷積神經(jīng)網(wǎng)絡(luò)可以巨幅提高神經(jīng)網(wǎng)絡(luò)在MNIST數(shù)據(jù)集上的正確率定踱。
然而一種卷積神經(jīng)網(wǎng)絡(luò)架構(gòu)不能解決所有問(wèn)題棍潘。比如LeNet-5模型就無(wú)法很好地處理類似ImageNet這樣比較大的圖像數(shù)據(jù)集。那么如何設(shè)計(jì)卷積神經(jīng)網(wǎng)絡(luò)的架構(gòu)呢崖媚?以下正則表達(dá)式公式總結(jié)了一些經(jīng)典的用于圖片分類問(wèn)題的卷積神經(jīng)網(wǎng)絡(luò)架構(gòu):
輸入層→(卷積層+→池化層?)+→全連接層+
在以上公式中:
*
“卷積層+”表示一層或者多層卷積層亦歉,大部分卷積神經(jīng)網(wǎng)絡(luò)中一般最多連續(xù)使用三層卷積層。
*
“池化層?”表示沒(méi)有或者一層池化層畅哑。池化層雖然可以起到減少 參數(shù)防止過(guò)擬合問(wèn)題肴楷,但是在部分論文中也發(fā)現(xiàn)可以直接通過(guò)調(diào)整卷積層步長(zhǎng)來(lái)完成。所以有些卷積神經(jīng)網(wǎng)絡(luò)中沒(méi)有地化層荠呐。
*
在多輪卷積層和池化層之后阶祭,卷積神經(jīng)網(wǎng)絡(luò)在輸出之前一般會(huì)經(jīng)過(guò)1~2個(gè)全連接層绷杜。
比如 LeNet-5模型就可以表示為以下結(jié)構(gòu):
輸入層→卷積層→池化層→卷積層→池化層→全連接層→全連接層→輸出層
除了 LeNet-5模型,2012年ImageNet ILSVRC圖像分類挑戰(zhàn)的第一名 AlexNet模型濒募、2013年ILSVRC第一名ZF Net模型以及2014年第二名VGGNet模型的架構(gòu)都滿足上面介紹的正則表達(dá)式。
表6-1給出了VGGNet論文《Very Deep Convolutional Networks for Large-Scale Image Recognition》中作者嘗試過(guò)的不同卷積神經(jīng)網(wǎng)絡(luò)架構(gòu)圾结。從表6-1中可以看出這些卷積神經(jīng)網(wǎng)絡(luò)架構(gòu)都滿足介紹的正則表達(dá)式瑰剃。
有了卷積神經(jīng)網(wǎng)絡(luò)的架構(gòu),那么每一層卷積層或者池化層中的配置需要如何設(shè)置呢筝野?表6-1也提供了很多線索晌姚。在表6-1中,convX-Y
表示過(guò)濾器的邊長(zhǎng)為X歇竟,深度為Y挥唠。比如conv3-64表示過(guò)濾器的長(zhǎng)和寬都為3,深度為64焕议。
*
從表6-1中可以看出宝磨,VGG Net 中的過(guò)濾器邊長(zhǎng)一般為3或者1。在LeNet-5模型中盅安,也使用了邊長(zhǎng)為5的過(guò)濾器唤锉。一般卷積層的過(guò)濾器邊長(zhǎng)不會(huì)超過(guò)5,但有些卷積神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)中别瞭,處理輸入的卷積層中使用了邊長(zhǎng)為7甚至是11的過(guò)濾器窿祥。
*
在過(guò)濾器的深度上,大部分卷積神經(jīng)網(wǎng)絡(luò)都采用逐層遞增的方式蝙寨。比如在表6-1中可以看到晒衩,每經(jīng)過(guò)一次池化層之后,卷積層過(guò)濾器的深度會(huì)乘以2墙歪。雖然不同的模型會(huì)選擇使用不同的具體數(shù)字听系,但是逐層遞增是比較普遍的模式。
*
卷積層的步長(zhǎng)一般為1箱亿,但是在有些模型中也會(huì)使用2跛锌,或者3作為步長(zhǎng)。
池化層的配置相對(duì)簡(jiǎn)單届惋,用得最多的是最大池化層髓帽。池化層的過(guò)濾器邊長(zhǎng)一般為2或者3,步長(zhǎng)也一般為2或者3脑豹。
-6.4.2- Inception-v3
模型
本節(jié)將介紹
*
設(shè)計(jì)卷積神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)的另外一種思路--Inception模型郑藏。
*
簡(jiǎn)單介紹TensorFlow-Slim工具,并通過(guò)這個(gè)工具實(shí)現(xiàn)谷歌提出的Inception-v3模型中的一個(gè)模塊
在6.4.1節(jié)中通過(guò)介紹LeNet-5模型整理出了一類經(jīng)典的卷積神經(jīng)網(wǎng)絡(luò)架構(gòu)設(shè)計(jì)瘩欺。在這一節(jié)中將介紹Inception結(jié)構(gòu)
以及Inception-v3卷積神經(jīng)網(wǎng)絡(luò)模型
必盖。
Inception 結(jié)構(gòu)是一種和LeNet-5結(jié)構(gòu)完全不同的卷積神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)拌牲。
在LeNet-5模型中,不同卷積層通過(guò)串聯(lián)
的方式連接在一起歌粥,
而Inception-v3模型中的Inception結(jié)構(gòu)是將不同的卷積層通過(guò)并聯(lián)
的方式結(jié)合在一起塌忽。
在下面的篇幅中將具體介紹Inception結(jié)構(gòu),并通過(guò)TensorFlow-Slim工具來(lái)實(shí)現(xiàn)Inception-v3模型中的一個(gè)模塊失驶。
在 6.4.1 中提到了一個(gè)卷積層可以使用邊長(zhǎng)為1土居、3或者5的過(guò)濾器,那么如何在這些邊長(zhǎng)中選呢嬉探?Inception模塊給出了一個(gè)方案擦耀,那就是同時(shí)使用所有不同尺寸的過(guò)濾器,然后再將得到的矩陣拼接起來(lái)涩堤。
圖6-16給出了Inception模塊的一個(gè)單元結(jié)構(gòu)示意圖眷蜓。從圖6-16中可以看出,Inception模塊會(huì)首先使用不同尺寸的過(guò)濾器處理輸入矩陣胎围。在圖6-16中吁系,最上方矩陣為使用了邊長(zhǎng)為1的過(guò)濾器的卷積層前向傳播的結(jié)果。類似的痊远,中間矩陣使用的過(guò)濾器邊長(zhǎng)為3垮抗,下方矩陣使用的過(guò)濾器邊長(zhǎng)為5。不同的矩陣代表了Inception模塊中的一條計(jì)算路徑碧聪。
雖然過(guò)濾器的大小不同冒版,但如果所有的過(guò)濾器都使用全0填充且步長(zhǎng)為1,那么前向傳播得到的結(jié)果矩陣的長(zhǎng)和寬都與輸入矩陣一致逞姿。這樣經(jīng)過(guò)不同過(guò)濾器處理的結(jié)果矩陣可以拼接成一個(gè)更深的矩陣辞嗡。如圖6-16所示,可以將它們?cè)谏疃冗@個(gè)維度上組合起來(lái)滞造。
圖6-16所示的Inception模塊得到的結(jié)果矩陣的長(zhǎng)和寬與輸入一樣续室,深度為紅黃藍(lán)三個(gè)矩陣深度的和。圖6-16中展示的是Inception模塊的核心思想谒养,真正在Inception-v3模型中使用的Inception模塊要更加復(fù)雜且多樣挺狰,有興趣的讀者可以參考論文《Rethinking the Inception Architecture for Computer Vision》。
圖6-17給出了Inception-v3模型的架構(gòu)圖买窟。Inception-v3模型總共有46層丰泊,由11個(gè)Inception模塊組成。圖6-17中方框標(biāo)注出來(lái)的結(jié)構(gòu)就是一個(gè)Inception模塊始绍。
在Inception-v3模型中有96個(gè)卷積層瞳购,如果將6.4.1節(jié)中的程序直接搬過(guò)來(lái),那么一個(gè)卷積層就需要5行代碼亏推,于是總共需要480行代碼來(lái)實(shí)現(xiàn)所有的卷積層学赛。這樣使得代碼的可讀性非常差年堆。為了更好地實(shí)現(xiàn)類似Inception-v3模型這樣的復(fù)雜卷積神經(jīng)網(wǎng)絡(luò),在下面將先介紹TensorFlow-Slim工具
來(lái)更加簡(jiǎn)潔地實(shí)現(xiàn)一個(gè)卷積層盏浇。以下代碼對(duì)比了直接使用TensorFlow實(shí)現(xiàn)一個(gè)卷積層和使用TensorFlow-Slim實(shí)現(xiàn)同樣結(jié)構(gòu)的神經(jīng)網(wǎng)絡(luò)的代碼量变丧。
# 直接使用TensorFlow原始API實(shí)現(xiàn)卷積層。
with tf.variable_scope(scope_nname):
weights = tf.get_variable("weight", ...)
biases = tf.get_variable("bias", ...)
conv = tf.nn.conv2d(...)
relu = tf.nn.relu(tf.nn.bias_add(conv, biases))
# 使用TensorFlow-Slim實(shí)現(xiàn)卷積層绢掰。
# 通過(guò)TensorFlow-Slim可以在一行中實(shí)現(xiàn)一個(gè)卷積層的前向傳播算法锄贷。
# slim.conv2d函數(shù)有3個(gè)參數(shù)是必填的:
# 第一個(gè)參數(shù)是輸入的節(jié)點(diǎn)矩陣
# 第二個(gè)參數(shù)是當(dāng)前卷積層過(guò)濾器的深度
# 第三個(gè)卷積層是過(guò)濾器的尺寸
# 可選的參數(shù)有過(guò)濾器移動(dòng)的步長(zhǎng)、是否全0填充曼月、激活函數(shù)的選擇、變量的命名空間等...
net = slim.conv2d(input, 32, [3, 3])
因?yàn)橥暾腎nception-v3模型比較長(zhǎng)柔昼,所以在本書(shū)中僅提供Inception-v3模型中結(jié)構(gòu)相對(duì)復(fù)雜的一個(gè)Inception模塊的代碼實(shí)現(xiàn)哑芹。
以下代碼實(shí)現(xiàn)了圖6-17中紅色方框中的Inception模塊:
# 加載slim庫(kù)
slim = tf.contrib.slim
# slim.arg_scope函數(shù)可以用于設(shè)置默認(rèn)的參數(shù)取值。
# slim.arg_scope函數(shù)的第一個(gè)參數(shù)是一個(gè)函數(shù)列表捕透,在這個(gè)列表中的函數(shù)將使用默認(rèn)的參數(shù)取值聪姿。
# 比如通過(guò)下面的定義,調(diào)用slim.conv2d(net, 320, [1, 1])函數(shù)時(shí)乙嘀,會(huì)自動(dòng)加上stride=1 和 padding='SAME' 的參數(shù)末购。
# 如果在函數(shù)調(diào)用時(shí)指定了stride,那么這里設(shè)置的默認(rèn)值就不會(huì)再使用虎谢。
# 通過(guò)這種方式可以進(jìn)一步減少冗余的代碼盟榴。
with slim.arg_scope(
[slim.conv2d,
slim.max_pool2d,
slim.avg_pool2d,
stride=1,
padding='VALID'
]
):
...
# 此處省略了Inception-v3模型中其他網(wǎng)絡(luò)結(jié)構(gòu)
# 而直接實(shí)現(xiàn)最后面紅色框中的Inception結(jié)構(gòu)。
# 假設(shè)輸入圖片經(jīng)過(guò)之前的神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)前向傳播的結(jié)果保存在變量net中婴噩。
net = 上一層的輸出節(jié)點(diǎn)矩陣
# 為一個(gè)Inception模塊生命一個(gè)統(tǒng)一的變量命名空間擎场。
with tf.variable_scope('Mixed_7c'):
# 給Inception模塊中每一條路徑聲明一個(gè)命名空間。
with tf.variable_scope('Branch_0'):
# 實(shí)現(xiàn)一個(gè)過(guò)濾器邊長(zhǎng)為1几莽、深度為320的卷積層迅办。
branch_0 = slim.conv2d(net, 320, [1, 1], scope='Conv2d_0a_1x1')
# Inception模塊中第二條路徑。
# 這條計(jì)算路徑上的結(jié)構(gòu)本身也是一個(gè)Inception結(jié)構(gòu)章蚣。
with tf.variable_scope('Branch_1'):
branch_1 = slim.conv2d(net, 384, [1, 1], scope='Conv2d_0a_1x1')
# tf.concat() 函數(shù)可以將多個(gè)矩陣拼接起來(lái)站欺。
# tf.concat() 函數(shù)的第一個(gè)參數(shù)指定了拼接的維度,這里給出的“3”代表了矩陣在深度這個(gè)維度上進(jìn)行拼接纤垂。
# 圖6-16中展示了在深度上拼接矩陣的方式矾策。
branch_1 = tf.concat(3,
[# 如圖6-17所示,此處2層卷積層的輸入都是branch_1而不是net洒忧。
slim.conv2d(branch_1, 384, [1, 3], scope='Conv2d_0b_1x3'),
slim.conv2d(branch_1, 384, [1, 3], scope='Conv2d_0c_3x1')
]
)
# Inception 模塊中第三條路徑蝴韭。
# 此計(jì)算路徑也是一個(gè)Inception結(jié)構(gòu)。
with tf.variable_scope('Branch_2'):
branch_2 = slim.conv2d(net, 448, [1, 1], scope='Conv2d_0a_1x1')
branch_2 = slim.conv2d(branch_2, 384, [3, 3], scope='Conv2d_0b_3x3')
branch_2 = tf.concat(3,
[slim.conv2d(branch_2, 384, [1, 3], scope='Conv2d_0c_1x3'),
slim.conv2d(branch_2, 384, [3, 1], scope='Conv2d_0d_3x1')
]
)
# Inception 模塊中第四條路徑
with tf.variable_scope('Branch_3'):
branch_3 = slim.avg_pool2d(net, [3, 3], scope='AvgPool_0a_3x3')
branch_3 = slim.conv2d(branch_3, 192, [1, 1], scope='Conv2d_0b_1x1')
# 當(dāng)前Inception模塊的最后輸出是由上面4個(gè)計(jì)算結(jié)果拼接得到的熙侍。
net = tf.concat(3, [branch_0, branch_1, branch_2, branch_3])
-6.5- 卷積神經(jīng)網(wǎng)絡(luò)遷移學(xué)習(xí)
本節(jié)中榄鉴,將:
*
介紹遷移學(xué)習(xí)的概念
*
介紹如何通過(guò) TensorFlow 實(shí)現(xiàn)卷積神經(jīng)網(wǎng)絡(luò)的遷移學(xué)習(xí)
-6.5.1- 遷移學(xué)習(xí)介紹
本節(jié)中履磨,將:
*
講解遷移學(xué)習(xí)
的動(dòng)機(jī)
;
*
介紹如何將一個(gè)數(shù)據(jù)集上訓(xùn)練好的卷積神經(jīng)網(wǎng)絡(luò)模型快速轉(zhuǎn)移到另外一個(gè)數(shù)據(jù)集上
在6.4節(jié)中介紹了1998年提出的LeNet-5模型和2015年提出的Inception-v3模型庆尘。對(duì)比這兩個(gè)模型可以發(fā)現(xiàn)剃诅,卷積神經(jīng)網(wǎng)絡(luò)模型的層數(shù)和復(fù)雜度都發(fā)生了巨大的變化。
表6-2給出了從2012年到2015年ILSVRC(Large Scale Visual Recognition Challenge)第一名模型的層數(shù)以及前五個(gè)答案的錯(cuò)誤率驶忌。從表6-2可以看到矛辕,隨著模型層數(shù)及復(fù)雜度的增加,模型在ImageNet上的錯(cuò)誤率也隨之降低付魔。
然而聊品,
*
訓(xùn)練復(fù)雜的卷積神經(jīng)網(wǎng)絡(luò)需要非常多的標(biāo)注數(shù)據(jù)。如6.1節(jié)中提到的几苍,ImageNet圖像分類數(shù)據(jù)集中有120萬(wàn)標(biāo)注圖片翻屈,所以才能將152層的ResNet的模型訓(xùn)練到大約96.5%的正確率。在真實(shí)的應(yīng)用中妻坝,很難收集到如此多的標(biāo)注數(shù)據(jù)伸眶。
*
即使可以收集到,也需要花費(fèi)大量人力物力刽宪。
*
而且即使有海量的訓(xùn)練數(shù)據(jù)厘贼,要訓(xùn)練一個(gè)復(fù)雜的卷積神經(jīng)網(wǎng)絡(luò)也需要幾天甚至幾周的時(shí)間。
為了解決標(biāo)注數(shù)據(jù)和訓(xùn)練時(shí)間的問(wèn)題圣拄,可以使用本節(jié)將要介紹的遷移學(xué)習(xí)
嘴秸。所謂遷移學(xué)習(xí),就是將一個(gè)問(wèn)題上訓(xùn)練好的模型通過(guò)簡(jiǎn)單的調(diào)整使其適用于一個(gè)新的問(wèn)題售担。
本節(jié)將介紹如何利用ImageNet數(shù)據(jù)集上訓(xùn)練好的Inception-v3模型來(lái)解決一個(gè)新的圖像分類問(wèn)題赁遗。根據(jù)論文《DeCAF: A Deep Convolutional Activation Feature for Generic Visual Recognition》中的結(jié)論,可以保留訓(xùn)練好的Inception-v3模型中所有卷積層的參數(shù)族铆,只是替換最后一層全連接層岩四。在最后這一層全連接層之前的網(wǎng)絡(luò)層稱之為瓶頸層(bottleneck)
。
將新的圖像通過(guò)訓(xùn)練好的卷積神經(jīng)網(wǎng)絡(luò)直到瓶頸層的過(guò)程可以看成是對(duì)圖像進(jìn)行特征提取
的過(guò)程哥攘。在訓(xùn)練好的Inception-v3模型中剖煌,因?yàn)閷⑵款i層的輸出再通過(guò)一個(gè)單層的全連接層神經(jīng)網(wǎng)絡(luò)可以很好地區(qū)分1000種類別的圖像,所以有理由認(rèn)為瓶頸層輸出的節(jié)點(diǎn)向量可以被作為任何圖像的一個(gè)更加精簡(jiǎn)且表達(dá)能力更強(qiáng)的特征向量
逝淹。于是耕姊,在新數(shù)據(jù)集上,可以直接利用這個(gè)訓(xùn)練好的神經(jīng)網(wǎng)絡(luò)對(duì)圖像進(jìn)行特征提取栅葡,然后再將提取得到的特征向量作為輸入來(lái)訓(xùn)練一個(gè)新的單層全連接神經(jīng)網(wǎng)絡(luò)處理新的分類問(wèn)題茉兰。
一般來(lái)說(shuō),在數(shù)據(jù)量足夠的情況下欣簇,遷移學(xué)習(xí)的效果不如完全重新訓(xùn)練规脸。但是遷移學(xué)習(xí)所需要的訓(xùn)練時(shí)間和訓(xùn)練樣本數(shù)要遠(yuǎn)遠(yuǎn)小于訓(xùn)練完整的模型坯约。在沒(méi)有GPU的普通臺(tái)式機(jī)或者筆記本電腦上,6.5.2節(jié)中給出的TensorFlow訓(xùn)練過(guò)程只需要大約3小時(shí)莫鸭,而且可以達(dá)到大概90%的正確率闹丐。
-6.5.2- TensorFlow實(shí)現(xiàn)遷移學(xué)習(xí)
本節(jié)中,將:
*
給出一個(gè)具體的TensorFlow程序?qū)mageNet上訓(xùn)練好的Inception-v3模型轉(zhuǎn)移到另外一個(gè)圖像分類數(shù)據(jù)集上
以下代碼給出了如何下載這一節(jié)中將要用到的數(shù)據(jù)集:
wget http://download.tensorflow.org/example_images/flower_photos.tgz
tar xzf flower_photos.tgz
解壓之后的文件夾包含了5個(gè)子文件夾被因,每一個(gè)子文件夾的名稱為一種花的名稱卿拴,代表了不同的類別。平均每一種花有734張圖片梨与,每一張圖片都是RGB色彩模式的堕花,大小也不相同。
和之前的樣例不同粥鞋,在這一節(jié)中給出的程序?qū)⒅苯犹幚頉](méi)有整理過(guò)的圖像數(shù)據(jù)航徙。以下代碼給出了如何將原始的圖像數(shù)據(jù)整理成模型需要的輸入數(shù)據(jù)。
#! /usr/bin/env python
# -*- coding : utf-8 -*-
import glob
import os.path
import numpy as np
import tensorflow as tf
from tensorflow.python.platform import gfile
# 原始輸入數(shù)據(jù)的目錄陷虎,這個(gè)目錄下有5個(gè)子目錄,每個(gè)子目錄底下保存屬于該類別的所有圖片
INPUT_DATA = '/path/to/flower_photos'
# 輸出文件地址杠袱。將整理后的圖片數(shù)據(jù)通過(guò)numpy的格式保存尚猿。
# 在第7章中將更加詳細(xì)地介紹數(shù)據(jù)預(yù)處理,這里先通過(guò)numpy來(lái)保存楣富。
OUTPUT_FILE = '/path/to/flower_processed_data.npy'
# 測(cè)試數(shù)據(jù)和驗(yàn)證數(shù)據(jù)比例
VALIDATION_PERCENTAGE = 10
TEST_PERCENTAGE = 10
# 讀取數(shù)據(jù)并將數(shù)據(jù)分割成訓(xùn)練數(shù)據(jù)、驗(yàn)證數(shù)據(jù)、測(cè)試數(shù)據(jù)
def create_image_lists(sess, testing_percentage, validation_percentage):
sub_dirs = [x[0] for x in os.walk(INPUT_DATA)]
is_root_dir = True
# 初始化各個(gè)數(shù)據(jù)集
training_images = []
training_labels = []
testing_images = []
testing_labels = []
validation_images = []
validation_labels = []
current_label = 0
# 讀取所有的子目錄
for sub_dir in sub_dirs:
if is_root_dor:
is_root_dir = False
continue
# 獲取一個(gè)子目錄中所有的圖片文件
extensions = ['jpg', 'jpeg', 'JPG', 'JPEG']
file_list = []
dir_name = os.path.basename(sub_dir)
for extension in extensions:
file_glob = os.path.join(INPUT_DATA, dir_name, '*.'+extension)
file_list.extend(glob.glob(file_glob))
if not file_list: continue
# 處理圖片數(shù)據(jù)
for file_name in file_list:
# 讀取并解析圖片礁击,將圖片轉(zhuǎn)化為299x299以便inception-v3模型來(lái)處理迹恐。
# 更多關(guān)于圖像預(yù)處理的內(nèi)容將在第7章中介紹。
image_raw_data = gfile.FastGFile(file_name, 'rb').read()
image = tf.image.decode_jpeg(image_raw_data)
if image.dtype != tf.float32:
image = tf.image.convert_image_dtype(image, dtype=tf.float32)
image = tf.image.resize_images(image, [299, 299])
image_value = sess.run(image)
# 隨機(jī)劃分?jǐn)?shù)據(jù)集
chance = np.random.randint(100)
if chance < validation_percentage:
validation_images.append(image_value)
validation_labels.append(current_label)
if chance < (testing_percentage + validation_percentage):
testing_images.append(image_value)
testing_labels.append(current_label)
else:
training_images.append(image_value)
training_labels.append(current_label)
current_label += 1
# 將訓(xùn)練數(shù)據(jù)隨機(jī)打亂以獲得更好的訓(xùn)練效果
state = np.random.get_state()
np.random.shuffle(training_images)
np.random.set_state(state)
np.random.shuffle(training_labels)
return np.asarray([
training_images,
training_labels,
validation_images,
validation_labels,
testing_images,
testing_labels
])
# 數(shù)據(jù)整理主函數(shù)
def main():
with tf.Session() as sess:
processed_data = create_image_lists(
sess,
TEST_PERCENTAGE,
VALIDATION_PERCENTAGE
)
# 通過(guò)numpy格式保存處理后的數(shù)據(jù)
np.save(OUTPUT_FILE, processed_data)
if __name__ == "__main__":
main()
運(yùn)行以上代碼可以講所有的圖片數(shù)據(jù)劃分為訓(xùn)練塘安、驗(yàn)證糠涛、測(cè)試3個(gè)數(shù)據(jù)集,并且將圖片從原始的jpg格式轉(zhuǎn)化為inception-v3模型需要的299x299x3的數(shù)字矩陣兼犯。
在數(shù)據(jù)處理完畢之后忍捡,通過(guò)以下命名可以下載谷歌提供的訓(xùn)練好的Inception-v3模型:
wget http://download.tensorflow.org/models/inception_v3_2016_08_28.tar.gz
# 解壓之后可以得到訓(xùn)練好的模型文件 inception_v3.ckpt
tar xzf inception_v3_2016_08_28.tar.gz
當(dāng)新的數(shù)據(jù)集和已經(jīng)訓(xùn)練好的模型都準(zhǔn)備好之后,可以通過(guò)以下代碼來(lái)完成遷移學(xué)習(xí)的過(guò)程:
#! /usr/bin/env python
# -*- coding : utf-8 -*-
import glob
import os.path
import numpy as np
import tensorflow as tf
from tensorflow.python.platform import gfile
import tensorflow.contrib.slim as slim
# 加載通過(guò)TensorFlow-Slim定義好的inception-v3模型切黔。
import tensorflow.contrib.slim.python.slim.nets.inception_v3 as inception_v3
# 處理好之后的數(shù)據(jù)文件
INPUT_DATA = '/path/to/flower_processed_data.npy'
# 保存訓(xùn)練好的模型的路徑砸脊。
# 這里可以將使用新數(shù)據(jù)訓(xùn)練得到的完整模型保存下來(lái),
# 如果計(jì)算資源充足纬霞,還可以在訓(xùn)練完成后的全連接層之后再訓(xùn)練所有的網(wǎng)絡(luò)層
# 這樣可以使得新模型更加貼近新數(shù)據(jù)凌埂。
TRAIN_FILE = '/path/to/save_model'
# 谷歌提供的訓(xùn)練好的模型文件地址
CKPT_FILE = '/path/to/inception_v3.ckpt'
# 定義訓(xùn)練中使用的參數(shù)
LEARNING_RATE = 0.0001
STEPS = 300
BATCH = 32
N_CLASSES = 5
# 不需要從谷歌訓(xùn)練好的模型中加載參數(shù)。
# 這里就是最后的全連接層诗芜,因?yàn)樵谛碌膯?wèn)題中要重新訓(xùn)練這一層中的參數(shù)瞳抓。
# 這里給出的是參數(shù)的前綴埃疫。
CHECKPOINT_EXCLUDE_SCOPES = 'InceptionV3/Logits, InceptionV3/AuxLogits'
# 需要訓(xùn)練的網(wǎng)絡(luò)層參數(shù)名稱,在fine-tuning的過(guò)程中就是最后的全連接層挨下。
# 這里給出的是參數(shù)的前綴熔恢。
TRAINABLE_SCOPES = 'InceptionV3/Logits, InceptionV3/AuxLogits'
# 獲取所有需要從谷歌訓(xùn)練好的模型中加載的參數(shù)
def get_tuned_variables():
exclusions = [scope.strip() for scope in CHECKPOINT_EXCLUDE_SCOPES.split(',')]
variables_to_restore = []
# 枚舉inception-v3模型中所有的參數(shù),
# 然后判斷是否需要從加載列表中移除
for var in slim.get_model_variables():
excluded = False
for exclusion in exclusions:
if var.op.name.startswitch(exclusion):
excluded = True
break
if not excluded:
variables_to_restore.append(var)
return variables_to_restore
# 獲取所有需要訓(xùn)練的變量列表
def get_trainable_variables():
scopes = [scope.strip() for scope inn TRAINABLE_SCOPES.split(',')]
variables_to_train = []
# 枚舉所有需要訓(xùn)練的參數(shù)前綴臭笆,并通過(guò)這些前綴找到所有的參數(shù)叙淌。
for scope in scopes:
variables = tf.get_collection(
tf.GraphKeys.TRAINABLE_VARIABLES,
scope
)
variables_to_train.extend(variables)
return variables_to_train
def main():
# 加載預(yù)處理好的數(shù)據(jù)
processed_data = np.load(INPUT_DATA)
training_images = processed_data[0]
n_training_example = len(training_images)
training_labels = processed_data[1]
validation_images = processed_data[2]
validation_labels = processed_data[3]
testing_images = processed_data[4]
testing_labels = processed_data[5]
print("%d training examples, %d validation examples and %d testing examples."%(
n_training_examples,
len(validation_labels),
len(testing_labels)
))
# 定義inception-v3的輸入,images為輸入圖片愁铺,labels為每一張圖對(duì)應(yīng)的標(biāo)簽
images = tf.placeholder(
tf.float32,
[None, 299, 299, 3],
name='input_images'
)
labels = tf.placeholder(tf.int64, [None], name='labels')
# 定義inception-v3模型.
# 因?yàn)楣雀杞o出的只有模型參數(shù)取值鹰霍,所以這里需要在這個(gè)代碼中定義inception-v3的模型結(jié)構(gòu)。
# 雖然理論上需要區(qū)分尋來(lái)呢和測(cè)試中使用的模型茵乱,也就是說(shuō)在測(cè)試時(shí)應(yīng)該使用is_training=False,
# 但是茂洒,因?yàn)轭A(yù)先訓(xùn)練好的inception-v3模型中使用的batch normalization參數(shù)與新的數(shù)據(jù)會(huì)有差異,導(dǎo)致結(jié)果很差
# 所以這里直接使用同一個(gè)模型來(lái)進(jìn)行測(cè)試瓶竭。
with slim.arg_scope(inception_v3.inception_v3_arg_scope()):
logits, _ = inception_v3.inception_v3(
images,
num_classes=N_CLASSES
)
# 獲取需要訓(xùn)練的變量
trainable_variables = get_trainable_variables()
# 定義交叉熵?fù)p失督勺。
# 注意在模型定義的時(shí)候已經(jīng)將正則化加入損失集合了。
tf.losses.softmax_cross_entropy(
tf.one_hot(labels, N_CLASSES),
logits,
weights=1.0
)
# 定義訓(xùn)練過(guò)程斤贰。
# 這里minimize的過(guò)程中制定了需要優(yōu)化的變量集合
train_step = tf.train.RMSPropOptimizer(LEARNING_RATE).minimize(
tf.losses.get_total_loss()
)
# 計(jì)算正確率
with tf.name_scope('evaluation'):
correct_prediction = tf.equal(tf.argmax(logits, 1), labels)
evaluation_step = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
# 定義加載模型的函數(shù)
load_fn = slim.assign_from_checkpoint_fn(
CKPT_FILE,
get_tuned_variables(),
ignore_missing_vars=True
)
# 定義好保存新的訓(xùn)練好的模型的函數(shù)
saver = tf.train.Saver()
with tf.Session() as sess:
# 初始化沒(méi)有加載進(jìn)來(lái)的變量智哀。
# 注意這個(gè)過(guò)程一定要在模型加載之前,
# 否則初始化過(guò)程會(huì)講已經(jīng)加載好的變量重新賦值
init = tf.global_variables_initializer()
sess.run(init)
# 加載谷歌已經(jīng)訓(xùn)練好的模型
print('Loading tuned variables from %s' % CKPT_FILE)
load_fn(init)
start = 0
end = BATCH
for i in range(STEPS):
# 運(yùn)行訓(xùn)練過(guò)程荧恍,這里不會(huì)更新全部的參數(shù)瓷叫,只會(huì)更新置頂?shù)牟糠謪?shù)。
sess.run(train_step, feed_dict={
images: training_images[start:end],
labels: training_labels[start:end]
})
# 輸出日志
if i%30 == 0 or i+1 == STEPS:
saver.save(sess, TRAIN_FILE, global_step=i)
validation_accuracy = sess.run(evaluation, feed_dict={
images: validation_images,
labels: validation_labels
})
print('Step %d: Validation accuracy = %.1f%%' % i, validation_accuracy*100.0)
# 因?yàn)樵跀?shù)據(jù)預(yù)處理的時(shí)候已經(jīng)做過(guò)了打亂數(shù)據(jù)的操作送巡,
# 所以這里只需要順序使用訓(xùn)練數(shù)據(jù)就好摹菠。
start = end
if start == n_training_examples:
start = 0
end = start + BATCH
if end > n_training_example:
end = n_trainning_example
# 在最后的試讀數(shù)據(jù)上測(cè)試正確率
test_accuracy = sess.run(evaluation_step, feed_dict={
images: testing_images,
labels: testing_labels
})
print('Final test accuracy = %.1f%%' % (test_accuracy*100))
if __name__ == "__main__":
tf.app.run()
運(yùn)行以上程序大概需要3小時(shí),可以得到類似下面的結(jié)果:
Step 0: Validation accuracy= 22.8%
Step 30: Validation accuracy = 29.6%
Step 60: Validation accuracy= 63.2%
Step 90: Validation accuracy = 81.2%
Step 120: Validation accuracy= 88.6%
...
Step 299: Validation accuracy = 91.5%
Final test accuracy= 91.9%
從以上結(jié)果可以看到骗爆,模型在新的數(shù)據(jù)集上很快能夠收斂次氨,并達(dá)到還不錯(cuò)的分類效果。
小結(jié)
在本章中詳細(xì)介紹了如何通過(guò)卷積神經(jīng)網(wǎng)絡(luò)解決圖像識(shí)別問(wèn)題摘投。
*
首先糟需,在6.1節(jié)中講解了什么是圖像識(shí)別問(wèn)題,并介紹了圖像識(shí)別問(wèn)題中的一些經(jīng)典公開(kāi)數(shù)據(jù)集谷朝。在這一節(jié)中介紹了不同算法在這些公開(kāi)數(shù)據(jù)集上的表現(xiàn)洲押,并指出卷積神經(jīng)網(wǎng)絡(luò)給這個(gè)領(lǐng)域帶來(lái)了質(zhì)的飛越。
*
接著圆凰,在6.2節(jié)中介紹了卷積神經(jīng)網(wǎng)絡(luò)的基本思想杈帐。在這一節(jié)中指出了全連接神經(jīng)網(wǎng)絡(luò)在處理圖像數(shù)據(jù)上的不足之處,并給出了經(jīng)典的卷積神經(jīng)網(wǎng)絡(luò)中包含的不同網(wǎng)絡(luò)結(jié)構(gòu)。
*
在6.3節(jié)中詳細(xì)講述了卷積神經(jīng)網(wǎng)絡(luò)中比較重要的兩個(gè)網(wǎng)絡(luò)結(jié)構(gòu)一一卷積層和池化層挑童。本節(jié)詳細(xì)介紹了這兩種網(wǎng)絡(luò)結(jié)構(gòu)的前向傳播算法累铅,并給出了TensorFlow中的代碼實(shí)現(xiàn)。
*
在6.4節(jié)中站叼,通過(guò)兩種經(jīng)典的卷積神經(jīng)網(wǎng)絡(luò)模型介紹了如何設(shè)計(jì)一個(gè)卷積神經(jīng)網(wǎng)絡(luò)的架構(gòu)娃兽,井介紹了配置卷積層和池化層中設(shè)置的一些經(jīng)驗(yàn)。在這一節(jié)中給出了一個(gè)完成的TensorFlow程序來(lái)實(shí)現(xiàn)LeNet-5模型尽楔,通過(guò)這個(gè)模型可以將MNIST數(shù)據(jù)集上的正確率進(jìn)一步提升到大約99.4%投储。這一節(jié)中還簡(jiǎn)單介紹了TensorFlow-Slim工具,通過(guò)這個(gè)工具可以巨幅提高實(shí)現(xiàn)復(fù)雜神經(jīng)網(wǎng)絡(luò)的編程效率阔馋。
*
最后在6.5節(jié)中玛荞,介紹了遷移學(xué)習(xí)的概念并給出了一個(gè)完整的TensorFlow來(lái)實(shí)現(xiàn)遷移學(xué)習(xí)呕寝。通過(guò)遷移學(xué)習(xí)勋眯,可以使用少量訓(xùn)練數(shù)據(jù)在短時(shí)間內(nèi)訓(xùn)練出效果還不錯(cuò)的神經(jīng)網(wǎng)絡(luò)模型。
在這一章中下梢,通過(guò)圖像識(shí)別問(wèn)題介紹了卷積神經(jīng)網(wǎng)絡(luò)客蹋。通過(guò)這種特殊結(jié)構(gòu)的神經(jīng)網(wǎng)絡(luò),可以將圖像識(shí)別問(wèn)題的準(zhǔn)確率提高到一個(gè)新的層次孽江。
除了改進(jìn)模型嚼酝,TensorFlow還提供了很多圖像處理的函數(shù)以方便圖像處理。在第7章中將具體介紹這些函數(shù)竟坛。同時(shí)也將介紹如何使用TensorFlow更好地處理輸入數(shù)據(jù)。