深度学习与计算机视觉系列(10)_细说卷积神经网络
轉(zhuǎn)載自:
深度學(xué)習(xí)與計算機視覺系列(10)_細說卷積神經(jīng)網(wǎng)絡(luò) - 龍心塵 - 博客頻道 - CSDN.NET
http://blog.csdn.net/longxinchen_ml/article/details/50545340
作者:寒小陽?&&?龍心塵?
時間:2016年1月。?
出處:?
http://blog.csdn.net/han_xiaoyang/article/details/50542880?
http://blog.csdn.net/longxinchen_ml/article/details/50545340?
聲明:版權(quán)所有,轉(zhuǎn)載請聯(lián)系作者并注明出處
1. 前言
前面九講對神經(jīng)網(wǎng)絡(luò)的結(jié)構(gòu),組件,訓(xùn)練方法,原理等做了介紹。現(xiàn)在我們回到本系列的核心:計算機視覺,神經(jīng)網(wǎng)絡(luò)中的一種特殊版本在計算機視覺中使用最為廣泛,這就是大家都知道的卷積神經(jīng)網(wǎng)絡(luò)。卷積神經(jīng)網(wǎng)絡(luò)和普通的神經(jīng)網(wǎng)絡(luò)一樣,由『神經(jīng)元』按層級結(jié)構(gòu)組成,其間的權(quán)重和偏移量都是可訓(xùn)練得到的。同樣是輸入的數(shù)據(jù)和權(quán)重做運算,輸出結(jié)果輸入激勵神經(jīng)元,輸出結(jié)果。從整體上看來,整個神經(jīng)網(wǎng)絡(luò)做的事情,依舊是對于像素級別輸入的圖像數(shù)據(jù),用得分函數(shù)計算最后各個類別的得分,然后我們通過最小化損失函數(shù)來得到最優(yōu)的權(quán)重。之前的博文中介紹的各種技巧和訓(xùn)練方法,以及注意事項,在這個特殊版本的神經(jīng)網(wǎng)絡(luò)上依舊好使。
咳咳,我們來說說它的特殊之處,首先卷積神經(jīng)網(wǎng)絡(luò)一般假定輸入就是圖片數(shù)據(jù),也正是因為輸入是圖片數(shù)據(jù),我們可以利用它的像素結(jié)構(gòu)特性,去做一些假設(shè)來簡化神經(jīng)網(wǎng)絡(luò)的訓(xùn)練復(fù)雜度(減少訓(xùn)練參數(shù)個數(shù))。
2.卷積神經(jīng)網(wǎng)總體結(jié)構(gòu)一覽
我們前面講過的神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)都比較一致,輸入層和輸出層中間夾著數(shù)層隱藏層,每一層都由多個神經(jīng)元組成,層和層之間是全連接的結(jié)構(gòu),同一層的神經(jīng)元之間沒有連接。
卷積神經(jīng)網(wǎng)絡(luò)是上述結(jié)構(gòu)的一種特殊化處理,因為對于圖像這種數(shù)據(jù)而言,上面這種結(jié)構(gòu)實際應(yīng)用起來有較大的困難:就拿CIFAR-10舉例吧,圖片已經(jīng)很小了,是32*32*3(長寬各32像素,3個顏色通道)的,那么在神經(jīng)網(wǎng)絡(luò)當中,我們只看隱藏層中的一個神經(jīng)元,就應(yīng)該有32*32*3=3072個權(quán)重,如果大家覺得這個權(quán)重個數(shù)的量還行的話,再設(shè)想一下,當這是一個包含多個神經(jīng)元的多層神經(jīng)網(wǎng)(假設(shè)n個),再比如圖像的質(zhì)量好一點(比如是200*200*3的),那將有200*200*3*n= 120000n個權(quán)重需要訓(xùn)練,結(jié)果是拉著這么多參數(shù)訓(xùn)練,基本跑不動,跑得起來也是『氣喘吁吁』,當然,最關(guān)鍵的是這么多參數(shù)的情況下,分分鐘模型就過擬合了。別急,別急,一會兒我們會提到卷積神經(jīng)網(wǎng)絡(luò)的想法和簡化之處。
卷積神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)比較固定的原因之一,是圖片數(shù)據(jù)本身的合理結(jié)構(gòu),類圖像結(jié)構(gòu)(200*200*3),我們也把卷積神經(jīng)網(wǎng)絡(luò)的神經(jīng)元排布成 width*height*depth的結(jié)構(gòu),也就是說這一層總共有width*height*depth個神經(jīng)元,如下圖所示。舉個例子說,CIFAR-10的輸出層就是1*1*10維的。另外我們后面會說到,每一層的神經(jīng)元,其實只和上一層里某些小區(qū)域進行連接,而不是和上一層每個神經(jīng)元全連接。?
?
3.卷積神經(jīng)網(wǎng)絡(luò)的組成層
在卷積神經(jīng)網(wǎng)絡(luò)中,有3種最主要的層:
- 卷積運算層
- pooling層
- 全連接層
一個完整的神經(jīng)網(wǎng)絡(luò)就是由這三種層疊加組成的。?
結(jié)構(gòu)示例?
我們繼續(xù)拿CIFAR-10數(shù)據(jù)集舉例,一個典型的該數(shù)據(jù)集上的卷積神經(jīng)網(wǎng)絡(luò)分類器應(yīng)該有[INPUT - CONV - RELU - POOL - FC]的結(jié)構(gòu),具體說來是這樣的:
- INPUT[32*32*3]包含原始圖片數(shù)據(jù)中的全部像素,長寬都是32,有RGB 3個顏色通道。
- CONV卷積層中,沒個神經(jīng)元會和上一層的若干小區(qū)域連接,計算權(quán)重和小區(qū)域像素的內(nèi)積,舉個例子可能產(chǎn)出的結(jié)果數(shù)據(jù)是[32*32*12]的。
- RELU層,就是神經(jīng)元激勵層,主要的計算就是max(0,x),結(jié)果數(shù)據(jù)依舊是[32*32*12]。
- POOLing層做的事情,可以理解成一個下采樣,可能得到的結(jié)果維度就變?yōu)閇16*16*12]了。
- 全連接層一般用于最后計算類別得分,得到的結(jié)果為[1*1*10]的,其中的10對應(yīng)10個不同的類別。和名字一樣,這一層的所有神經(jīng)元會和上一層的所有神經(jīng)元有連接。
這樣,卷積神經(jīng)網(wǎng)絡(luò)作為一個中間的通道,就一步步把原始的圖像數(shù)據(jù)轉(zhuǎn)成最后的類別得分了。有一個點我們要提一下,剛才說到了有幾種不同的神經(jīng)網(wǎng)絡(luò)層,其中有一些層是有待訓(xùn)練參數(shù)的,另外一些沒有。詳細一點說,卷積層和全連接層包含權(quán)重和偏移的;而RELU和POOLing層只是一個固定的函數(shù)運算,是不包含權(quán)重和偏移參數(shù)的。不過POOLing層包含了我們手動指定的超參數(shù),這個我們之后會提到。
總結(jié)一下:
- 一個卷積神經(jīng)網(wǎng)絡(luò)由多種不同類型的層(卷幾層/全連接層/RELU層/POOLing層等)疊加而成。
- 每一層的輸入結(jié)構(gòu)是3維的數(shù)據(jù),計算完輸出依舊是3維的數(shù)據(jù)。
- 卷積層和全連接層包含訓(xùn)練參數(shù),RELU和POOLing層不包含。
- 卷積層,全連接層和POOLing層包含超參數(shù),RELU層沒有。
下圖為CIFAR-10數(shù)據(jù)集構(gòu)建的一個卷積神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)示意圖:?
既然有這么多不同的層級結(jié)構(gòu),那我們就展開來講講:
3.1 卷積層
說起來,這是卷積神經(jīng)網(wǎng)絡(luò)的核心層(從名字就可以看出來對吧-_-||)。
3.1.1 卷積層綜述
直觀看來,卷積層的參數(shù)其實可以看做,一系列的可訓(xùn)練/學(xué)習(xí)的過濾器。在前向計算過程中,我們輸入一定區(qū)域大小(width*height)的數(shù)據(jù),和過濾器點乘后等到新的二維數(shù)據(jù),然后滑過一個個濾波器,組成新的3維輸出數(shù)據(jù)。而我們可以理解成每個過濾器都只關(guān)心過濾數(shù)據(jù)小平面內(nèi)的部分特征,當出現(xiàn)它學(xué)習(xí)到的特征的時候,就會呈現(xiàn)激活/activate態(tài)。
局部關(guān)聯(lián)度。這是卷積神經(jīng)網(wǎng)絡(luò)的獨特之處其中之一,我們知道在高維數(shù)據(jù)(比如圖片)中,用全連接的神經(jīng)網(wǎng)絡(luò),實際工程中基本是不可行的。卷積神經(jīng)網(wǎng)絡(luò)中每一層的神經(jīng)元只會和上一層的一些局部區(qū)域相連,這就是所謂的局部連接性。你可以想象成,上一層的數(shù)據(jù)區(qū),有一個滑動的窗口,只有這個窗口內(nèi)的數(shù)據(jù)會和下一層神經(jīng)元有關(guān)聯(lián),當然,這個做法就要求我們手動敲定一個超參數(shù):窗口大小。通常情況下,這個窗口的長和寬是相等的,我們把長x寬叫做receptive field。實際的計算中,這個窗口是會『滑動』的,會近似覆蓋圖片的所有小區(qū)域。
舉個實例,CIFAR-10中的圖片輸入數(shù)據(jù)為[32*32*3]的,如果我們把receptive field設(shè)為5*5,那receptive field的data都會和下一層的神經(jīng)元關(guān)聯(lián),所以共有5*5*3=75個權(quán)重,注意到最后的3依舊代表著RGB 3個顏色通道。
如果不是輸入數(shù)據(jù)層,中間層的data格式可能是[16*16*20]的,假如我們?nèi)?*3的receptive field,那單個神經(jīng)元的權(quán)重為3*3*20=180。
?
局部關(guān)聯(lián)細節(jié)。我們剛才說到卷積層的局部關(guān)聯(lián)問題,這個地方有一個receptive field,也就是我們直觀理解上的『滑動數(shù)據(jù)窗口』。從輸入的數(shù)據(jù)到輸出數(shù)據(jù),有三個超參數(shù)會決定輸出數(shù)據(jù)的維度,分別是深度/depth,步長/stride 和 填充值/zero-padding:
這么解釋可能理解起來還是會有困難,我們找兩張圖來對應(yīng)一下這三個量:
?
這是解決ImageNet分類問題用到的卷積神經(jīng)網(wǎng)絡(luò)的一部分,我們看到卷積層直接和最前面的圖像層連接。圖像層的維度為[227*227*3],而receptive field設(shè)為11*11,圖上未標明,但是滑動窗口的步長stride設(shè)為4,深度depth為48+48=96(這是雙GPU并行設(shè)置),邊緣沒有補0,因此zero-padding為0,因此窗口滑完一行,總共停留次數(shù)為(data_len-receptive_field_len+2*zero-padding)/stride+1=(227-11+2*0)/4+1=55,因為圖像的長寬相等,因此縱向窗口數(shù)也是55,最后得到的輸出數(shù)據(jù)維度為55*55*96維。
這是一張動態(tài)的卷積層計算圖,圖上的zero-padding為1,所以大家可以看到數(shù)據(jù)左右各補了一行0,窗口的長寬為3,滑動步長stride為2。
關(guān)于zero-padding,補0這個操作產(chǎn)生的根本原因是,為了保證窗口的滑動能從頭剛好到尾。舉個例子說,上2圖中的上面一幅圖,因為(data_len-receptive_field_len+2*zero-padding)/stride剛好能夠整除,所以窗口左側(cè)貼著數(shù)據(jù)開始位置,滑到尾部剛好窗口右側(cè)能夠貼著數(shù)據(jù)尾部位置,因此是不需要補0的。而在下面那幅圖中,如果滑動步長設(shè)為4,你會發(fā)現(xiàn)第一次計算之后,窗口就無法『滑動』了,而尾部的數(shù)據(jù),是沒有被窗口『看到過』的,因此補0能夠解決這個問題。
關(guān)于窗口滑動步長。大家可以發(fā)現(xiàn)一點,窗口滑動步長設(shè)定越小,兩次滑動取得的數(shù)據(jù),重疊部分越多,但是窗口停留的次數(shù)也會越多,運算律大一些;窗口滑動步長設(shè)定越長,兩次滑動取得的數(shù)據(jù),重疊部分越少,窗口停留次數(shù)也越少,運算量小,但是從一定程度上說數(shù)據(jù)信息不如上面豐富了。
3.1.2 卷積層的參數(shù)共享
首先得說卷積層的參數(shù)共享是一個非常贊的處理方式,它使得卷積神經(jīng)網(wǎng)絡(luò)的訓(xùn)練計算復(fù)雜度和參數(shù)個數(shù)降低非常非常多。就拿實際解決ImageNet分類問題的卷積神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)來說,我們知道輸出結(jié)果有55*55*96=290400個神經(jīng)元,而每個神經(jīng)元因為和窗口內(nèi)數(shù)據(jù)的連接,有11*11*3=363個權(quán)重和1個偏移量。所以總共有290400*364=105705600個權(quán)重。。。然后。。。恩,訓(xùn)練要累掛了。。。
因此我們做了一個大膽的假設(shè),我們剛才提到了,每一個神經(jīng)元可以看做一個filter,對圖片中的數(shù)據(jù)窗區(qū)域做『過濾』。那既然是filter,我們干脆就假設(shè)這個神經(jīng)元用于連接數(shù)據(jù)窗的權(quán)重是固定的,這意味著,對同一個神經(jīng)元而言,不論上一層數(shù)據(jù)窗口停留在哪個位置,連接兩者之間的權(quán)重都是同一組數(shù)。那代表著,上面的例子中的卷積層,我們只需要 神經(jīng)元個數(shù)*數(shù)據(jù)窗口維度=96*11*11*3=34848個權(quán)重。
如果對應(yīng)每個神經(jīng)元的權(quán)重是固定的,那么整個計算的過程就可以看做,一組固定的權(quán)重和不同的數(shù)據(jù)窗口數(shù)據(jù)做內(nèi)積的過程,這在數(shù)學(xué)上剛好對應(yīng)『卷積』操作,這也就是卷積神經(jīng)網(wǎng)的名字來源。另外,因為每個神經(jīng)元的權(quán)重固定,它可以看做一個恒定的filter,比如上面96個神經(jīng)元作為filter可視化之后是如下的樣子:
?
需要說明的一點是,參數(shù)共享這個策略并不是每個場景下都合適的。有一些特定的場合,我們不能把圖片上的這些窗口數(shù)據(jù)都視作作用等同的。一個很典型的例子就是人臉識別,一般人的面部都集中在圖像的中央,因此我們希望,數(shù)據(jù)窗口滑過這塊區(qū)域的時候,權(quán)重和其他邊緣區(qū)域是不同的。我們有一種特殊的層對應(yīng)這種功能,叫做局部連接層/Locally-Connected Layer
3.1.3 卷積層的簡單numpy實現(xiàn)
我們假定輸入到卷積層的數(shù)據(jù)為X,加入X的維度為X.shape: (11,11,4)。假定我們的zero-padding為0,也就是左右上下不補充0數(shù)據(jù),數(shù)據(jù)窗口大小為5,窗口滑動步長為2。那輸出數(shù)據(jù)的長寬應(yīng)該為(11-5)/2+1=4。假定第一個神經(jīng)元對應(yīng)的權(quán)重和偏移量分別為W0和b0,那我們就能算得,在第一行數(shù)據(jù)窗口停留的4個位置,得到的結(jié)果值分別為:
- V[0,0,0] = np.sum(X[:5,:5,:] * W0) + b0
- V[1,0,0] = np.sum(X[2:7,:5,:] * W0) + b0
- V[2,0,0] = np.sum(X[4:9,:5,:] * W0) + b0
- V[3,0,0] = np.sum(X[6:11,:5,:] * W0) + b0
注意上述計算過程中,*運算符是對兩個向量進行點乘的,因此W0應(yīng)該維度為(5,5,4),同樣你可以計算其他位置的計算輸出值:
- V[0,0,1] = np.sum(X[:5,:5,:] * W1) + b1
- V[1,0,1] = np.sum(X[2:7,:5,:] * W1) + b1
- V[2,0,1] = np.sum(X[4:9,:5,:] * W1) + b1
- V[3,0,1] = np.sum(X[6:11,:5,:] * W1) + b1
- …
每一個神經(jīng)元對應(yīng)不同的一組W和b,在每個數(shù)據(jù)窗口停留的位置,得到一個輸出值。
我們之前提到了卷積層在做的事情,是不斷做權(quán)重和窗口數(shù)據(jù)的點乘和求和。因此我們也可以把這個過程整理成一個大的矩陣乘法。
這個實現(xiàn)的弊端是,因為數(shù)據(jù)窗口的滑動過程中有重疊,因此我們出現(xiàn)了很多重復(fù)數(shù)據(jù),占用內(nèi)存較大。好處是,實際計算過程非常簡單,如果我們用類似BLAS這樣的庫,計算將非常迅速。
另外,在反向傳播過程中,其實卷積對應(yīng)的操作還是卷積,因此實現(xiàn)起來也很方便。
3.2 Pooling層
簡單說來,在卷積神經(jīng)網(wǎng)絡(luò)中,Pooling層是夾在連續(xù)的卷積層中間的層。它的作用也非常簡單,就是**逐步地壓縮/減少數(shù)據(jù)和參數(shù)的量,也在一定程度上減小過擬合的現(xiàn)象。**Pooling層做的操作也非常簡單,就是將原數(shù)據(jù)上的區(qū)域壓縮成一個值(區(qū)域最大值/MAX或者平均值/AVERAGE),最常見的Pooling設(shè)定是,將原數(shù)據(jù)切成2*2的小塊,每塊里面取最大值作為輸出,這樣我們就自然而然減少了75%的數(shù)據(jù)量。需要提到的是,除掉MAX和AVERAGE的Pooling方式,其實我們也可以設(shè)定別的pooling方式,比如L2范數(shù)pooling。說起來,歷史上average pooling用的非常多,但是近些年熱度降了不少,工程師們在實踐中發(fā)現(xiàn)max pooling的效果相對好一些。
一個對Pooling層和它的操作直觀理解的示意圖為:?
?
上圖為Pooling層的一個直觀示例,相當于對厚度為64的data,每一個切片做了一個下采樣。下圖為Pooling操作的實際max操作。
Pooling層(假定是MAX-Pooling)在反向傳播中的計算也是很簡單的,大家都知道如何去求max(x,y)函數(shù)的偏導(dǎo)。
3.3 歸一化層(Normalization Layer)
卷積神經(jīng)網(wǎng)絡(luò)里面有時候會用到各種各樣的歸一化層,尤其是早期的研究,經(jīng)常能見到它們的身影,不過近些年來的研究表明,似乎這個層級對最后結(jié)果的幫助非常小,所以后來大多數(shù)時候就干脆拿掉了。
3.4 全連接層
這是我們在介紹神經(jīng)網(wǎng)絡(luò)的時候,最標準的形式,任何神經(jīng)元和上一層的任何神經(jīng)元之間都有關(guān)聯(lián),然后矩陣運算也非常簡單和直接。現(xiàn)在的很多卷積神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu),末層會采用全連接去學(xué)習(xí)更多的信息。
4. 搭建卷積神經(jīng)網(wǎng)結(jié)構(gòu)
從上面的內(nèi)容我們知道,卷積神經(jīng)網(wǎng)絡(luò)一般由3種層搭建而成:卷積層,POOLing層(我們直接指定用MAX-Pooling)和全連接層。然后我們一般選用最常見的神經(jīng)元ReLU,我們來看看有這些『組件』之后,怎么『拼』出一個合理的卷積神經(jīng)網(wǎng)。
4.1 層和層怎么排
最常見的組合方式是,用ReLU神經(jīng)元的卷積層組一個神經(jīng)網(wǎng)絡(luò),同時在卷積層和卷積層之間插入Pooling層,經(jīng)過多次的[卷積層]=>[Pooling層]疊加之后,數(shù)據(jù)的總體量級就不大了,這個時候我們可以放一層全連接層,然后最后一層和output層之間是一個全連接層。所以總結(jié)一下,最常見的卷積神經(jīng)網(wǎng)結(jié)構(gòu)為:
[輸入層] => [[ReLU卷積層]*N => [Pooling層]?]*M => [ReLU全連接層]*K => [全連接層]
解釋一下,其中\(zhòng)*操作代表可以疊加很多層,而[Pooling層]?表示Pooling層其實是可選的,可有可無。N和M是具體層數(shù)。比如說[輸入層] -> [[ReLU卷積層]=>[ReLU卷積層]=>[Pooling層]]*3 -> [ReLU全連接層]*2 -> [全連接層]就是一個合理的深層的卷積神經(jīng)網(wǎng)。
『在同樣的視野范圍內(nèi),選擇多層疊加的卷積層,而不是一個大的卷積層』
這句話非常拗口,但這是實際設(shè)計卷積神經(jīng)網(wǎng)絡(luò)時候的經(jīng)驗,我們找個例子來解釋一下這句話:如果你設(shè)計的卷積神經(jīng)網(wǎng)在數(shù)據(jù)層有3層連續(xù)的卷積層,同時每一層滑動數(shù)據(jù)窗口為3*3,第一層每個神經(jīng)元可以同時『看到』3*3的原始數(shù)據(jù)層,那第二層每個神經(jīng)元可以『間接看到』(1+3+1)*(1+3+1)=5*5的數(shù)據(jù)層內(nèi)容,第三層每個神經(jīng)元可以『間接看到』(1+5+1)*(1+5+1)=7*7的數(shù)據(jù)層內(nèi)容。那從最表層看,還不如直接設(shè)定滑動數(shù)據(jù)窗口為7*7的,為啥要這么設(shè)計呢,我們來分析一下優(yōu)劣:
- 雖然第三層對數(shù)據(jù)層的『視野』范圍是一致的。但是單層卷積層加7*7的上層滑動數(shù)據(jù)窗口,結(jié)果是這7個位置的數(shù)據(jù),都是線性組合后得到最后結(jié)果的;而3層卷積層加3*3的滑動數(shù)據(jù)窗口,得到的結(jié)果是原數(shù)據(jù)上7*7的『視野』內(nèi)數(shù)據(jù)多層非線性組合,因此這樣的特征也會具備更高的表達能力。
- 如果我們假設(shè)所有層的『厚度』/channel數(shù)是一致的,為C,那7*7的卷積層,會得到C×(7×7×C)=49C2個參數(shù),而3層疊加的3*3卷積層只有3×(C×(3×3×C))=27C2個參數(shù)。在計算量上后者顯然是有優(yōu)勢的。
- 同上一點,我們知道為了反向傳播方便,實際計算過程中,我們會在前向計算時保留很多中間梯度,3層疊加的3*3卷積層需要保持的中間梯度要小于前一種情況,這在工程實現(xiàn)上是很有好處的。
4.2 層大小的設(shè)定
話說層級結(jié)構(gòu)確定了,也得知道每一層大概什么規(guī)模啊。現(xiàn)在我們就來聊聊這個。說起來,每一層的大小(神經(jīng)元個數(shù)和排布)并沒有嚴格的數(shù)字規(guī)則,但是我們有一些通用的工程實踐經(jīng)驗和系數(shù):
- 對于輸入層(圖像層),我們一般把數(shù)據(jù)歸一化成2的次方的長寬像素值。比如CIFAR-10是32*32*3,STL-10數(shù)據(jù)集是64*64*3,而ImageNet是224*224*3或者512*512*3。
- 卷積層通常會把每個[濾子/filter/神經(jīng)元]對應(yīng)的上層滑動數(shù)據(jù)窗口設(shè)為3*3或者5*5,滑動步長stride設(shè)為1(工程實踐結(jié)果表明stride設(shè)為1雖然比較密集,但是效果比較好,步長拉太大容易損失太多信息),zero-padding就不用了。
- Pooling層一般采用max-pooling,同時設(shè)定采樣窗口為2*2。偶爾會見到設(shè)定更大的采樣窗口,但是那意味著損失掉比較多的信息了。
- 比較重要的是,我們得預(yù)估一下內(nèi)存,然后根據(jù)內(nèi)存的情況去設(shè)定合理的值。我們舉個例子,在ImageNet分類問題中,圖片是224*224*3的,我們跟在數(shù)據(jù)層后面3個3*3『視野窗』的卷積層,每一層64個filter/神經(jīng)元,把padding設(shè)為1,那么最后每個卷積層的output都是[224*224*64],大概需要1000萬次對output的激勵計算(非線性activation),大概花費72MB內(nèi)存。而工程實踐里,一般訓(xùn)練都在GPU上進行,GPU的內(nèi)存比CPU要吃緊的多,所以也許我們要稍微調(diào)動一下參數(shù)。比如AlexNet用的是11*11的的視野窗,滑動步長為4。
4.3 典型的工業(yè)界在用卷積神經(jīng)網(wǎng)絡(luò)
幾個有名的卷積神經(jīng)網(wǎng)絡(luò)如下:
- LeNet,這是最早用起來的卷積神經(jīng)網(wǎng)絡(luò),Yann LeCun在論文LeNet提到。
- AlexNet,2012 ILSVRC比賽遠超第2名的卷積神經(jīng)網(wǎng)絡(luò),和LeNet的結(jié)構(gòu)比較像,只是更深,同時用多層小卷積層疊加提到大卷積層。
- ZF Net,2013 ILSVRC比賽冠軍,可以參考論文ZF Net
- GoogLeNet,2014 ILSVRC比賽冠軍,Google發(fā)表的論文Going Deeper with Convolutions有具體介紹。
- VGGNet,也是2014 ILSVRC比賽中的模型,有意思的是,即使這個模型當時在分類問題上的效果,略差于google的GoogLeNet,但是在很多圖像轉(zhuǎn)化學(xué)習(xí)問題(比如object detection)上效果奇好,它也證明卷積神經(jīng)網(wǎng)的『深度』對于最后的效果有至關(guān)重要的作用。預(yù)訓(xùn)練好的模型在pretrained model site可以下載。
具體一點說來,VGGNet的層級結(jié)構(gòu)和花費的內(nèi)存如下:
<code class="language-python hljs has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">INPUT: [<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">224</span>x224x3] memory: <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">224</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">224</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">150</span>K weights: <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span> CONV3-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">64</span>: [<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">224</span>x224x64] memory: <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">224</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">224</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">64</span>=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3.2</span>M weights: (<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>)*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">64</span> = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">728</span> CONV3-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">64</span>: [<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">224</span>x224x64] memory: <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">224</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">224</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">64</span>=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3.2</span>M weights: (<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">64</span>)*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">64</span> = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">36</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">864</span> POOL2: [<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">112</span>x112x64] memory: <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">112</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">112</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">64</span>=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">800</span>K weights: <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span> CONV3-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">128</span>: [<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">112</span>x112x128] memory: <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">112</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">112</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">128</span>=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1.6</span>M weights: (<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">64</span>)*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">128</span> = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">73</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">728</span> CONV3-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">128</span>: [<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">112</span>x112x128] memory: <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">112</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">112</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">128</span>=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1.6</span>M weights: (<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">128</span>)*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">128</span> = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">147</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">456</span> POOL2: [<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">56</span>x56x128] memory: <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">56</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">56</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">128</span>=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">400</span>K weights: <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span> CONV3-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">256</span>: [<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">56</span>x56x256] memory: <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">56</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">56</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">256</span>=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">800</span>K weights: (<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">128</span>)*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">256</span> = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">294</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">912</span> CONV3-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">256</span>: [<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">56</span>x56x256] memory: <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">56</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">56</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">256</span>=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">800</span>K weights: (<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">256</span>)*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">256</span> = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">589</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">824</span> CONV3-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">256</span>: [<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">56</span>x56x256] memory: <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">56</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">56</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">256</span>=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">800</span>K weights: (<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">256</span>)*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">256</span> = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">589</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">824</span> POOL2: [<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">28</span>x28x256] memory: <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">28</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">28</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">256</span>=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">200</span>K weights: <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span> CONV3-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">512</span>: [<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">28</span>x28x512] memory: <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">28</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">28</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">512</span>=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">400</span>K weights: (<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">256</span>)*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">512</span> = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">179</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">648</span> CONV3-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">512</span>: [<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">28</span>x28x512] memory: <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">28</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">28</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">512</span>=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">400</span>K weights: (<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">512</span>)*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">512</span> = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">359</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">296</span> CONV3-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">512</span>: [<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">28</span>x28x512] memory: <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">28</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">28</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">512</span>=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">400</span>K weights: (<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">512</span>)*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">512</span> = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">359</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">296</span> POOL2: [<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">14</span>x14x512] memory: <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">14</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">14</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">512</span>=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">100</span>K weights: <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span> CONV3-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">512</span>: [<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">14</span>x14x512] memory: <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">14</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">14</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">512</span>=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">100</span>K weights: (<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">512</span>)*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">512</span> = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">359</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">296</span> CONV3-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">512</span>: [<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">14</span>x14x512] memory: <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">14</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">14</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">512</span>=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">100</span>K weights: (<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">512</span>)*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">512</span> = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">359</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">296</span> CONV3-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">512</span>: [<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">14</span>x14x512] memory: <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">14</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">14</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">512</span>=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">100</span>K weights: (<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">512</span>)*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">512</span> = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">359</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">296</span> POOL2: [<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">7</span>x7x512] memory: <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">7</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">7</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">512</span>=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">25</span>K weights: <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span> FC: [<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>x1x4096] memory: <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4096</span> weights: <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">7</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">7</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">512</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4096</span> = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">102</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">760</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">448</span> FC: [<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>x1x4096] memory: <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4096</span> weights: <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4096</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4096</span> = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">16</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">777</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">216</span> FC: [<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>x1x1000] memory: <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1000</span> weights: <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4096</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1000</span> = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">096</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">000</span>TOTAL memory: <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">24</span>M * <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4</span> bytes ~= <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">93</span>MB / image (only forward! ~*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> bwd) TOTAL params: <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">138</span>M parameters</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li></ul>有意思的是,大家會注意到,在VGGNet這樣一個神經(jīng)網(wǎng)絡(luò)里,大多數(shù)的內(nèi)存消耗在前面的卷積層,而大多數(shù)需要訓(xùn)練的參數(shù)卻集中在最后的全連接層,比如上上面的例子里,全連接層有1億權(quán)重參數(shù),總共神經(jīng)網(wǎng)里也就1.4億權(quán)重參數(shù)。
4.4 考慮點
組一個實際可用的卷積神經(jīng)網(wǎng)絡(luò)最大的瓶頸是GPU的內(nèi)存。畢竟現(xiàn)在很多GPU只有3/4/6GB的內(nèi)存,最大的GPU也就12G內(nèi)存,所以我們應(yīng)該在設(shè)計卷積神經(jīng)網(wǎng)的時候多加考慮:
- 很大的一部分內(nèi)存開銷來源于卷積層的激勵函數(shù)個數(shù)和保存的梯度數(shù)量。
- 保存的權(quán)重參數(shù)也是內(nèi)存的主要消耗處,包括反向傳播要用到的梯度,以及你用momentum, Adagrad, or RMSProp這些算法時候的中間存儲值。
- 數(shù)據(jù)batch以及其他的類似版本信息或者來源信息等也會消耗一部分內(nèi)存。
5. 更多的卷積神經(jīng)網(wǎng)絡(luò)參考資料
- DeepLearning.net tutorial是一個用Theano完整實現(xiàn)卷積神經(jīng)網(wǎng)的教程。
- cuda-convnet2是多GPU并行化的實現(xiàn)。
- ConvNetJS CIFAR-10 demo允許你手動設(shè)定參數(shù),然后直接在瀏覽器看卷積神經(jīng)網(wǎng)絡(luò)的結(jié)果。
- Caffe,主流卷積神經(jīng)網(wǎng)絡(luò)開源庫之一。
- Example Torch 7 ConvNet,在CIFAR-10上錯誤率只有7%的卷積神經(jīng)網(wǎng)絡(luò)實現(xiàn)。
- Ben Graham’s Sparse ConvNet,CIFAR-10上錯誤率只有4%的實現(xiàn)。
- Face recognition for right whales using deep learning,Kaggle看圖識別瀕臨滅絕右鯨比賽的冠軍隊伍卷積神經(jīng)網(wǎng)絡(luò)。
總結(jié)
以上是生活随笔為你收集整理的深度学习与计算机视觉系列(10)_细说卷积神经网络的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Caffe学习系列(23):如何将别人训
- 下一篇: 深度学习(DL)与卷积神经网络(CNN)