在經(jīng)歷成千上萬(wàn)個(gè)小時(shí)機(jī)器學(xué)習(xí)訓(xùn)練時(shí)間后,計(jì)算機(jī)并不是唯一學(xué)到很多東西的角色,作為開(kāi)發(fā)者和訓(xùn)練者的我們也犯了很多錯(cuò)誤,修復(fù)了許多錯(cuò)誤,從而積累了很多經(jīng)驗(yàn)。在本文中,作者基于自己的經(jīng)驗(yàn)(主要基于 TensorFlow)提出了一些訓(xùn)練神經(jīng)網(wǎng)絡(luò)的建議,還結(jié)合了案例,可以說(shuō)是過(guò)來(lái)人的實(shí)踐技巧了。
通用技巧
有些技巧對(duì)你來(lái)說(shuō)可能就是明擺著的事,但在某些時(shí)候可能卻并非如此,也可能存在不適用的情況,甚至對(duì)你的特定任務(wù)來(lái)說(shuō),可能不是一個(gè)好的技巧,所以使用時(shí)需要?jiǎng)?wù)必要謹(jǐn)慎!
▌使用 ADAM 優(yōu)化器
確實(shí)很有效。與更傳統(tǒng)的優(yōu)化器相比,如 Vanilla 梯度下降法,我們更喜歡用ADAM優(yōu)化器。用 TensorFlow 時(shí)要注意:如果保存和恢復(fù)模型權(quán)重,請(qǐng)記住在設(shè)置完AdamOptimizer 后設(shè)置 Saver,因?yàn)?ADAM 也有需要恢復(fù)的狀態(tài)(即每個(gè)權(quán)重的學(xué)習(xí)率)。
▌ReLU 是最好的非線性(激活函數(shù))
就好比 Sublime 是最好的文本編輯器一樣。ReLU 快速、簡(jiǎn)單,而且,令人驚訝的是,它們工作時(shí),不會(huì)發(fā)生梯度遞減的情況。雖然 sigmoid 是常見(jiàn)的激活函數(shù)之一,但它并不能很好地在 DNN 進(jìn)行傳播梯度。
▌不要在輸出層使用激活函數(shù)
這應(yīng)該是顯而易見(jiàn)的道理,但如果使用共享函數(shù)構(gòu)建每個(gè)層,那就很容易犯這樣的錯(cuò)誤:所以請(qǐng)確保在輸出層不要使用激活函數(shù)。
▌?wù)堅(jiān)诿恳粋€(gè)層添加一個(gè)偏差
這是 ML 的入門(mén)知識(shí)了:偏差本質(zhì)上就是將平面轉(zhuǎn)換到最佳擬合位置。在 y=mx+b 中,b 是偏差,允許曲線上下移動(dòng)到“最佳擬合”位置。
▌使用方差縮放(variance-scaled)初始化
在 Tensorflow 中,這看起來(lái)像tf.reemaner.variance_scaling_initializer()。根據(jù)我們的經(jīng)驗(yàn),這比常規(guī)的高斯函數(shù)、截尾正態(tài)分布(truncated normal)和 Xavier 能更好地泛化/縮放。
粗略地說(shuō),方差縮放初始化器根據(jù)每層的輸入或輸出數(shù)量(TensorFlow中的默認(rèn)值是輸入數(shù)量)調(diào)整初始隨機(jī)權(quán)重的方差,從而有助于信號(hào)更深入地傳播到網(wǎng)絡(luò)中,而無(wú)須額外的裁剪或批量歸一化(batch normalization)。Xavier 與此相似,只是各層的方差幾乎相同;但是不同層形狀變化很大的網(wǎng)絡(luò)(在卷積網(wǎng)絡(luò)中很常見(jiàn))可能不能很好地處理每層中的相同方差。
▌歸一化輸入數(shù)據(jù)
對(duì)于訓(xùn)練,減去數(shù)據(jù)集的均值,然后除以它的標(biāo)準(zhǔn)差。在每個(gè)方向的權(quán)重越少,你的網(wǎng)絡(luò)就越容易學(xué)習(xí)。保持輸入數(shù)據(jù)以均值為中心且方差恒定有助于實(shí)現(xiàn)這一點(diǎn)。你還必須對(duì)每個(gè)測(cè)試輸入執(zhí)行相同的規(guī)范化,因此請(qǐng)確保你的訓(xùn)練集與真實(shí)數(shù)據(jù)相似。
以合理保留其動(dòng)態(tài)范圍的方式縮放輸入數(shù)據(jù)。這與歸一化有關(guān),但應(yīng)該在歸一化之前就進(jìn)行。例如,真實(shí)世界范圍為 [0,140000000] 的數(shù)據(jù) x 通常可以用 tanh(x) 或 tanh(x/C) 來(lái)控制,其中 C 是一些常數(shù),它可以拉伸曲線,以適應(yīng) tanh 函數(shù)緩坡部分的動(dòng)態(tài)范圍內(nèi)的更多輸入范圍。特別是在輸入數(shù)據(jù)在一端或兩端可能不受限制的情況下,神經(jīng)網(wǎng)絡(luò)將在(0,1)之間學(xué)習(xí)得更好。
▌一般不用學(xué)習(xí)率衰減
學(xué)習(xí)率衰減在 SGD 中更為常見(jiàn),但 ADAM 很自然地處理了這個(gè)問(wèn)題。如果你真的想把每一分表現(xiàn)都擠出去:在訓(xùn)練結(jié)束時(shí)短時(shí)間內(nèi)降低學(xué)習(xí)率;你可能會(huì)看到突然的、非常小的誤差下降,然后它會(huì)再次變平。
如果你的卷積層有 64 或 128 個(gè)過(guò)濾器,那就足夠了。特別是一個(gè)對(duì)于深度網(wǎng)絡(luò)而言。比如,128 個(gè)真的就已經(jīng)很多了。如果你已經(jīng)有了大量的過(guò)濾器,那么再添加更多的過(guò)濾器未必會(huì)進(jìn)一步提高性能。
▌池化用于平移不變性
池化本質(zhì)上就是讓網(wǎng)絡(luò)學(xué)習(xí)圖像“那部分”的“總體思路”。例如,最大池化可以幫助卷積網(wǎng)絡(luò)對(duì)圖像中的特征的平移、旋轉(zhuǎn)和縮放變得更加健壯。
調(diào)試神經(jīng)網(wǎng)絡(luò)
如果你的網(wǎng)絡(luò)沒(méi)能很好地進(jìn)行學(xué)習(xí)(指在訓(xùn)練過(guò)程中損失/準(zhǔn)確率沒(méi)有收斂,或者沒(méi)有得到預(yù)期的結(jié)果),那么可以試試以下的技巧:
▌過(guò)擬合
如果你的網(wǎng)絡(luò)沒(méi)有學(xué)習(xí),那么首先要做的第一件事就是對(duì)訓(xùn)練點(diǎn)進(jìn)行過(guò)擬合。準(zhǔn)確率基本上應(yīng)為 100% 或 99.99%,或誤差接近 0。如果你的神經(jīng)網(wǎng)絡(luò)不能對(duì)單個(gè)數(shù)據(jù)點(diǎn)進(jìn)行過(guò)擬合,那么體系架構(gòu)就可能有嚴(yán)重的問(wèn)題,但這可能是微妙的。如果你可以對(duì)一個(gè)數(shù)據(jù)點(diǎn)進(jìn)行過(guò)擬合,但是對(duì)較大的集合進(jìn)行訓(xùn)練仍然無(wú)法收斂,請(qǐng)嘗試以下建議:
▌降低學(xué)習(xí)率
你的網(wǎng)絡(luò)學(xué)習(xí)就會(huì)變得更慢一些,但是它可能會(huì)找到以前無(wú)法進(jìn)入的最小化的方式,因?yàn)樗牟介L(zhǎng)太大了。
▌提高學(xué)習(xí)率
這樣做將會(huì)加快訓(xùn)練,有助于收緊反饋,這意味著無(wú)論你的網(wǎng)絡(luò)是否正常工作,你都會(huì)很快地知道你的網(wǎng)絡(luò)是否有效。雖然網(wǎng)絡(luò)應(yīng)該更快地收斂,但其結(jié)果可能不會(huì)很好,而且“收斂”實(shí)際上可能會(huì)跳來(lái)跳去。(對(duì)于 ADAM 優(yōu)化器,我們發(fā)現(xiàn)在很多經(jīng)歷中,學(xué)習(xí)率大約為 0.001 時(shí),表現(xiàn)很不錯(cuò)。)
▌減少批量處理規(guī)模
將批處理大小減小到 1,可以為你提供與權(quán)重更新相關(guān)的更細(xì)粒度的反饋,你應(yīng)該使用TensorBoard(或其他一些調(diào)試/可視化工具)展示出來(lái)。
▌刪除批歸一化層
隨著批處理大小減少到 1,這樣做會(huì)暴露出梯度消失或梯度爆炸的問(wèn)題。我們?cè)羞^(guò)一個(gè)網(wǎng)絡(luò),在好幾周都沒(méi)有收斂,當(dāng)我們刪除了批歸一化層之后,我們才意識(shí)到第二次迭代時(shí)輸出都是 NaN。就像是創(chuàng)可貼上的吸水墊,它也有它可以發(fā)揮效果的地方,但前提是你知道網(wǎng)絡(luò)沒(méi)有 Bug。
▌增加批量處理的規(guī)模
一個(gè)更大的批處理規(guī)模,如果可以的話,整個(gè)訓(xùn)練集減少梯度更新中的方差,使每個(gè)迭代更準(zhǔn)確。換句話說(shuō),權(quán)重更新將朝著正確的方向發(fā)展。但是!它的可用性和物理內(nèi)存限制都有一個(gè)有效的上限。通常,我們發(fā)現(xiàn)這個(gè)建議不如上述兩個(gè)建議有用,可以將批處理規(guī)模減少到1并刪除批歸一化層。
▌檢查你的重構(gòu)
大幅度的矩陣重構(gòu)(如改變圖像的X、Y 維度)會(huì)破壞空間局部性,使網(wǎng)絡(luò)更難學(xué)習(xí),因?yàn)樗脖仨殞W(xué)會(huì)重塑。(自然特征變得支離破碎。事實(shí)上,自然特征在空間上呈局部性,也是為什么卷積神經(jīng)網(wǎng)絡(luò)能如此有效的原因!)如果使用多個(gè)圖像/通道進(jìn)行重塑,請(qǐng)?zhí)貏e小心;使用 numpi.stack()進(jìn)行適當(dāng)?shù)膶?duì)齊操作。
▌仔細(xì)檢查你的損失函數(shù)
如果使用一個(gè)復(fù)雜的函數(shù),請(qǐng)嘗試將其簡(jiǎn)化為 L1 或 L2。我們發(fā)現(xiàn)L1對(duì)異常值不那么敏感,在發(fā)出噪聲的批或訓(xùn)練點(diǎn)時(shí),不會(huì)做出太大的調(diào)整。
如果可以的話,仔細(xì)檢查你的可視化。你的可視化庫(kù)(matplotlib、OpenCV等)是調(diào)整值的比例呢,還是它們進(jìn)行裁剪?可考慮使用一種視覺(jué)上均勻的配色方案。
實(shí)戰(zhàn)分析
為了使上面所描述的過(guò)程更容易讓讀者理解,我們這兒有一些用于描述我們構(gòu)建的卷積神經(jīng)網(wǎng)絡(luò)的真實(shí)回歸實(shí)驗(yàn)的損失圖(通過(guò)TesnorBoard)。
起初,這個(gè)網(wǎng)絡(luò)根本沒(méi)有學(xué)習(xí):
我們?cè)噲D裁剪這些值,以防止它們超出界限:
嗯。看看不平滑的值有多瘋狂啊!學(xué)習(xí)率是不是太高了?我們?cè)囍谝粋€(gè)輸入數(shù)據(jù)上降低學(xué)習(xí)率并進(jìn)行訓(xùn)練:
你可以看到學(xué)習(xí)率的前幾個(gè)變化發(fā)生的位置(大約在 300 步和 3000 步)。顯然,我們衰減得太快了。所以,給它更多的衰減時(shí)間,它表現(xiàn)得會(huì)更好:
你可以看到我們?cè)?2000 步和 5000 步的時(shí)候衰減了。這樣更好一些了,但還不夠好,因?yàn)樗鼪](méi)有趨于 0。
然后我們禁用了 LR 衰減,并嘗試將值移動(dòng)到更窄的范圍內(nèi),而不是通過(guò) tanh 輸入。雖然這顯然使誤差值小于 1,但我們?nèi)匀徊荒軐?duì)訓(xùn)練集進(jìn)行過(guò)擬合:
這里我們發(fā)現(xiàn),通過(guò)刪除批歸一化層,網(wǎng)絡(luò)在一到兩次迭代之后迅速輸出 NaN。我們禁用了批歸一化,并將初始化更改為方差縮放。這些改變了一切!我們能夠?qū)χ挥幸粌蓚€(gè)輸入的測(cè)試集進(jìn)行過(guò)擬合了。當(dāng)?shù)撞康膱D標(biāo)裁剪Y軸時(shí),初始誤差值遠(yuǎn)高于 5,表明誤差減少了近 4 個(gè)數(shù)量級(jí):
上面的圖表是非常平滑的,但是你可以看到它非常快地?cái)M合了測(cè)試輸入,隨著時(shí)間的推移,整個(gè)訓(xùn)練集的損失降低到了 0.01 以下。這沒(méi)有降低學(xué)習(xí)速度。然后我們將學(xué)習(xí)速率降低一個(gè)數(shù)量級(jí)后繼續(xù)訓(xùn)練,得到更好的結(jié)果:
這些結(jié)果好得多了!但是,如果我們以幾何方式降低學(xué)習(xí)率,而不是將訓(xùn)練分成兩部分,會(huì)發(fā)生什么樣的結(jié)果呢?
通過(guò)在每一步將學(xué)習(xí)率乘以 0.9995,結(jié)果就不那么好了:
大概是因?yàn)閷W(xué)習(xí)率衰減太快了吧。乘數(shù)為 0.999995 會(huì)表現(xiàn)的更好,但結(jié)果幾乎相當(dāng)于完全沒(méi)有衰減。我們從這個(gè)特定的實(shí)驗(yàn)序列中得出結(jié)論,批歸一化隱藏了由槽糕的初始化引起的爆炸梯度,并且 ADAM 優(yōu)化器對(duì)學(xué)習(xí)率的衰減并沒(méi)有什么特別的幫助,與批歸一化一樣,裁剪值只是掩蓋了真正的問(wèn)題。我們還通過(guò) tanh 來(lái)控制高方差輸入值。
我們希望,本文提到的這些基本技巧能夠在你構(gòu)建深度神經(jīng)網(wǎng)絡(luò)時(shí)有所幫助。通常,正式因?yàn)楹?jiǎn)單的事情才改變了這一切。
-
神經(jīng)網(wǎng)絡(luò)
+關(guān)注
關(guān)注
42文章
4772瀏覽量
100851 -
ADAM
+關(guān)注
關(guān)注
0文章
13瀏覽量
9810
原文標(biāo)題:一位ML工程師構(gòu)建深度神經(jīng)網(wǎng)絡(luò)的實(shí)用技巧
文章出處:【微信號(hào):rgznai100,微信公眾號(hào):rgznai100】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論