卷積神經網絡(CNN)做爲深度學習的重要一支,在當前計算機視覺領域應用至關普遍。本文回顧了深度學習的發展歷程,講述CNN基本的理論概念和第一代卷積神經網絡LeNet-5的創建。文章言有不當之處,還望批評指出,共同進步!算法
2015年,AlphaGo戰敗樊麾二段,"深度學習"的命運就此改變,這個曾被拋棄忘卻的領域成爲了數年至今無數人追求的研究方向。然而,它璀璨奪目的前世卻充滿了暗淡與不幸。數據庫
「深度學習」的概念正式提出是在2006年,狹義上能夠看做是人工神經網絡。最先的相關研究是19世紀40~60年代的控制論,已經提出了前饋層次網絡摸型,也就是感知器,不過只是一種簡單的線性模型。該模型功能相似於擬合$f(x,\omega )=x_0\omega_0+x_1\omega_1+...+x_n\omega_n$這樣的函數,但在許多像異或問題的情形下顯得無能爲力。網絡
直到80年代,Hinton等人提出了反向傳播(BP)算法,使得模型具有了非線性映射的能力,解決了歷史遺留下來的異或問題。但當時不少神經網絡的研究者都是物理學家或者是心理學家,神經網絡廣泛不能被工程師和計算機科學家所接受。而且,由於受限於當時的數據規模,模型訓練很容易出現「過擬合」,加上機器計算能力的不足和神經網絡算法的「神祕性」,那些本就寥寥無幾的研究者也逐漸對它失去了興趣,紛紛轉行鑽研支持向量機(SVM)的機器學習算法。雖然如此,當時卻仍有一些「執拗」的探索者憑着堅決的信念在神經網絡領域默默耕耘,其中就包括後來創建LeNet網絡的Yann LeCun。架構
1998年,Yann LeCun等人在IEEE上發表了《Gradient-based learning applied to document recognization》一文,文中提出了基於梯度學習的卷積神經網絡算法,併成功運用於手寫數字識別中,取得了低於1%的錯誤率,超過了當時全部的模型,由此神經網絡的研究開始回熱。app
第一個卷積神經網絡並不是是LeNet,而是1987年由Alexander Waibel等人提出的時間延遲網絡(Time Delay Neural Network, TDNN)。TDNN是一個應用於語音識別問題的一維卷積神經網絡,而二維網絡則是由Yann LeCun提出的,而且論文中首次使用了「卷積」一詞,因此以「第一人」稱呼Yann LeCun不爲過。框架
據吳恩達對LeCun的採訪瞭解,LeCun從小就對科技興致盎然,尤爲是對「人類的智慧」、「有智慧的機器」等話題很是癡迷,最喜歡看有「現代科幻電影技術里程碑」美譽之稱的《2001太空漫遊》——看來幼時的興趣着實能影響一我的的一輩子啊!後來在大學期間,LeCun經過一本辯論語言是否天生的哲學書間接瞭解到了「感知器」的概念。抱着滿腦的好奇,他去了好幾個大學的圖書館,想要找到有關的資料進一步學習,才發如今50年代以後就不多有人談及到感知器了。機器學習
當LeCun拿到工程學位之後,LeCun去學習了與神經網絡並不相關的芯片設計,但同時對研究神經網絡仍念念不忘——在當時,尚未出現所謂的反向傳播算法,如何訓練多層網絡依舊是困擾研究者的一大難題,LeCun所以特別想從事這方面的研究。幸運的是,老天曆來不會辜負有理想併爲之努力的人,LeCun在後來漸漸接觸到了一些神經網絡方面的研究者,這些人都多多少少對他產生過影響。例如,當時有羣法國實驗室的人正在研究自動機網絡,給他看了一些前沿的論文,其中就有Hinton和Terrence寫的關於玻爾茲曼機的文章,LeCun看後很是震驚,原來世界上有這樣一羣人已經找到了神經網絡正確的研究方向。函數
後來在讀博期間,LeCun有幸遇到了當年論文的做者之一Terrence,經過交流,他從Terrence那瞭解到了反向傳播,這個概念當時還處於研究階段,沒有論文的發表。Terrence從法國回到美國後,就跟好友Hinton談及了LeCun,幾個月後Hinton的演講會上,LeCun便認識了這位對他影響深遠的導師。工具
LeCun最先開始研究卷積網絡是在多倫多大學跟着Hinton作博士後的階段。那時候沒有像如今這樣豐富完善的數據庫,天然也沒有如今被人「嚼爛」了的MNIST數據集,LeCun就用鼠標在我的電腦上一個一個地畫出字符用做訓練樣本,就這樣作出了早期的卷積神經網絡,而且那時已經有超越傳統網絡的跡象了。再後來,不得不提的就是貝爾實驗室了,能夠說它是LeCun成功的重要平臺。在實驗室,LeCun擁有了本身專用的Sun4電腦(在多倫多大學一臺Sun4電腦是整個學院共享的),當時實驗室的主管Larry說,在貝爾實驗室沒有誰是能靠省錢省出名的。在剛加入實驗室的三個月內,LeCun便用實驗室本來創建的數據集USPS訓練出了第一代LeNet,獲得了實驗室內最好的效果。雖然如今回過頭看LeNet的架構已經至關普通了,甚至一些教程裏都只是一筆帶過,網上也有各類版本的復現,但對於當時環境來說,沒有Python、Matlab,沒有Pytorch、TensorFlow等現成框架,網絡的構建須要本身寫模擬器和解釋器,是至關複雜的。性能
再後來,被人所銘記的就是LeCun在98年的LeNet論文,論文中說起了LeNet5和自動機,標誌着真正的CNN誕生了。現今任何的卷積網絡你均可以看到LeNet的影子,Yann LeCun也同Geoffrey Hinton 和 Yoshua Bengio一塊兒得到了2018年的圖靈獎,並稱爲「深度學習三巨頭」。
成功背後——在被問及深度學習的冬天時,LeCun說道,我一直堅信這些方法總有一天會回到你們的視野中,你們會學會如何用它們,解決一些實際問題。我一直有這個信念。
我我的剛接觸深度學習並無太長時間,同許多人同樣,也是看着吳恩達老師的視頻「長大」的。慶幸的是,咱們學校有自組織的深度學習小組,因此在必定程度上講,我並不是是徹底的自學,這一點我認爲仍是很重要的——衆人的智慧老是比我的來得強大。一樣,LeNet5也並不是純粹的我的成果,其中也汲取了時代的經驗。此外,我認爲,有些人學深度學習都是沒有「根」的(有點狂妄了),這裏所講的「根」即是歷史的概念。高中時候學歷史總感受興味索然,認爲歷史無用,理科纔是有「料」的;但反觀物理學,瞭解物理的發展史是基本的素養。深度學習也是同樣,當視頻中講到擬合、偏差函數、梯度降低等概念的時候,總覺得學到了一些很先進的概念,其實回顧歷史,這些東西早在上世紀中期就差很少有了。
這一節主要講的是在LeNet5提出前當時已有一些重要成果,也只是走馬觀花通常地描述,不會過分深刻地解釋,一來是本身的底子薄弱,二來也並不是是文章的主旨。
神經網絡的訓練實質上就是網絡權重的更新調整。如今的網絡基本都採用計算損失函數結合梯度降低來更新參數,有趣的是,最先具有這種特徵的算法在70年前差很少就存在了,該算法被稱爲Delta學習規則,其修正公式是$\omega_{ij}(t+1)=\omega_{ij}(t)+\alpha(d_i-y_i)x_j(t) $。其中,$\alpha$爲學習速率,$d_i$和$y_i$爲神經元i的指望輸出和實際輸出,$x_j(t)$爲神經元j的狀態(神經元i輸入),能夠發現,這跟咱們如今的權重更新是很類似了,只是Delta學習規則是針對單層網絡而言的,對於多層網絡的權重更新,當時的人仍是一頭霧水。
不過從那時起到如今,人們對於如何從數據中學習的基本思想是一致的——不管什麼樣的網絡,咱們都但願,實際的輸出和指望的結果間的差異最小(損失函數的內涵所在),而影響損失函數的即是網絡的權重,因此可藉助損失函數的梯度,來衡量參數對損失函數值的影響力大小,進而更新權重(梯度更新的內涵)。
在LeNet5論文中,做者曾談到一個經驗公式:
$E_{test}$和$E_{train}$分別表示測試集和訓練集的偏差;$k$和$\alpha$都是常數,$h$是網絡複雜度水平,$P$表示數據集的大小。這個簡單公式實際上能夠當作是整個深度學習研究的潛在定律:首先,對深度學習有過了解的人都知道隨着網絡複雜度的增長,對訓練集的擬合效果會愈來愈好,也就是訓練集偏差會降低,公式也驗證了這個常識。那麼這種狀況下的測試集偏差呢,一開始可能也是降低的,但降低的速度通常都比訓練集慢,這就牽扯到網絡的泛化能力了,假如複雜度再增長,若是數據集大小不變的話,極可能就會有過擬合問題冒出來。再來看數據集大小的影響,隨着$P$的增大,測試集偏差會無限接近訓練集的偏差,這每每是研究者們指望看到的結果。
在實際訓練時,咱們既想要訓練集偏差的降低,又想要測試集偏差儘量接近訓練集偏差,這就對硬件的性能和數據獲取提出了巨大的挑戰。即便在今日,咱們也沒辦法將這兩項都作到極致,力所能及的只是作到二者的平衡罷了,這也是當時研究者所能看到的情況。
神經網絡發展過程出現了不少的梯度降低法,其中有不少好的算法能夠加快降低、更容易找到全局最小值,好比如今廣泛使用的Adam。但在90年代用的比較多的仍是隨機梯度降低SGD,SGD從60年代開始便有在研究了,只是到了80年代中期才被應用到網絡上。總的來講,SGD每次採用個別樣原本更新權重,這使得計算量減小了不少,收斂得也更快,不容易困在局部最小值裏出不來,固然前提是訓練集得足夠大,稀釋噪聲帶來的影響。
LeNet的出現或者CNN的發展都要感謝反向傳播算法的提出。在反向傳播算法提出之前,梯度降低都只能應用於線性網絡中,由於人們沒法很方便地求解多層網絡間對參數的導數。反向傳播實質上是鏈式法則的應用,相信一些像我同樣的深度學習的初學者對反向傳播的過程也不是很熟悉——如今的框架像TensorFlow具有了自動求導的功能,根本不須要手動一層層地向前求導了。以前知乎上看到胡淵鳴大神一篇文章講述了本身曾被鏈式求導法則折磨了好久,因而最後將其開發的模擬器命名爲ChainQueen來記念那段經歷,可知鏈式求導可不是說說那麼簡單的呀!
其實還有不少的技術能夠一一說來的,可是精力和能力有限,這裏再也不敘述了。有興趣的能夠看看LeNet5論文,包含了不少當時的研究情況。
咱們常常討論一些頗有意思的爲何,好比:「爲何天然選擇人成爲高等生物」、「爲何民主和法治是制度發展的趨勢」、「爲何華爲能成爲行業的領先者」等等,這些問題彷佛都遵循了物競天擇的道理。在卷積網絡出現前,廣泛使用的都是全鏈接的形式,卷積憑藉什麼特性可以獨樹一幟呢?本節將講述卷積網絡的基本概念和優越之處。
針對2D圖像識別的全鏈接網絡,首要的問題便在於參數過多。試想一下,一張32*32像素大小的手寫字符圖片做爲第一層輸入,假使第二層神經元數量只有100個,那麼須要訓練的數量就已經達到32*32*100=102400個了,況且通常的網絡層數都要在3層以上。對於全鏈接網絡,網絡的鏈接數等於要訓練的參數個數(不考慮偏置的話),一方面網絡複雜性的提升是必須的,可是參數增長的同時所須要的訓練數據也必須增長,不然就容易過擬合,所以全鏈接層帶來的參數增加和過擬合問題在當時是著名的難題。
其次就是網絡不具有特徵不變性。最簡單的例子就是,若是你拿一批字符都在中間的數據去訓練的話,即便測試時準確率有多高,若是用一批字符都偏左邊的數據去測試,那麼獲得的結果將大跌眼鏡。其中緣由就在於全鏈接層是順序輸入的,很是依賴於特徵的位置信息,所以致使了它對平移、形變、扭曲等幾何變換很是敏感。
進一步地說,由於全鏈接層是每一個像素單獨對應一個權重,而圖像特徵大多都是相鄰像素的組合,這種作法顯然忽視了圖片像素的拓撲結構,就像是「管中窺豹」通常。再打個有趣的比方,我讓你去識別一個數字,但規定了你一次只能看圖片裏的一個像素,這顯然是故意爲難你啊!
要了解卷積網絡,就必須先了解什麼是感覺野。這個概念最先是在1959年的對貓的初級視皮層的一項研究中提出的,卷積網絡即是受到了它的啓發。
咱們能夠通俗地將感覺野理解爲眼睛所能看到的區域,好比說,眼睛能夠看到整個圖片的內容,那感覺野就是一張圖片那麼大;若是也讓這隻眼睛來次「管中窺豹」,那感覺野就可能減小爲幾個像素的大小了。例子的後者就能夠認爲是局部感覺野,由於只能看見圖片的一部分。如今,咱們將網絡的每個神經元都看做一雙雙眼睛,那麼情景就以下圖同樣,每雙眼睛觀察的地方都不同,但視野大小相同,最終整個圖片都會被窺看一盡。
看的過程並不是是漫無目地賞景,而是對視野內的像素做加權運算,感覺野每一個位置都有權重值,這些權重值就是網絡的訓練參數。加權所得的值做爲這隻「眼睛」的值,而後感覺野會平移必定像素距離,這個距離稱爲步長。移動後的感覺野再次加權運算,結果做爲另外一隻「眼睛」的值。這樣,前一層的圖就會映射成新的圖,這個圖叫作特徵圖。
這就是局部感覺野,相比於全鏈接,它同時考慮某個局部區域,這樣更容易提取到想要的特徵。
爲何叫作「特徵圖」呢?若是有接觸過圖像處理的話,會知道卷積在圖像平滑、邊緣等方面應用不少。一種權重的感覺野(如下簡稱「一種感覺野」)可能會「感覺」到邊緣特徵,另外一種感覺野可能會「感覺」到拐角特徵。對於一張特徵圖來講,由於都是由同一種感覺野觀察到的,所以極可能就是一張某種特徵的集合,只是這些特徵分佈在前一層圖的不一樣位置。
咱們將以前的模型推廣一下,以下圖所示,前一層圖具備3個通道。在卷積的過程當中,感覺野再也不是二維,而變成了三維形式,包含的權重參數也就有3*3*3=27個。感覺野每平移一次,27個像素值線性加權,結果做爲這隻「眼睛」的值,卷積完畢後獲得一個新特徵圖。在實際應用中,一般對前一層圖卷積屢次,每次使用不一樣的感覺野,以得到多種特徵。好比卷積4次,那麼總共就用了4種三維感覺野,獲得4種特徵。
共享權重就體如今每次卷積只使用一種感覺野。之因此將感覺野變成三維模式,能夠這麼理解:在多層卷積網絡中,某層網絡有n通道的特徵圖,也就有n種特徵;對該層卷積就是對這n個特徵進行組合,獲取更高維特徵的過程,於是三維感覺野的線性加權至關於特徵的組合,權重不一樣,組合方式也不一樣。
再來算一下所產生的參數量,假設卷積4次,步長爲1,感覺野大小爲3*3,前一層圖大小爲32*32,有3個通道。將感覺野擴展爲三維形式,一個感覺野有3*3*3+3=30個參數(加上每一個感覺野有個偏置參數),因而總參數量爲30*4=120個。通過卷積後生成的特徵圖大小爲30*30(感覺野不能超過圖的邊界,所以少了兩行兩列),共4個通道,那就有4*30*30個「眼睛」,每一個眼睛在卷積時都有27+1根鏈接線,因此總鏈接數爲4*30*30*28=100800。能夠看到,在保持網絡複雜性的同時,有效下降了須要訓練的參數,這就是共享權重帶來的好處。
向後層網絡傳遞時,特徵圖的大小老是不斷縮減,而通道不斷增長的。這樣作使得特徵愈來愈多,愈來愈重要,而位置信息愈來愈少。事實上,物體的識別未嘗不是這樣的呢?例如,咱們判斷一個動物是否是貓,根本就不用在乎它體型多大,是肥的仍是瘦的;不用在乎它坐在桌上,仍是躺在牀上。而是去看它的鬍鬚、耳朵、鼻子等等的細節特徵。再好比判斷一個數字是否是7,咱們會看它的三個端點的相對關係,至於它多少大、寫得多少歪那隻不過是審美上的事罷了。卷積網絡更是這樣,在最後幾層的特徵圖裏,你根本看不出是個啥玩意兒,由於過高維了!
卷積網絡的這個特性在必定程度上要歸功於下采樣操做,它相似於卷積,不過不含權重,通常對每一個通道都在感覺野內選擇最大值或者均值做爲結果,所以下采樣後特徵圖的大小會減少,但通道數仍不變。這種操做相似於將一張圖片進行縮小,在縮小時主動丟失了一些像素信息,可是總體上看內容基本上沒有發生變化。
不少教程上說,下采樣有三種功效:必定程度的特徵不變性、防止過擬合和減小參數量。最後一個功能是顯而易見的,過擬合在參數減小狀況下也相對難以出現,可是關於特徵不變性我還不能很好理解(大佬若是知道,能夠教教我),只能這樣解釋:下采樣創建了一種激勵機制,越有幫助的特徵其值便越大,這經過網絡的反饋和權重的調整應該是能夠作到的,既而特徵所處的位置就再也不敏感,形變的輸入也會由於這種機制凸顯出所要的特徵。
LeNet-5是爲手寫字符的識別專門而生的,LeCun後來也創建了MNIST數據庫供人們使用,如今初學者通常都會拿這個數據集下刀。跑這個數據集的話,我仍是很想建議用全鏈接層和LeNet-5跑一下的——用過笨辦法,你才知道智慧是怎麼來的。
LeNet-5當時用的圖片大小是32*32的,這個跟如今的不同,如今直接就是28*28了。其實32*32也是LeCun他們本身從28*28擴出來的,而如今的邊緣處理由框架直接能夠實現了。LeNet採用的是最原始的卷積下采樣交替,全鏈接輸出的結構。
輸入的圖像像素值都通過了嚴格的歸一化處理,最後255對應了-0.1,0對應了1.175,歸一化的過程做者並未說起,只是說這樣處理後數據的均值近似0,方差近似爲1,這與如今的概念差不了多少。
C1層、S2層很普通就不囉嗦了。C3層採用了很怪異的局部鏈接,就是每次卷積並不是都對所有通道進行,而是有選擇的進行,具體配置請看下圖,至於這樣有選擇的進行特徵組合是否有意義呢?很很差說,至少如今的網絡都不這麼作了。不過,這裏有個頗有趣的點——假如讓LeCun在中間再加一層卷積,他還會不會這麼幹?表示很好奇。
S4也略過。由於輸入大小的巧合,因此C5層已是被展平了,可是在結構上仍表示一層卷積,所以做者沒有把它標成F5。圖中的高斯鏈接涉及到了當時的RBF算法,相似於如今的softmax,這裏也不深刻探究了。
另外,除了輸出層之外的層都採用了tanh型激活函數,在當時,sigma函數的缺點就已經被發現了。還有一個不一樣點就是,LeNet的下采樣層也是有訓練參數的,當時他採用的仍是平均值採樣,再乘以一個權重值。
最近正在學習卷積神經網絡,打算好好琢磨一下這幾年出現的經典網絡。深度學習是一個很「玄學」的研究,有不少地方都值得去思考深究。以前看到有人問一個只專於圖像處理算法研究的博主,爲何不去搞深度學習,博主評論道,若是你不去原理上研究深度學習,那這就是個調參的東西,沒什麼意思。
我前兩天糾結要不要好好看一下LeNet論文,要不要寫這樣一篇回顧性的文章,畢竟LeNet對於如今來說已經不怎麼用了。就像前文提到的,你是傾向於緊追潮流,仍是願意先回頭瞥一眼歷史,這個話題在飛速發展的今天顯得挺有意思。後來整理過程當中,我以爲歷史仍是很重要的,歷史能幫助我搞清楚本身研究這個的目的,是爲了有一技之長,仍是爲了什麼?
這裏分享LeCun的一段話:
AI 這個領域和我剛剛進入的時候已經徹底不同了。我以爲這個領域如今有一點很棒,就是想要在必定程度上參與進來是很簡單的一件事。咱們如今有不少簡單好用的工具,TensorFlow、PyTorch 等等一大堆,本身家裏隨便一個什麼電腦就能運行得起來,而後訓練一個卷積網絡或者循環神經網絡作任何想作的事情。除了這些工具,也還有不少線上的教學資源能夠學習,沒有什麼門檻,高中生都能玩得轉,我以爲這棒極了。並且如今的學生裏對機器學習、AI 感興趣的也愈來愈多,年輕人也能喜歡真的很好。
個人建議是,若是你想要進入這個領域的話,作出一些幫助,好比在開源項目裏貢獻一些代碼,或者實現某個網上找不到代碼的標準算法,這樣別人就有得用了。你能夠就找一篇你以爲重要的論文,把算法實現出來,而後作成開源的代碼包,或者貢獻到別的開源代碼包裏。若是你寫的東西有趣、有用,就會有別人注意到你,你很是想去的公司可能會發 offer 給你,你很想讀博的地方也可能給你回信,之類的。我以爲這是一種很好的開頭方式。
最後,仍是得感謝你們的閱讀!