不少人都說訓練神經網絡和鍊金術師煉藥的過程相像,難以破解其中的黑盒子。其實否則,在訓練的時候咱們依然能夠經過大量的技巧去最大化咱們的訓練效果,從而幫助咱們的任務取得不錯的精度,這些技巧是訓練神經網絡不可缺乏的一環。html
本文儘量說明訓練過程當中所須要的各類小技巧,會有不完善的地方,限於篇幅每一個點不會說很細,可是這些觀念是咱們都須要掌握的,牢記這幾點,在訓練神經網絡的過程當中就能夠駕輕就熟,讓煉丹再也不沒有頭緒~git
overfitting
即過擬合,典型的表現爲訓練集損失遠遠小於驗證集損失。而欠擬合則表現爲訓練集損失大於驗
證集損失。github
咱們要清楚遠遠大於的概念,若是訓練集損失只比驗證集損失多一點點的話,同等數量級(例如0.8與0.9)這種狀況下並非過擬合的表現。咱們通常遇到的過擬合應該是0.8(訓練集損失)與2.0(驗證集損失)這種不在一個量級的損失比。算法
Dropout相似於bagging ensemble減小variance。也就是投經過投票來減小可變性。一般咱們在全鏈接層部分使用dropout,在卷積層則不使用。但要聲明,dropout並不適合全部的狀況,請你們不要無腦上Dropout
。bash
Dropout
通常適合於全鏈接層部分,而卷積層因爲其參數並非不少,因此不須要dropout,加上的話對模型的泛化能力並無太大的影響。以下圖:網絡
咱們通常在網絡的最開始和結束的時候使用全鏈接層,而hidden layers則是網絡中的卷積層。因此通常狀況,在全鏈接層部分,採用較大機率的dropout而在卷積層採用低機率或者不採用dropout。app
進一步請看相關討論機器學習
數據集的好壞是算法泛化好壞的一個很是重要的前提條件,咱們一般在構建深度學習的任務中,所獲得的數據集通常不會是很是完美的(不管是本身搭建仍是利用他人的數據,在數據集量過大的時候,數據集中不免會有圖像損壞或者錯誤的個例)。分佈式
若是有損壞的圖像,若是咱們不知情,通常來講,在咱們使用代碼讀取的時候就會報錯,舉個例子:raise IOError("image file is truncated) "
。ide
在Kaggle的一個比賽中就存在這樣的狀況,訓練的數據中有10w+的圖像數據,可是存在10餘張的圖像內容缺失(圖像大小明顯小於其餘正常圖像)或者直接被損壞沒法讀取。這個時候就須要咱們本身去手動編寫代碼將那些錯誤且沒法參與訓練的圖像挑選出來。
那麼若是正確過濾這些圖像呢?
固然,數據集損壞的形式還有不少,須要咱們本身去發掘。在一開始獲得數據集的時候最好不要直接開始訓練,應該去仔細檢查本身的數據集是否有問題,這樣能夠避免不少以後訓練時須要的處理的麻煩。
在任何一個深度學習任務中,咱們都會遇到一些比較「棘手」的數據,這些數據相比較於其餘的普通數據更難識別,這種特比容易識別錯誤的例子就稱爲hard-negative
。
舉個栗子。
好比Kaggle比賽中的一個識別遙感圖像中船隻的任務,使用的圖像集是從一張大的遙感圖中裁剪出來的,每張圖的大小爲768*768,在簡單地對圖像進行分類時(僅僅分類圖像中有無船隻),在validation中發現最容易識別出錯的圖以下:
在觀察到這些最難辦的圖像的特徵後,咱們能夠針對這些難辦的圖像採起一些方法來解決這些問題。咱們先用初始的正負樣本(通常是正樣本+與正樣本同規模的負樣本的一個子集)訓練分類器, 而後再用訓練出的分類器對樣本進行分類, 把其中負樣本中錯誤分類的那些樣本(hard negative)放入負樣本集合, 再繼續訓練分類器, 如此反覆, 直到達到中止條件(好比分類器性能再也不提高)。也就是不停滴將困難樣本拿去訓練,讓分類器更好地學習到難以學習的特徵,簡單來講就是熟能生巧嘛。
而在fast-rcnn中,這個方法也被使用了:
在 Fast-RCNN 中將與 groud-truth 的 IoU 在 [0.1, 0.5) 之間的圖像標記爲負例,[0, 0.1)的example 用於hard negative mining.在訓練時通常輸入爲N=2張圖片, 選擇128個RoI,即每張圖片64個RoI。對於每張圖片, 按照1:3的比例來抽取RoI, 抽取正負樣本的比例爲1:3,要在負例中抽取48個。
相關的兩篇文章能夠看一下
[17] P. Felzenszwalb, R. Girshick, D. McAllester, and D. Ramanan. Object detection with discriminatively trained part based models. TPAMI, 2010.
[37] K. Sung and T. Poggio. Example-based learning for viewbased human face detection. Technical Report A.I. Memo No. 1521, Massachussets Institute of Technology, 1994.
複製代碼
學習率是一個很是很是重要的超參數,這個參數呢,面對不一樣規模、不一樣batch-size、不一樣優化方式、不一樣數據集,其最合適的值都是不肯定的,咱們沒法光憑經驗來準確地肯定lr
的值,咱們惟一能夠作的,就是在訓練中不斷尋找最合適當前狀態的學習率。
好比下圖利用fastai中的lr_find()函數尋找合適的學習率,根據下方的學習率-損失曲線獲得此時合適的學習率爲1e-2
。
若是想要了解更多,這裏推薦一篇fastai首席設計師Sylvain Gugger的一篇博客:How Do You Find A Good Learning Rate
以及相關的論文Cyclical Learning Rates for Training Neural Networks。
通常來講,越大的batch-size使用越大的學習率。
原理很簡單,越大的batch-size
意味着咱們學習的時候,收斂方向的confidence
越大,咱們前進的方向更加堅決,而小的batch-size
則顯得比較雜亂,毫無規律性,由於相比批次大的時候,批次小的狀況下沒法照顧到更多的狀況,因此須要小的學習率來保證不至於出錯。
能夠看下圖損失Loss
與學習率Lr
的關係:
上圖來源於這篇文章:Visualizing Learning rate vs Batch size
固然咱們也能夠從上圖中看出,當batchsize變大後,獲得好的測試結果所能容許的lr範圍在變小,也就是說,當batchsize很小時,比較容易找打一個合適的lr達到不錯的結果,當batchsize變大後,可能須要精細地找一個合適的lr才能達到較好的結果,這也給實際的large batch分佈式訓練帶來了困難。
因此說,在顯存足夠的條件下,最好採用較大的batch-size進行訓練,找到合適的學習率後,能夠加快收斂速度。另外,較大的batch-size能夠避免batch normalization出現的一些小問題:github.com/pytorch/pyt…
更多相似的問題能夠在知乎找到相關答案:www.zhihu.com/question/64…
首先說下遷移學習,遷移學習是一種很常見的深度學習技巧,咱們利用不少預訓練的經典模型直接去訓練咱們本身的任務。雖說領域不一樣,可是在學習權重的廣度方面,兩個任務之間仍是有聯繫的。
由上圖,咱們拿來model A訓練好的模型權重去訓練咱們本身的模型權重(Model B),其中,modelA多是ImageNet的預訓練權重,而ModelB則是咱們本身想要用來識別貓和狗的預訓練權重。
那麼差分學習率和遷移學習有什麼關係呢?咱們直接拿來其餘任務的訓練權重,在進行optimize的時候,如何選擇適當的學習率是一個很重要的問題。
通常地,咱們設計的神經網絡(以下圖)通常分爲三個部分,輸入層,隱含層和輸出層,隨着層數的增長,神經網絡學習到的特徵越抽象。所以,下圖中的卷積層和全鏈接層的學習率也應該設置的不同,通常來講,卷積層設置的學習率應該更低一些,而全鏈接層的學習率能夠適當提升。
這就是差分學習率的意思,在不一樣的層設置不一樣的學習率,能夠提升神經網絡的訓練效果,具體的介紹能夠查看下方的鏈接。
上面的示例圖來自:towardsdatascience.com/transfer-le…
餘弦就是相似於餘弦函數的曲線,退火就是降低,餘弦退火就是學習率相似餘弦函數慢慢降低。
熱重啓就是在學習的過程當中,學習率慢慢降低而後忽然再回彈(重啓)而後繼續慢慢降低。
兩個結合起來就是下方的學習率變化圖:
更多詳細的介紹能夠查看知乎機器學習算法如何調參?這裏有一份神經網絡學習速率設置指南
以及相關論文SGDR: Stochastic Gradient Descent with Warm Restarts
權重初始化相比於其餘的trick來講在日常使用並非很頻繁。
爲何呢?
緣由很簡單,由於大部分人使用的模型都是預訓練模型,使用的權重都是在大型數據集上訓練好的模型,固然不須要本身去初始化權重了。只有沒有預訓練模型的領域會本身初始化權重,或者在模型中去初始化神經網絡最後那幾個全鏈接層的權重。
那麼你們喜歡用什麼初始化權重算法?
固然是kaiming_normal或者xavier_normal。
相關論文:
Delving deep into rectifiers: Surpassing human-level performance on ImageNet classification
Understanding the difficulty of training deep feedforward neural networks
多尺度訓練是一種直接有效的方法,經過輸入不一樣尺度的圖像數據集,由於神經網絡卷積池化的特殊性,這樣可讓神經網絡充分地學習不一樣分辨率下圖像的特徵,能夠提升機器學習的性能。
也能夠用來處理過擬合效應,在圖像數據集不是特別充足的狀況下,能夠先訓練小尺寸圖像,而後增大尺寸並再次訓練相同模型,這樣的思想在Yolo-v2的論文中也提到過:
須要注意的是:多尺度訓練並非適合全部的深度學習應用,多尺度訓練能夠算是特殊的數據加強方法,在圖像大小這一塊作了調整。若是有可能最好利用可視化代碼將多尺度後的圖像近距離觀察一下,看看多尺度會對圖像的總體信息有沒有影響,若是對圖像信息有影響的話,這樣直接訓練的話會誤導算法致使得不到應有的結果。
按理說不一樣的優化算法適合於不一樣的任務,不過咱們大多數採用的優化算法仍是是adam和SGD+monmentum。
這兩個爲何好用?
經驗唄~
這是一個經典的小trick了,可是不少人並不這樣作,能夠嘗試一下。
關閉正則化/隨機失活/數據擴充,使用訓練集的一小部分,讓神經網絡訓練幾個週期。確保能夠實現零損失,若是沒有,那麼極可能什麼地方出錯了。
在李航的統計學方法中說到,交叉驗證每每是對實際應用中數據不充足而採用的,基本目的就是重複使用數據。在日常中咱們將全部的數據分爲訓練集和驗證集就已是簡單的交叉驗證了,能夠稱爲1折交叉驗證。注意,交叉驗證和測試集不要緊,測試集是用來衡量咱們的算法標準的,不參與到交叉驗證中來。
交叉驗證只針對訓練集和驗證集。
交叉驗證是Kaggle比賽中特別推崇的一種技巧,咱們常用的是5-折(5-fold)交叉驗證,將訓練集分紅5份,隨機挑一份作驗證集其他爲訓練集,循環5次,這種比較常見計算量也不是很大。還有一種叫作leave-one-out cross validation
留一交叉驗證,這種交叉驗證就是n-折交叉,n表示數據集的容量,這種方法只適合數據量比較小的狀況,計算量很是大的狀況不多用到這種方法。
吳恩達有一節課The nuts and bolts of building applications using deep learning中也提到了。
若是數據集極其不平衡,假如咱們有個檢測船隻的任務,在100000圖中只有30000張圖中含有船隻,其他圖像都是不含船隻的圖像,這時候若是對此直接進行訓練效果應該會不好。爲此,首先能夠挑選出只有船隻的圖像集合進行初步訓練。其次,使用訓練好的模型去檢測沒有訓練的部分(不含船隻),挑選出檢測失敗的false positive(也就是在沒有船的圖像集中檢測出船隻了)加入以前的訓練集再次進行訓練。
數據集加強是一個老生常談的話題了,咱們爲何須要那麼多數據?爲何須要數據加強技術?
能夠看這篇文章來了解一下:深度學習爲何須要那麼多的數據?
這裏只簡單說下咱們經常使用的數據加強的Transform
。
大部分咱們使用的圖像加強技術通常是隨機旋轉,水平翻轉,高斯模糊和尺度變化還有什麼拉伸等blabla的操做。這些圖像變化對大部分的任務是比較適合的,但針對特定的任務,存在某一簇特殊的圖像加強技術能夠達到比普通圖像加強技術更好的效果。
例如夜視圖或者光照:
但也須要提個醒,並非全部的圖像加強均可以提高模型的泛化能力。
並且有些圖像加強技術會對原始圖像形成損失從而致使神經網絡學習到錯誤的信息,這點是咱們比較容易忽視的問題,一樣重要,相關內容能夠查看fastai中的圖像加強技術爲何相對比較好。
最初這個概念是在fastai課程中看到的,這個過程在訓練階段不會參與,是經過在驗證和測試階段進行的。具體過程是,對所要處理的圖像進行幾種隨機的圖像加強變化,而後對每種圖像加強後的圖像進行預測,對預測結果取平均值。
原理相似於模型平均,犧牲推斷速度來實現推斷精度的提高。
固然,這個技術也有好有壞,在我本身跑的衛星圖數據集中採用TTA的精確度比不採用低了0.03個百分點。
大概先說這麼多,訓練神經網絡真的很像煉丹,而咱們全部使用的技巧tricks,也只是增長一些煉丹的成功率,而究竟煉丹能不能成功,最終仍是要取決於咱們設計的算法合不合理。
www.cnblogs.com/nowgood/p/H…
towardsdatascience.com/kaggle-plan…
文章來源於OLDPAN博客,歡迎來訪:Oldpan博客
歡迎關注Oldpan博客公衆號,持續醞釀深度學習質量文: