網(wǎng)絡(luò)CNN核心原理與訓(xùn)練實(shí)戰(zhàn):從全連接到卷積的架構(gòu)躍遷)
先說一個(gè)我自己復(fù)習(xí)時(shí)反復(fù)確認(rèn)過很多次的結(jié)論卷積神經(jīng)網(wǎng)絡(luò)CNN真正厲害的地方不是它有多少層、用了多少參數(shù)而是它在一開始就從架構(gòu)層面繞開了全連接網(wǎng)絡(luò)在圖像任務(wù)上的兩大死穴——參數(shù)爆炸和空間結(jié)構(gòu)丟失。2017年CS231n第五講花了大量篇幅把這件事拆開揉碎地講我當(dāng)時(shí)沒有完全聽進(jìn)去后來自己復(fù)現(xiàn)了幾個(gè)經(jīng)典結(jié)構(gòu)才徹底想明白。這篇內(nèi)容就是我對(duì)這一講筆記的完整整理把卷積層、池化層、全連接層、激活函數(shù)、訓(xùn)練技巧串起來講適合正在學(xué)深度視覺、準(zhǔn)備復(fù)現(xiàn)模型、或者剛被各種卷積術(shù)語繞暈的同學(xué)。先說好這不是課程視頻的逐句翻譯而是我自己消化之后重新組織的版本。重點(diǎn)放在“為什么這么做”和“動(dòng)手時(shí)要注意什么”上公式會(huì)有但每個(gè)公式我都會(huì)想辦法解釋到你能自己推出來。1. 從全連接層到卷積層為什么非改不可1.1 一張圖片被全連接層“拉直”之后丟掉了什么假設(shè)輸入是一張224×224的RGB圖片數(shù)據(jù)形狀是224×224×3。傳統(tǒng)全連接層的做法很直接把整個(gè)三維數(shù)組展平成一維向量長度是224×224×3150528然后接入一個(gè)擁有若干神經(jīng)元的隱層。聽起來沒什么大不了但如果你讓這個(gè)隱層有512個(gè)神經(jīng)元權(quán)重矩陣的規(guī)模就是150528×512約7700萬個(gè)參數(shù)這還只是一層。更關(guān)鍵的問題不是參數(shù)量而是結(jié)構(gòu)。圖像是三維的像素之間存在天然的空間鄰域關(guān)系相鄰像素往往顏色相近、紋理連續(xù)貓的眼睛總是出現(xiàn)在臉的局部區(qū)域。展平成一維向量之后這種鄰域關(guān)系被徹底打亂網(wǎng)絡(luò)看到的只是“一長串?dāng)?shù)字”每個(gè)位置之間的關(guān)系完全失去了空間含義。你等于把一張照片撕成碎片再硬塞給一個(gè)只會(huì)數(shù)順序的模型。課程里反復(fù)強(qiáng)調(diào)一個(gè)類比對(duì)圖像識(shí)別來說位置相近的像素比距離遠(yuǎn)的像素關(guān)系大得多這是最基本的先驗(yàn)。全連接層沒有利用這個(gè)先驗(yàn)他默認(rèn)所有輸入特征是全連接的、地位對(duì)等的這在圖像任務(wù)上是一種巨大的浪費(fèi)。1.2 參數(shù)共享和局部連接是怎么救場的卷積層就是針對(duì)這兩個(gè)問題設(shè)計(jì)的。第一是局部連接。每個(gè)卷積核不再連接整張輸入圖而是只連接到輸入的一個(gè)局部區(qū)域這個(gè)區(qū)域的大小就是卷積核的尺寸比如3×3或5×5。這和人的視覺系統(tǒng)很像看東西的時(shí)候也是一小塊一小塊地看局部紋理先被檢測(cè)出來再由后面更深的層組合成更大的語義概念。第二是參數(shù)共享。同一個(gè)卷積核會(huì)游走整張輸入圖也就是說在左上角檢測(cè)“橫向邊緣”的那組權(quán)重也會(huì)被用在右下角。為什么合理因?yàn)閳D像中同一個(gè)特征可能出現(xiàn)在任意位置一只貓?jiān)趫D片左上角和右下角本質(zhì)上都是“貓”對(duì)應(yīng)的邊緣紋理并沒有變。既然特征本身一樣檢測(cè)特征的那組參數(shù)也沒必要區(qū)分位置。這一下子把參數(shù)量從幾千萬壓到幾百。你可以拿全連接和卷積做個(gè)對(duì)比直觀感受一下差距結(jié)構(gòu)處理224×224×3圖像的典型參數(shù)量是否保留空間關(guān)系全連接層隱層512節(jié)點(diǎn)約7700萬否展平成一維卷積層6個(gè)3×3卷積核6×(3×3×31)168是按局部窗口掃描168對(duì)7700萬差了約46萬倍。課程里常說的“卷積讓深度學(xué)習(xí)在視覺上變得可行”說的就是這個(gè)差距。參數(shù)少了過擬合風(fēng)險(xiǎn)隨之降低訓(xùn)練需要的樣本量和計(jì)算資源也友好很多。1.3 平移等變性換個(gè)位置特征依然能被抓住參數(shù)共享還帶來一個(gè)隱藏的好處卷積天然具備平移等變性。意思是輸入圖像里的一個(gè)目標(biāo)平移一段距離卷積層輸出的特征圖也會(huì)跟著平移但特征本身仍然會(huì)被檢測(cè)出來。這對(duì)圖像任務(wù)太重要了因?yàn)槲覀儾辉敢饽P鸵驗(yàn)樨垙淖筮吪驳接疫吘蛷摹柏垺弊兂伞拔粗矬w”。不過我后來想明白一件事只有卷積層給的是“等變”而不是“不變”。真正讓你對(duì)平移不敏感的是后面的池化層它把局部區(qū)域內(nèi)的響應(yīng)做聚合才給了分類器一定的“無論出現(xiàn)在哪都能認(rèn)出來”的寬容度。所以看這章的時(shí)候最好把卷積和池化當(dāng)成一對(duì)搭檔來理解單獨(dú)拎出來看任何一個(gè)都解釋不了完整的網(wǎng)絡(luò)行為。2. 卷積層的輸出尺寸、超參數(shù)與感受野親手算一次就忘不掉2.1 卷積核到底在算什么一個(gè)卷積核本質(zhì)上是一個(gè)小的權(quán)重張量。以輸入RGB三通道圖為例一個(gè)3×3卷積核的形狀是3×3×3空間大小3×3通道數(shù)必須與輸入一致。這個(gè)卷積核覆蓋在輸入的某個(gè)位置上和覆蓋區(qū)域內(nèi)的27個(gè)數(shù)值做逐元素乘法再求和加上一個(gè)偏置得到輸出特征圖上的一個(gè)數(shù)。這個(gè)數(shù)代表什么直觀理解就是“這個(gè)局部區(qū)域與卷積核的匹配程度”。如果卷積核學(xué)到的是“橫向漸變邊緣”那么它在圖像邊緣區(qū)域就會(huì)輸出較大的響應(yīng)在平滑區(qū)域輸出接近0。多個(gè)卷積核并存時(shí)每個(gè)核相當(dāng)于一個(gè)特征檢測(cè)器有多少個(gè)卷積核就有多少個(gè)輸出特征圖也就是輸出通道數(shù)。課程把輸出通道數(shù)叫深度這個(gè)叫法容易和網(wǎng)絡(luò)層數(shù)混淆我在筆記里習(xí)慣叫“特征圖數(shù)量”。2.2 三個(gè)超參數(shù)決定輸出有多大多密卷積層有三個(gè)核心超參數(shù)深度卷積核個(gè)數(shù)、步長stride和零填充zero-padding。步長決定了卷積核每次滑動(dòng)幾步。步長為1時(shí)卷積核挨個(gè)移動(dòng)步長為2時(shí)輸出特征圖尺寸直接減半左右。填充則是在輸入邊緣補(bǔ)一圈0目的有兩個(gè)一是防止卷積把特征圖越卷越小信息快速縮水二是讓邊緣像素也有機(jī)會(huì)被卷積核中心覆蓋到畢竟邊緣元素在無填充時(shí)參與的卷積次數(shù)會(huì)比中間元素少信息地位不對(duì)等。輸出尺寸公式在課程里寫得很清楚輸出邊長 (N - F 2P) / S 1。其中N是輸入邊長F是卷積核空間尺寸P是填充量S是步長。我在紙上算了三年才真正理解這個(gè)公式每個(gè)項(xiàng)的意圖N - F 是“卷積核中心還能走多遠(yuǎn)”加上2P是因?yàn)樘畛渥屳斎脒呴L變長除以S是看按步長能取幾個(gè)位置最后加1是因?yàn)槌跏嘉恢靡惨阋淮巍N易约簩懥藗€(gè)小函數(shù)每次搭網(wǎng)絡(luò)都過一遍def conv_out_size(N, F, S, P0): return (N - F 2 * P) // S 1 # 輸入32x325x5卷積核步長1無填充 print(conv_out_size(32, 5, 1, 0)) # 28 # 輸入32x325x5卷積核步長1填充2 print(conv_out_size(32, 5, 1, 2)) # 32 # 輸入7x73x3卷積核步長2無填充 print(conv_out_size(7, 3, 2, 0)) # 3搭網(wǎng)絡(luò)時(shí)最怕的就是這里算錯(cuò)。常見配置是卷積核3×3、步長1、填充1輸出尺寸保持不變或者卷積核5×5、步長1、填充2輸出尺寸也保持不變。這樣在設(shè)計(jì)串聯(lián)結(jié)構(gòu)時(shí)你可以清晰控制哪些層改變空間尺寸哪些層只做特征變換。2.3 感受野與堆疊小卷積核的哲學(xué)感受野是另一個(gè)繞不開的概念意思是輸出特征圖上一個(gè)像素點(diǎn)對(duì)應(yīng)回輸入圖像上的多大區(qū)域。這個(gè)理解到后面看網(wǎng)絡(luò)結(jié)構(gòu)會(huì)非常有用因?yàn)槟愫芸炀桶l(fā)現(xiàn)現(xiàn)代網(wǎng)絡(luò)很少用大的卷積核了。原因很簡單堆疊兩個(gè)3×3卷積核換算成感受野是一個(gè)5×5因?yàn)榈谝粋€(gè)3×3讓特征圖每個(gè)點(diǎn)看到輸入3×3區(qū)域再接一個(gè)3×3時(shí)看到的是上一層3×3區(qū)域?qū)?yīng)的輸入?yún)^(qū)域合起來是5×5范圍。但參數(shù)量呢兩個(gè)3×3卷積的參數(shù)量是2×918按單通道看而一個(gè)5×5卷積是25。參數(shù)更少感受野卻一樣大而且中間多了一次ReLU激活給網(wǎng)絡(luò)增加了非線性表達(dá)能力。課程里明確指出這就是后來很多經(jīng)典結(jié)構(gòu)偏好使用小卷積核堆疊的根本原因。1×1卷積也值得單獨(dú)說。它不改變空間尺寸但會(huì)改變通道數(shù)相當(dāng)于在每個(gè)像素位置上對(duì)通道做一次線性組合可以用很低的成本控制特征圖厚度。課程里把1×1卷積看成“跨通道的池化”或者說“通道層面的重組合”在GoogLeNet這類結(jié)構(gòu)里被大量用來降維先把通道壓下來再做大卷積核計(jì)算。3. 池化層和全連接層縮小特征圖與匯總決策3.1 池化層不是“必須”但它的動(dòng)機(jī)很樸素池化層負(fù)責(zé)的是特征圖的降采樣。最常見的是最大池化用一個(gè)2×2窗口以步長2掃過特征圖每個(gè)窗口內(nèi)取最大值輸出寬高直接減半通道數(shù)不變。為什么需要這一步首先卷積層雖然已經(jīng)控制了參數(shù)規(guī)模但特征圖本身依然很大如果一路保持高分辨率后面的層計(jì)算量會(huì)一直維持在很高的水平。其次最大池化給了網(wǎng)絡(luò)對(duì)微小位移的容忍度物體偏移一兩個(gè)像素時(shí)池化窗口內(nèi)的最大值往往變化不大后續(xù)層看到的仍是接近相同的特征。用課程里的說法池化是在逐步抽象位置細(xì)節(jié)慢慢讓位于語義內(nèi)容。這里特別想說池化并不改變通道數(shù)量。它只在寬和高兩個(gè)維度上做壓縮通道維度保持不動(dòng)。常見配置就是2×2窗口加步長2效果是特征圖每個(gè)維度減半相當(dāng)于對(duì)特征圖做了空間上的“濃縮”。3.2 最大池化和平均池化的取舍講師在課上對(duì)比過兩種池化。最大池化取窗口內(nèi)的最強(qiáng)響應(yīng)實(shí)際經(jīng)驗(yàn)里效果更好因?yàn)樗A舻氖恰斑@個(gè)區(qū)域里到底有沒有某種特征”而不是被區(qū)域內(nèi)大量低響應(yīng)值拉低平均。平均池化沒那么激進(jìn)把窗口內(nèi)所有值等權(quán)匯總信息更平滑但更容易把微弱特征稀釋掉。不過平均池化有一個(gè)用法一直活到了今天全局平均池化也就是把整張?zhí)卣鲌D池化成1×1。它一般出現(xiàn)在網(wǎng)絡(luò)的末端用來替代全連接層做最終分類前的特征匯總好處是參數(shù)量幾乎為零并且天然輸出一個(gè)與類別數(shù)一致的特征向量。課程在講經(jīng)典網(wǎng)絡(luò)的時(shí)候提到這種設(shè)計(jì)我當(dāng)時(shí)沒太在意后來自己動(dòng)手做小模型時(shí)試了一次才發(fā)現(xiàn)這種結(jié)尾方式既省參數(shù)又不容易過擬合。3.3 全連接層把二維特征圖變成分類分?jǐn)?shù)卷積層和池化層把圖像逐步抽象成了“長寬更小、通道更多”的特征圖但分類任務(wù)最終要輸出一個(gè)向量比如10個(gè)類別的得分。全連接層做的就是最后這一步把特征圖展平成一維然后通過一個(gè)權(quán)重矩陣映射到類別維度上。全連接層的問題和開頭講的一樣參數(shù)量很大。假設(shè)最后一個(gè)卷積層輸出是7×7×512展平后長度是25088如果再接一個(gè)1024節(jié)點(diǎn)的全連接層權(quán)重就是25088×1024約2570萬。這也是為什么很多現(xiàn)代結(jié)構(gòu)要么不用全連接層要么只保留最后一層。課程里提過一個(gè)技巧全連接層本質(zhì)上可以被看成一種特殊卷積當(dāng)輸入特征圖空間尺寸為1×1時(shí)全連接就是1×1卷積。理解這個(gè)對(duì)應(yīng)關(guān)系對(duì)改造網(wǎng)絡(luò)結(jié)構(gòu)很有幫助比如你想把某個(gè)分類網(wǎng)絡(luò)改成全卷積的版本只需要把全連接層替換成對(duì)應(yīng)的1×1卷積。到這里一個(gè)經(jīng)典網(wǎng)絡(luò)的完整骨架就清楚了輸入圖像經(jīng)過多輪“卷積-激活-池化”把空間尺寸逐步壓低、通道逐步加深最后展平接全連接層再接一個(gè)Softmax把得分變成概率。整個(gè)流程可以概括成特征提取在前分類決策在后。4. 激活函數(shù)與經(jīng)典網(wǎng)絡(luò)骨架從CONV-RELU-POOL到現(xiàn)代變體4.1 為什么Sigmoid在深度網(wǎng)絡(luò)里基本被放棄了2017年課程講激活函數(shù)時(shí)仍然是從Sigmoid講起的因?yàn)樗鼩v史上重要但隨后很快就指出它的致命缺陷飽和。Sigmoid把輸入壓到0到1之間當(dāng)輸入絕對(duì)值較大時(shí)曲線變得非常平緩梯度接近0。多個(gè)層連起來的時(shí)候這些接近0的梯度一乘就會(huì)讓靠近輸入層的參數(shù)幾乎得不到更新信號(hào)這就是梯度消失。Tanh比Sigmoid好一點(diǎn)輸出是零中心的但同樣存在飽和區(qū)的問題。ReLU就樸素多了函數(shù)是max(0,x)正半軸梯度恒為1負(fù)半軸直接置0。優(yōu)勢(shì)很明顯計(jì)算只要一次比較收斂速度比Sigmoid快很多而且正的梯度能順利往后傳。課程里給出的建議非常直接默認(rèn)用ReLU如果遇到神經(jīng)元大量死亡嘗試Leaky ReLU或帶參數(shù)的變體。ReLU有個(gè)著名的問題叫“死亡ReLU”如果某個(gè)神經(jīng)元在訓(xùn)練中被負(fù)區(qū)間壓住它的梯度永遠(yuǎn)是0權(quán)重再也無法更新這個(gè)神經(jīng)元就永久退出了。通常原因有兩點(diǎn)一是初始化不合適二是學(xué)習(xí)率設(shè)置太大。課程里也提到合理的初始化和學(xué)習(xí)率能大幅減少這種現(xiàn)象所以別一見到死亡神經(jīng)元就急著換激活函數(shù)先把訓(xùn)練配置調(diào)對(duì)。4.2 經(jīng)典層布局CONV-RELU-[(POOL)]的節(jié)奏普通卷積網(wǎng)絡(luò)的布局有一個(gè)非常清晰的節(jié)奏卷積層負(fù)責(zé)特征提取激活函數(shù)引入非線性池化層做空間降維然后重復(fù)。典型的一個(gè)階段是“卷積-ReLU-池化”或者更細(xì)致一點(diǎn)“若干個(gè)卷積-ReLU-池化”。為什么卷積和池化的順序固定成這個(gè)樣子因?yàn)榧せ詈瘮?shù)必須緊跟卷積否則多個(gè)卷積層疊起來還是線性變換堆再多層也等效于一個(gè)卷積。池化則可以稍微延后讓卷積層先在同一分辨率下充分提取特征再用池化降低冗余。課程講到最后的經(jīng)典結(jié)構(gòu)演進(jìn)時(shí)其實(shí)講的都是這個(gè)節(jié)奏的變化早期5層網(wǎng)絡(luò)是“卷積-池化-全連接”的簡單拼接8層的AlexNet把卷積層增加到5層同時(shí)用ReLU和Dropout讓網(wǎng)絡(luò)第一次在大規(guī)模圖像數(shù)據(jù)上取得明顯優(yōu)勢(shì)16層風(fēng)格的VGG網(wǎng)絡(luò)證明了“小卷積核深網(wǎng)絡(luò)”的組合它完全堆疊3×3卷積結(jié)構(gòu)極度規(guī)整22層的GoogLeNet則嘗試在同一個(gè)層上并行使用不同尺寸的卷積核讓網(wǎng)絡(luò)自己選擇合適尺度的特征而50層以上能訓(xùn)練起來的關(guān)鍵是殘差連接讓梯度能繞過一個(gè)層直接傳到前面。我自己復(fù)習(xí)到這一段時(shí)最大的感受是每一代結(jié)構(gòu)都不是憑空想出來的都是在解決上一代網(wǎng)絡(luò)訓(xùn)練或表達(dá)的某個(gè)具體瓶頸。經(jīng)典結(jié)構(gòu)按課程演進(jìn)順序核心改動(dòng)參數(shù)量量級(jí)早期5層網(wǎng)絡(luò)卷積池化全連接的基本拼接百萬級(jí)8層結(jié)構(gòu)加深網(wǎng)絡(luò)、引入ReLU與隨機(jī)丟棄約6000萬16層純卷積結(jié)構(gòu)大量堆疊3×3小卷積核結(jié)構(gòu)規(guī)整約1.38億22層多分支結(jié)構(gòu)同層多種尺度卷積并行組合特征約700萬50層殘差結(jié)構(gòu)增加跨層直連解決深度網(wǎng)絡(luò)的梯度問題約2560萬4.3 為什么2017年講的內(nèi)容到今天仍然適用雖然這是2017年的課很多具體結(jié)構(gòu)和數(shù)據(jù)都已經(jīng)不是最前沿但第五講的核心思想一點(diǎn)沒過時(shí)卷積層的局部連接和參數(shù)共享、池化層的空間降采樣、激活函數(shù)的非線性、殘差結(jié)構(gòu)對(duì)梯度傳播的改善這些仍是今天絕大多數(shù)視覺模型的基石。后面的注意力機(jī)制、大規(guī)模預(yù)訓(xùn)練、多模態(tài)模型都是在這些基礎(chǔ)構(gòu)件之上生長出來的。所以我現(xiàn)在看這篇筆記更多的不是看技術(shù)有多新而是看它如何把若干基本的視覺先驗(yàn)清晰地注入到架構(gòu)里這個(gè)底層思路是穩(wěn)定的。5. 訓(xùn)練卷積神經(jīng)網(wǎng)絡(luò)的現(xiàn)實(shí)問題初始化、正則化、數(shù)據(jù)增強(qiáng)5.1 輸入預(yù)處理和權(quán)重初始化兩臺(tái)發(fā)動(dòng)機(jī)的預(yù)熱課程在訓(xùn)練細(xì)節(jié)部分很早就強(qiáng)調(diào)數(shù)據(jù)預(yù)處理。圖像數(shù)據(jù)最基礎(chǔ)的處理是零中心化對(duì)每個(gè)像素位置或每個(gè)通道減去均值讓輸入分布在0附近。這樣做的原因是Sigmoid和Tanh這類激活函數(shù)在0附近梯度大、不飽和雖然ReLU對(duì)中心化不那么敏感但中心化仍然能讓優(yōu)化過程更穩(wěn)定尤其是配合Batch Normalization時(shí)。權(quán)重初始化也是訓(xùn)練成敗的隱形關(guān)卡。全零初始化不可行因?yàn)樗猩窠?jīng)元會(huì)同步更新永遠(yuǎn)無法分化出不同特征。用小隨機(jī)數(shù)初始化是可接受的基礎(chǔ)做法但更關(guān)鍵是要配合激活函數(shù)選擇方差尺度ReLU家族網(wǎng)絡(luò)更推薦He初始化它根據(jù)輸入維度調(diào)整權(quán)重方差保證前向傳播時(shí)信號(hào)的方差基本穩(wěn)定不會(huì)逐層放大或衰減。實(shí)測(cè)里初始化錯(cuò)誤不會(huì)讓網(wǎng)絡(luò)立即報(bào)錯(cuò)而是表現(xiàn)為loss在某個(gè)值附近震蕩或者訓(xùn)練很慢不下降這種問題排查起來比顯式報(bào)錯(cuò)痛苦得多所以寧可在一開始就按規(guī)則初始化。5.2 Batch Normalization和Dropout兩個(gè)作用完全不同的工具Batch Normalization簡稱BN在2017年已經(jīng)非常常用。它的核心操作是讓每一層卷積后的特征在通道維度上做一次標(biāo)準(zhǔn)化減均值再除以標(biāo)準(zhǔn)差然后用可學(xué)習(xí)的縮放和平移參數(shù)恢復(fù)表達(dá)能力。效果是網(wǎng)絡(luò)對(duì)初始化敏感度降低收斂速度明顯提升。放到卷積層時(shí)BN的作用位置是在卷積/全連接之后、激活函數(shù)之前這一點(diǎn)我在復(fù)現(xiàn)時(shí)經(jīng)常記反結(jié)果效果打了折扣。Dropout則是另一個(gè)維度的事它屬于正則化目標(biāo)是抑制過擬合。做法非常簡單粗暴訓(xùn)練時(shí)按概率隨機(jī)把一部分神經(jīng)元輸出置0讓網(wǎng)絡(luò)不能過度依賴某幾個(gè)節(jié)點(diǎn)迫使信息分散到更多連接中。這里最容易翻車的是忘記在驗(yàn)證和測(cè)試階段關(guān)閉Dropout或者把訓(xùn)練用的縮放邏輯搞錯(cuò)。我見過不少人的驗(yàn)證效果比訓(xùn)練差一大截排查半天發(fā)現(xiàn)是驗(yàn)證代碼里忘了關(guān)Dropout屬于新手區(qū)高頻失誤。5.3 數(shù)據(jù)增強(qiáng)不要錢的訓(xùn)練集擴(kuò)張數(shù)據(jù)增強(qiáng)在圖像任務(wù)里性價(jià)比極高。最簡單的幾招隨機(jī)水平翻轉(zhuǎn)、隨機(jī)裁剪、小幅顏色抖動(dòng)、隨機(jī)旋轉(zhuǎn)和縮放。這些變換不改變圖片的語義內(nèi)容但讓模型看到更多變體從而學(xué)到更魯棒的特征。課程里明確把它當(dāng)作一種正則化手段和Dropout、權(quán)值衰減并列。權(quán)值衰減L2正則化也值得提一句它給大權(quán)重加懲罰迫使模型使用分布更平緩的參數(shù)。通常系數(shù)設(shè)在10的負(fù)四次方到負(fù)五次方這個(gè)范圍。配上前面的增強(qiáng)和Dropout三者合起來能讓驗(yàn)證準(zhǔn)確率提升幾個(gè)點(diǎn)是非常劃算的組合拳。5.4 調(diào)學(xué)習(xí)率的過程比調(diào)結(jié)構(gòu)更影響最終結(jié)果課程里反復(fù)強(qiáng)調(diào)學(xué)習(xí)率可能是最需要重點(diǎn)調(diào)的超參數(shù)。太大容易震蕩甚至發(fā)散太小則收斂極其緩慢。常見做法是階梯式衰減比如每訓(xùn)練若干輪學(xué)習(xí)率乘0.1或者在驗(yàn)證loss不再下降時(shí)手動(dòng)降低學(xué)習(xí)率。我在復(fù)現(xiàn)過程中體會(huì)最深的一件事是與其盯著網(wǎng)絡(luò)結(jié)構(gòu)改來改去不如先跑一個(gè)少量數(shù)據(jù)的小實(shí)驗(yàn)把學(xué)習(xí)率、批大小這些訓(xùn)練參數(shù)調(diào)到合理范圍再投入全部數(shù)據(jù)。這個(gè)順序節(jié)省下來的時(shí)間和算力非??捎^。還有一條被說了無數(shù)遍但依然有效的經(jīng)驗(yàn)在做大實(shí)驗(yàn)之前先用極少量數(shù)據(jù)比如一個(gè)batch或幾十張圖把網(wǎng)絡(luò)跑到過擬合。如果連過擬合都做不到說明代碼里有bug如果能過擬合到接近100%才說明正向流程是通的。這個(gè)“先過擬合驗(yàn)證代碼”的思路是課程和后來各種工程實(shí)踐都一致認(rèn)可的起步動(dòng)作。6. 復(fù)習(xí)完這一講之后我想留下的幾條實(shí)操經(jīng)驗(yàn)先說最容易卡住新手的“尺寸問題”。每次搭網(wǎng)絡(luò)前我建議把每一層的輸入輸出尺寸、通道數(shù)、參數(shù)量都手寫在一個(gè)草稿表里。不要只依賴框架自動(dòng)計(jì)算因?yàn)槟阏嬲{(diào)試的時(shí)候發(fā)現(xiàn)尺寸不匹配會(huì)很難受。我自己吃過一次虧兩個(gè)分支結(jié)構(gòu)里的卷積padding參數(shù)寫錯(cuò)導(dǎo)致特征圖尺寸對(duì)不上拼接時(shí)直接報(bào)錯(cuò)排查了一個(gè)多小時(shí)才找到問題。這類問題提前算一遍基本可以規(guī)避。然后是關(guān)于“復(fù)現(xiàn)經(jīng)典結(jié)構(gòu)”的路徑推薦。如果你正在入門不建議一上來就啃幾十層的復(fù)雜結(jié)構(gòu)。先做一個(gè)小型卷積網(wǎng)絡(luò)跑到CIFAR級(jí)別的小數(shù)據(jù)集上看清卷積、池化、全連接之間怎么配合然后照著8層風(fēng)格的網(wǎng)絡(luò)復(fù)現(xiàn)一遍體會(huì)什么叫“深度增加帶來的表達(dá)力提升”最后再去碰殘差結(jié)構(gòu)這時(shí)你會(huì)真正理解為什么跨層連接能穩(wěn)住在深層網(wǎng)絡(luò)的訓(xùn)練。每走一步都把前面講的尺寸計(jì)算、初始化和正則化流程走一遍這些基本功才會(huì)變成肌肉記憶。我最后一次完整復(fù)習(xí)這講內(nèi)容時(shí)也順帶整理了一個(gè)適合自己的檢查清單數(shù)據(jù)有沒有做零中心化BN的位置是不是在激活之前Dropout在驗(yàn)證時(shí)有沒有關(guān)閉卷積輸出尺寸有沒有算錯(cuò)初始化是不是按激活函數(shù)選了對(duì)應(yīng)的方案。如果這五項(xiàng)都對(duì)訓(xùn)練一般不會(huì)出現(xiàn)“完全學(xué)不動(dòng)”的詭異情況。遇到loss不降時(shí)我第一反應(yīng)不是改網(wǎng)絡(luò)結(jié)構(gòu)而是回頭核對(duì)這個(gè)清單。最后分享一個(gè)觀念上的轉(zhuǎn)變。最開始看這類筆記總會(huì)忍不住去記每個(gè)經(jīng)典網(wǎng)絡(luò)的層數(shù)、參數(shù)量、準(zhǔn)確率但這些數(shù)字過幾個(gè)月就會(huì)模糊。真正留在腦子里的是卷積為什么比全連接適合圖像、感受野是怎么被小卷積核擴(kuò)大的、網(wǎng)絡(luò)加深為什么需要?dú)埐钸B接兜底。理解了這些動(dòng)機(jī)之后再去看任何新模型都不會(huì)覺得是一堆陌生名詞的堆砌。這大概是第五講對(duì)我來說最大的價(jià)值。