想入門設計卷積神經網路?這是一份綜合設計指南
來自專欄 機器之心
選自hackernoon,作者:George Seif,機器之心編譯。
這篇文章可以作為一個設計指南,為特定分類任務的 CNN 設計提供指導。作者圍繞準確率、速度、內存消耗三個指標的權衡,從網路類型、架構設計、數據處理和遷移學習等方面介紹了 CNN 設計過程中使用的方法。
你想開始做圖像分類,但是無從著手。應該使用哪個預訓練網路?如何修改網路以使其滿足需求?你的網路應該包含 20 層還是 100 層?哪些是最快的、最準確的?這些是你為圖像分類選擇最好的 CNN 時會遇到的眾多問題。
當選擇 CNN 來進行圖像分類時,有 3 個非常主要的指標需要去優化:準確率、速度和內存消耗。在這些指標上的性能取決於你所選擇的 CNN 以及對它所做的任何修改。不同的網路(如 VGG、Inception 以及 ResNet 等)在這些指標上有不同的權衡。此外,你還可以修改這些網路結構,例如通過削減某些層、增加某些層、在網路內部使用擴張卷積,或者不同的網路訓練技巧。
這篇文章可以作為一個設計指南,為特定的分類任務的 CNN 設計提供指導。尤其是,我們會聚焦在 3 個主要指標上:準確率、速度和內存消耗。我們會研究很多不同的分類 CNN,並探索它們在這 3 個指標方面對應的屬性。我們還會研究對這些基本 CNN 可能做出的修改,以及這些修改會怎樣影響這些指標。最後,我們會研究如何為特定圖像分類任務最優地設計 CNN。
網路類型
在網路類型和這 3 個指標上有著明確的權衡。首先,你肯定會希望使用 Inception 或者 ResNet 類型的設計。它們比 VGGNet 和 AlexNet 更新,而且在速度和準確率之間提供了更好選擇的權衡(正如你在上圖中看到的)。斯坦福大學的 Justin Johnson 對其中的一部分做了很棒的基準測試(https://github.com/jcjohnson/cnn-benchmarks)。
Inception 和 ResNet 的選擇確實是速度和準確率的權衡:要準確率,用超深層的 ResNet;要速度,用 Inception。
使用巧妙的卷積設計來減少運行時間和內存消耗
對 CNN 一般設計的最新進展已經提出了一些非常棒的可選擇方法,它們能夠在沒有太多的準確率損失的情況下加速 CNN 的運行,並減少內存消耗。所有的這些方法都可以很容易地集成在上述的任何一類卷積神經網路中。
- MobileNets(https://arxiv.org/pdf/1801.04381.pdf)使用深度分離的卷積來極大地減少運算和內存的消耗,同時僅犧牲 1% 到 5% 的準確率,準確率的犧牲程度取決於你想要獲得的計算節約。
- XNOR-Net(https://arxiv.org/pdf/1603.05279.pdf)使用二進位卷積,也就是說,卷積運算只涉及兩個可能的數值:0 或者 1。通過這種設計,網路可以具有較高程度的稀疏性,易於被壓縮而不消耗太多內存。
- ShuffleNet(https://arxiv.org/pdf/1707.01083.pdf)使用點組卷積和通道隨機化來極大地減少計算代價,同時還能維持比 MobileNets 高的準確率。事實上,它們可以在超過 10 倍的運算速度下達到早期最先進的分類 CNN 的準確率。
- Network Pruning(https://arxiv.org/pdf/1605.06431.pdf)是為了減少運行時間和內存消耗而刪除 CNN 的部分權重的技術,而且有希望不降低準確率。為了保持準確率,被刪除的部分應該對最終結果沒有大的影響。鏈接中的論文展示了使用 ResNets 可以輕易地做到這一點。
網路深度
這個比較容易:通常增加更多地層會提升準確率,同時會犧牲一些速度和內存。然而,我們已經意識到的是這種權衡受制於邊際效應,也就是說,我們增加的層越多,通過增加每一層而帶來的準確率提升將越少。
激活函數
關於激活函數,最近有很多爭議。然而,很好的一個經驗法則就是從 ReLU 開始。使用 ReLU 通常會在開始的時立即得到一些好的結果。不像 ELU、PReLU 或者 LeakyReLU 一樣還需要一些繁瑣的調整。當你確定你的設計使用 ReLU 能夠達到不錯的效果,那你就可以調整其它的部分,並調整它們的參數,以嘗試對準確率做最後的提升。
卷積核大小
你也許認為使用更大的卷積核總會導致最高的準確率,同時還會損失速度和內存。然而,情況並不總是如此,因為研究中多次發現使用較大的卷積核會使得網路難以發散。使用更小的核(例如 3×3)會更好一些。ResNet 和 VGGNet 都相當全面的詮釋了這一點。正如這兩篇論文所展示的,你也可以使用 1×1 的核來減少特徵的數目。
空洞卷積
為了能夠使用遠離中心的像素,空洞卷積(Dilated Convolution)在卷積核的權重之間使用空格。這使得網路不用增加參數數目就能夠指數級地擴展感受野,也就是說根本沒有增加內存消耗。已經證明,空洞卷積可以在微小的速度權衡下就能增加網路準確率。
數據增強
你應該經常做數據增強。使用更多的數據已經被證明能夠持續地增強性能,甚至達到極限(https://arxiv.org/pdf/1707.02968.pdf)。使用數據增強,你可以免費獲得更多數據。增強類型取決於你的應用。比如,如果你做的是無人車的應用,你可能會遇到路上的車、樹以及建築物,所以,將你的圖像垂直翻轉是沒有意義的。然而,你一定會遇到由於天氣變化或者場景變化而引起的光線改變,通過改變光線和水平翻轉來增強數據是有意義的。可以看一下這個數據增強庫(https://github.com/aleju/imgaug)
訓練優化器
當你最終要訓練網路的時候,有幾種可以選擇的優化演算法。很多人說 SGD 在準確率方面會得到最好的結果,在我的經驗看來,這是正確的。然而,調整學習率設置和參數是枯燥的,也是具有挑戰性的。另一方面,雖然使用自適應的學習率(例如 Adam,、Adagrad 或者 Adadelta)比較容易,也比較快速,但是你可能得不到和 SGD 一樣的最優準確率。
最好就是讓優化器遵循和激活函數一樣的「風格」:先使用最容易的,看看它是否奏效,然後使用更複雜的來調節和優化。我個人推薦以 Adam 作為開始,因為根據我的經驗,它最容易使用:設置一個不太高的學習率,一般默認 0.0001,然後你通常會得到一些非常好的結果。隨後你可以從零開始使用 SGD,或者甚至以 Adam 作為開始,然後使用 SGD 精調。事實上,這篇文章發現使用 Adam,中間換到 SGD,能夠以最容易的方式達到最好的準確率。看一下論文中的這張圖:
類別均衡
很多情況下你會遇到不均衡數據,尤其是在現實應用中。舉一個現實中的簡單例子:由於安檢原因,你在訓練深度網路來預測輸入視頻中的某人是否持有殺傷性武器。但是在你的訓練數據中,你只有 50 個視頻中的人持有武器,而 1000 個視頻中的人是沒有持有武器的!如果你立即使用這些數據訓練你的網路,你的模型一定會以很高的偏差偏向於預測某人未持有武器。
可以用以下的方法來解決類別不均衡問題:
- 在損失函數中使用類別權重。本質上,樣本數量不足的類別在損失函數中接受較高的權重,這樣的話特定類別的誤分類會在損失函數中導致較高的誤差。
- 過採樣:對訓練樣本中數量不足的類別進行重複採樣,這樣有助於樣本分布的均衡化。當可用數據較少的時候這個方法最能奏效。
- 降採樣:你也可以簡單地跳過包含過多樣本的類別中的一些訓練樣本。當可用數據非常多的時候,這個方法最奏效。
- 數據增強:對少數類別的數據進行數據擴增。
優化你的遷移學習
對大多數應用而言,使用遷移學習要比從零開始訓練網路更加合適。然而,需要選擇的是:你要捨棄哪些層,保留哪些層。這非常依賴於你的數據。你的數據和預訓練網路(通常是在 ImageNet 上訓練)所用的數據越相似,你需要重新訓練的層就越少,反之亦然。例如,假設你要訓練網路來區分一張圖片是否包含葡萄,所以你會有大量的包含葡萄和不包含葡萄的圖像。這些圖像和 ImageNet 中使用的圖像相當相似,所以你僅僅需要重新訓練最後幾層,或許只需要重新訓練全連接層。然而,倘若你要分類的是一幅外太空的圖像是否包含一顆行星能夠,這種數據和 ImageNet 中的數據大有不同,所以你還需要重新訓練後邊的卷積層。簡而言之,應該遵循以下的原則:
總結
本文給出了用於圖像分類應用而設計 CNN 的全面指南。希望你能夠愉快地閱讀本文,並學到一些新的、有用的東西。
原文鏈接:https://hackernoon.com/a-comprehensive-design-guide-for-image-classification-cnns-46091260fb92
推薦閱讀: