卷積神經網絡性能優化(提高準確率)

神經網絡是一種在很多用例中能夠提供最優準確率的機器學習算法。但是,很多時候我們構建的神經網絡的準確率可能無法令人滿意,或者無法讓我們在數據科學競賽中拿到領先名次。所以,我們總是在尋求更好的方式來改善模型的性能。有很多技術可以幫助我們達到這個目標。本文將介紹這些技術,幫助大家構建更準確的神經網絡。

過擬合

過擬合,典型的表現為訓練集損失遠遠小於驗證集損失。而欠擬合則表現為訓練集損失大於驗證集損失。

卷積神經網絡性能優化(提高準確率)

保證神經網絡在測試集上運行良好的第一步就是驗證神經網絡沒有過擬合。

我們要清楚遠遠大於的概念,如果訓練集損失只比驗證集損失多一點點的話,同等數量級(例如0.8與0.9)這種情況下並不是過擬合的表現。我們一般遇到的過擬合應該是0.8(訓練集損失)與2.0(驗證集損失)這種不在一個量級的損失比。

什麼是過擬合呢?

當你的模型開始記錄訓練數據而不是從中學習的時候,就發生了過擬合。然後,當你的模型遇到之前沒有見過的數據時,它就無法很好的運行。為了更好地理解,我們來看一個類比。

我們有一個記性特好的同學,假設一次數學考試馬上就要來臨了。你和這位擅長記憶的同學開始學習課本。這名同學記住課本中的每一個公式、問題以及問題的答案,然而你要比他來得聰明一些,所以你決定以直覺為基礎、解決問題、學習這些公式是如何發揮作用的。考試來了,如果試卷中的問題是直接來源於課本的,那麼可以想像那名記憶力超群的同學發揮得更好,但是,如果試題是涉及應用直觀知識的全新問題,那麼你將會做得更好,而你的朋友會慘敗。

如何鑑別模型是否過擬合呢?

你僅僅需要交叉檢查訓練準確率和測試準確率。如果訓練準確率遠遠高出了測試準確率,那麼可以斷定你的模型是過擬合了。你也可以在圖中畫出預測點來驗證。下面是一些避免過擬合的技術:

  1. 數據正則化(L1 或 L2);
  2. Dropout:隨機丟棄一些神經元之間的連接,強制神經網絡尋找新的路徑並泛化;

Dropout類似於bagging ensemble減少variance。也就是投通過投票來減少可變性。通常我們在全連接層部分使用dropout,在卷積層則不使用。但要聲明,dropout並不適合所有的情況,請大家不要無腦上Dropout。

Dropout一般適合於全連接層部分,而卷積層由於其參數並不是很多,所以不需要dropout,加上的話對模型的泛化能力並沒有太大的影響。如下圖:

卷積神經網絡性能優化(提高準確率)

我們一般在網絡的最開始和結束的時候使用全連接層,而hidden layers則是網絡中的卷積層。所以一般情況,在全連接層部分,採用較大概率的dropout而在卷積層採用低概率或者不採用dropout。

  1. 早停(Early Stopping):促使神經網絡訓練早點停止,以減少在測試集中的誤差。

超參數調節

卷積神經網絡性能優化(提高準確率)

超參數是你必須給網絡初始化的值,這些數值不能在訓練的過程中學到。在卷積神經網絡中,這些超參數包括:核大小、神經網絡層數、激活函數、損失函數、所用的優化器(梯度下降、RMSprop)、批大小、訓練的 epoch 數量等等。

每個神經網絡都會有最佳超參數組合,這組參數能夠得到最大的準確率。你也許會問,「有這麼多超參數,我如何選擇每個參數呢?

不幸的是,對每個神經網絡而言,並沒有確定最佳超參數組合的直接方法,所以通常都是通過反覆試驗得到的。但是也有一些關於上述超參數的最佳實踐:

學習率: 選擇最優學習率是很重要的,因為它決定了神經網絡是否可以收斂到全局最小值。選擇較高的學習率幾乎從來不能到達全局最小值,因為你很可能跳過它。所以,你總是在全局最小值附近,但是從未收斂到全局最小值。選擇較小的學習率有助於神經網絡收斂到全局最小值,但是會花費很多時間。這樣你必須用更多的時間來訓練神經網絡。較小的學習率也更可能使神經網絡困在局部極小值裡面,也就是說,神經網絡會收斂到一個局部極小值,而且因為學習率比較小,它無法跳出局部極小值。所以,在設置學習率的時候你必須非常謹慎。

比如下圖利用fastai中的lr_find()函數尋找合適的學習率,根據下方的學習率-損失曲線得到此時合適的學習率為1e-2

卷積神經網絡性能優化(提高準確率)

如果想要了解更多,這裡推薦一篇fastai首席設計師Sylvain Gugger的一篇博客:How Do You Find A Good Learning Rate以及相關的論文Cyclical Learning Rates for Training Neural Networks。

神經網絡架構: 並不存在能夠在所有的測試集中帶來高準確率的標準網絡架構。你必須實驗,嘗試不同的架構,從實驗結果進行推斷,然後再嘗試。我建議使用已經得到驗證的架構,而不是構建自己的網絡架構。例如:對於圖像識別任務,有 VGG、Resnet、谷歌的 Inception 網絡等。這些都是開源的,而且已經被證明具有較高的準確率。所以你可以把這些架構複製過來,然後根據自己的目的做一些調整。

優化器和損失函數: 這方面有很多可供選擇。事實上,如果有必要,你可以自定義損失函數。常用的優化器有 RMSprop、隨機梯度下降和 Adam。這些優化器貌似在很多用例中都可以起作用。如果你的任務是分類任務,那麼常用的損失函數是類別交叉熵。如果你在執行迴歸任務,那麼均方差是最常用的損失函數。你可以自由地使用這些優化器超參數進行試驗,也可以使用不同的優化器和損失函數。

批大小和 epoch 次數: 同樣,沒有適用於所有用例的批大小和 epoch 次數的標準值。你必須進行試驗,嘗試不同的選擇。在通常的實踐中,批大小被設置為 8、16、32……epoch 次數則取決於開發者的偏好以及他/她所擁有的計算資源。

權重初始化 權重初始化相比於其他的trick來說在平常使用並不是很頻繁。為什麼呢?原因很簡單,因為大部分人使用的模型都是預訓練模型,使用的權重都是在大型數據集上訓練好的模型,當然不需要自己去初始化權重了。只有沒有預訓練模型的領域會自己初始化權重,或者在模型中去初始化神經網絡最後那幾個全連接層的權重。那麼大家喜歡用什麼初始化權重算法? 當然是kaiming_normal或者xavier_normal。

相關論文:

Delving deep into rectifiers: Surpassing human-level performance on ImageNet classificationUnderstanding the difficulty of training deep feedforward neural networks

激活函數: 激活函數映射非線性函數輸入和輸出。激活函數是特別重要的,選擇合適的激活函數有助於模型學習得更好。現在,整流線性單元(ReLU)是最廣泛使用的激活函數,因為它解決了梯度消失的問題。更早時候,Sigmoid 和 Tanh 函數都是最常用的激活函數。但是它們都會遇到梯度消失的問題,即在反向傳播中,梯度在到達初始層的過程中,值在變小,趨向於 0。這不利於神經網絡向具有更深層的結構擴展。ReLU 克服了這個問題,因此也就可以允許神經網絡擴展到更深的層。

卷積神經網絡性能優化(提高準確率)

learning-rate學習率與batch-size批大小的關係 一般來說,越大的batch-size使用越大的學習率。

原理很簡單,越大的batch-size意味著我們學習的時候,收斂方向的confidence越大,我們前進的方向更加堅定,而小的batch-size則顯得比較雜亂,毫無規律性,因為相比批次大的時候,批次小的情況下無法照顧到更多的情況,所以需要小的學習率來保證不至於出錯。

可以看下圖損失Loss與學習率Lr的關係:

卷積神經網絡性能優化(提高準確率)

當然我們也可以從上圖中看出,當batchsize變大後,得到好的測試結果所能允許的lr範圍在變小,也就是說,當batchsize很小時,比較容易找打一個合適的lr達到不錯的結果,當batchsize變大後,可能需要精細地找一個合適的lr才能達到較好的結果,這也給實際的large batch分佈式訓練帶來了困難。

所以說,在顯存足夠的條件下,最好採用較大的batch-size進行訓練,找到合適的學習率後,可以加快收斂速度。另外,較大的batch-size可以避免batch normalization出現的一些小問題:

<code>https://github.com/pytorch/pytorch/issues/4534
/<code>

如何理解深度學習分佈式訓練中的large batch size與learning rate的關係?

差分學習率與遷移學習 有關遷移學習可以看這篇博客:遷移學習 Transfer Learning—通俗易懂地介紹(常見網絡模型pytorch實現)

先說下遷移學習,遷移學習是一種很常見的深度學習技巧,我們利用很多預訓練的經典模型直接去訓練我們自己的任務。雖然說領域不同,但是在學習權重的廣度方面,兩個任務之間還是有聯繫的。

卷積神經網絡性能優化(提高準確率)

由上圖,我們拿來model A訓練好的模型權重去訓練我們自己的模型權重(Model B),其中,modelA可能是ImageNet的預訓練權重,而ModelB則是我們自己想要用來識別貓和狗的預訓練權重。

那麼差分學習率和遷移學習有什麼關係呢?我們直接拿來其他任務的訓練權重,在進行optimize的時候,如何選擇適當的學習率是一個很重要的問題。

一般地,我們設計的神經網絡(如下圖)一般分為三個部分,輸入層,隱含層和輸出層,隨著層數的增加,神經網絡學習到的特徵越抽象。因此,下圖中的卷積層和全連接層的學習率也應該設置的不一樣,一般來說,卷積層設置的學習率應該更低一些,而全連接層的學習率可以適當提高。

卷積神經網絡性能優化(提高準確率)

這就是差分學習率的意思,在不同的層設置不同的學習率,可以提高神經網絡的訓練效果,具體的介紹可以查看Transfer Learning using differential learning rates。

卷積神經網絡性能優化(提高準確率)

餘弦退火(cosine annealing)和熱重啟的隨機梯度下降 餘弦就是類似於餘弦函數的曲線,退火就是下降,餘弦退火就是學習率類似餘弦函數慢慢下降。

熱重啟就是在學習的過程中,學習率慢慢下降然後突然再回彈(重啟)然後繼續慢慢下降。

兩個結合起來就是下方的學習率變化圖:

卷積神經網絡性能優化(提高準確率)

更多詳細的介紹可以查看知乎機器學習算法如何調參?這裡有一份神經網絡學習速率設置指南 以及相關論文SGDR: Stochastic Gradient Descent with Warm Restarts

多尺度訓練 多尺度訓練是一種直接有效的方法,通過輸入不同尺度的圖像數據集,因為神經網絡卷積池化的特殊性,這樣可以讓神經網絡充分地學習不同分辨率下圖像的特徵,可以提高機器學習的性能。

也可以用來處理過擬合效應,在圖像數據集不是特別充足的情況下,可以先訓練小尺寸圖像,然後增大尺寸並再次訓練相同模型,這樣的思想在Yolo-v2的論文中也提到過:

卷積神經網絡性能優化(提高準確率)

需要注意的是:多尺度訓練並不是適合所有的深度學習應用,多尺度訓練可以算是特殊的數據增強方法,在圖像大小這一塊做了調整。如果有可能最好利用可視化代碼將多尺度後的圖像近距離觀察一下,看看多尺度會對圖像的整體信息有沒有影響,如果對圖像信息有影響的話,這樣直接訓練的話會誤導算法導致得不到應有的結果。

算法集成

如果單個神經網絡不像你期待的那樣準確,那麼你可以創建一個神經網絡集成,結合多個網絡的預測能力。你可以選擇不同的神經網絡架構,在不同部分的數據集上訓練它們,然後使用它們的集合預測能力在測試集上達到較高的準確率。

假設你在構建一個貓狗分類器,0 代表貓,1 代表狗。當組合不同的貓狗分類器時,基於單個分類器之間的皮爾遜相關係數,集成算法的準確率有了提升。讓我們看一個例子,拿 3 個模型來衡量它們各自的準確率:

<code>Ground Truth: 1111111111
Classifier 1: 1111111100 = 80% accuracy
Classifier 2: 1111111100 = 80% accuracy
Classifier 3: 1011111100 = 70% accuracy
/<code>

3 個模型的皮爾遜相關係數很高。所以,集成它們並不會提升準確率。如果我們使用多數投票的方式來組合這三個模型,會得到下面的結果:

<code>Ensemble Result: 1111111100 = 80% accuracy
/<code>

正如你在上面所看到的,具有低皮爾遜相關係數的弱學習器的組合優於具有較高皮爾遜相關係數的學習器的組合。

難例
挖掘 hard-negative-mining

在任何一個深度學習任務中,我們都會遇到一些比較“棘手”的數據,這些數據相比較於其他的普通數據更難識別,這種特比容易識別錯誤的例子就稱為hard-negative。

卷積神經網絡性能優化(提高準確率)

比如Kaggle比賽中的一個識別遙感圖像中船隻的任務,使用的圖像集是從一張大的遙感圖中裁剪出來的,每張圖的大小為768*768,在簡單地對圖像進行分類時(僅僅分類圖像中有無船隻),在validation中發現最容易識別出錯的圖如下:

卷積神經網絡性能優化(提高準確率)

在觀察到這些最難辦的圖像的特徵後,我們可以針對這些難辦的圖像採取一些方法來解決這些問題。我們先用初始的正負樣本(一般是正樣本+與正樣本同規模的負樣本的一個子集)訓練分類器, 然後再用訓練出的分類器對樣本進行分類, 把其中負樣本中錯誤分類的那些樣本(hard negative)放入負樣本集合, 再繼續訓練分類器, 如此反覆, 直到達到停止條件(比如分類器性能不再提升)。也就是不停滴將困難樣本拿去訓練,讓分類器更好地學習到難以學習的特徵,簡單來說就是熟能生巧嘛。

卷積神經網絡性能優化(提高準確率)

在 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個。

相關的兩篇文章可以看一下

<code>[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.
/<code>

數據問題

缺乏數據 在使用了上述所有的技術以後,如果你的模型仍然沒有在測試集上表現得更好一些,這可能是因為缺乏數據。在很多用例中訓練數據的數量是有限的。如果你無法收集更多的數據,那麼你可以採取數據增強方法。

卷積神經網絡性能優化(提高準確率)

如果你正在使用的是圖像數據集,你可以通過剪切、翻轉、隨機裁剪等方法來增加新的圖像。這可以為你正在訓練的神經網絡提供不同的樣本。

數據集損壞 數據集的好壞是算法泛化好壞的一個非常重要的前提條件,我們通常在構建深度學習的任務中,所得到的數據集一般不會是非常完美的(不論是自己搭建還是利用他人的數據,在數據集量過大的時候,數據集中難免會有圖像損壞或者錯誤的個例)。如果有損壞的圖像,如果我們不知情,一般來說,在我們使用代碼讀取的時候就會報錯,舉個例子:

<code>raise IOError("image file is truncated)
/<code>

在Kaggle的一個比賽中就存在這樣的情況,訓練的數據中有10w+的圖像數據,但是存在10餘張的圖像內容缺失(圖像大小明顯小於其他正常圖像)或者直接被損壞無法讀取。這個時候就需要我們自己去手動編寫代碼將那些錯誤且無法參與訓練的圖像挑選出來。

卷積神經網絡性能優化(提高準確率)

那麼如果正確過濾這些圖像呢?

  • 找到損壞圖像的特點,例如無法讀取,編寫程序去除無法讀取的圖像
  • 找到內容缺失的圖像,這樣的圖像大小往往比普通圖像小一些,通過過濾文件大小小於某一閾值去除

當然,數據集損壞的形式還有很多,需要我們自己去發掘。在一開始得到數據集的時候最好不要直接開始訓練,應該去仔細檢查自己的數據集是否有問題,這樣可以避免很多之後訓練時需要的處理的麻煩。

Cross Validation 交叉驗證

在李航的統計學方法中說到,交叉驗證往往是對實際應用中數據不充足而採用的,基本目的就是重複使用數據。在平常中我們將所有的數據分為訓練集和驗證集就已經是簡單的交叉驗證了,可以稱為1折交叉驗證。注意,交叉驗證和測試集沒關係,測試集是用來衡量我們的算法標準的,不參與到交叉驗證中來。

交叉驗證只針對訓練集和驗證集。

交叉驗證是Kaggle比賽中特別推崇的一種技巧,我們經常使用的是5-折(5-fold)交叉驗證,將訓練集分成5份,隨機挑一份做驗證集其餘為訓練集,循環5次,這種比較常見計算量也不是很大。還有一種叫做leave-one-out cross validation留一交叉驗證,這種交叉驗證就是n-折交叉,n表示數據集的容量,這種方法只適合數據量比較小的情況,計算量非常大的情況很少用到這種方法。

吳恩達有一節課The nuts and bolts of building applications using deep learning中也提到了。

卷積神經網絡性能優化(提高準確率)

數據增強 數據集增強是一個老生常談的話題了,我們為什麼需要那麼多數據?為什麼需要數據增強技術? 可以看這篇文章來了解一下:深度學習為什麼需要那麼多的數據?

這裡只簡單說下我們常用的數據增強的Transform。大部分我們使用的圖像增強技術一般是隨機旋轉,水平翻轉,高斯模糊和尺度變化還有什麼拉伸等blabla的操作。這些圖像變化對大部分的任務是比較適合的,但針對特定的任務,存在某一簇特殊的圖像增強技術可以達到比普通圖像增強技術更好的效果。例如夜視圖或者光照:

卷積神經網絡性能優化(提高準確率)

但也需要提個醒,並不是所有的圖像增強都可以提升模型的泛化能力。

而且有些圖像增強技術會對原始圖像造成損失從而導致神經網絡學習到錯誤的信息,這點是我們比較容易忽視的問題,同樣重要,相關內容可以查看fastai中的圖像增強技術為什麼相對比較好。

TTA(Test Time Augmentation) 最初這個概念是在fastai課程中看到的,這個過程在訓練階段不會參與,是通過在驗證和測試階段進行的。具體過程是,對所要處理的圖像進行幾種隨機的圖像增強變化,然後對每種圖像增強後的圖像進行預測,對預測結果取平均值。

原理類似於模型平均,犧牲推斷速度來實現推斷精度的提升。

卷積神經網絡性能優化(提高準確率)

當然,這個技術也有好有壞,在我自己跑的衛星圖數據集中採用TTA的精確度比不採用低了0.03個百分點。

訓練神經網絡真的很像煉丹,而我們所有使用的技巧tricks,也只是增加一些煉丹的成功率,而究竟煉丹能不能成功,最終還是要取決於我們設計的算法合不合理。


卷積神經網絡性能優化(提高準確率)


分享到:


相關文章: