好用的深度學習CNN預訓練模型框架總整理: 從AlexNet到EfficientNet(ML 隨筆)

KevinLuo
19 min readFeb 16, 2022

--

各位好,我是Kevin. 忽然發現頗久沒有更新我的medium...可能都快長蜘蛛網了(驚!

所以最近推出了一個新概念…就是…隨筆!!意思就是該篇文章幾乎是想到甚麼寫什麼…然後也不一定會有一個good end,可能會斷在某個奇怪的地方:),就是我暫時想不出來怎麼寫…未來某一天我會再把它補完。

Anyway ,因為前陣子比較忙,在面試一些公司,有些公司要到好幾面…(汗

其中我發現,有好幾家公司會問有關CNN深度學習-預訓練模型框架的問題。

當然還有另外一些很常被問到的題型,我之後有時間再寫文章提出。

這一篇主要是想整理自己對預訓練CNN模型框架的理解,和梳理一些原則和想法,除了對我自己有複習作用之外也幫讀者做一個小整理。

在深度學習上,竟有如此快速的進展在這約8~9年間!

倒回至2012年,AlexNet以第一名的成績: scored 63.3% 的準確率(Accuracy)拿下了ImageNet圖片分類競賽的第一名。

現在,有絕大多數的人都在使用名為"EfficientNet"的架構做teacher-student training.

‎如果我們繪製出所有在imagenet上作品的準確性報告,會得到以下的結果:

Source: Papers with Code — Imagenet Benchmark

在本文中,我們將重點於介紹卷積神經網路(CNN)架構的演變。我們將重點介紹基本原則,而不是報告簡單的數據。為了提供另一個視覺概述,可以在單個圖像中獲得2018年之前性能最佳的CNN框架:‎‎

Overview of architectures until 2018. Source: Simone Bianco et al. 2018

‎請注意,X軸的(G-‎‎FLOPs‎‎) 表示模型的複雜性,而在y-axis垂直軸上,我們具有 Imagenet 準確度。圓的半徑表示參數的大小。

‎從上圖中可以明顯看出,‎‎擁有較多的參數並不見得總是能帶來更好的準確性‎‎。我們將嘗試概括對CNN更廣泛的視角,看看這是為什麼。‎

這邊推薦一門Andrew Ng 的一門CNN課程。:Convolutional Neural Networks | Coursera 有解釋到此的概念。

術語介紹:

首先,我們必須定義一些術語:

  • ‎更寬的‎‎(wider)網路意味著卷積層中有更多的特徵映射機制(過濾器filters)‎
  • ‎更深層次(deeper)‎‎的網路意味著更多的卷積層‎
  • ‎具有‎‎更高解析度的網路(higher resolution)‎‎意味著它處理具有較大寬度和深度(空間解析度)的輸入圖像。這樣,生成的要素地圖將具有更高的空間維度。‎
Architecture scaling. Source: Mingxing Tan, Quoc V. Le 2019

‎架構工程就是關於‎‎scaling‎‎。我們將徹底使用這些術語,因此在繼續之前請務必了解它們。‎

AlexNet: ImageNet Classification with Deep Convolutional Neural Networks (2012)

‎Alexnet [1] 由 5 個 conv 層組成,從 11x11 內核開始。它是第一個採用‎‎最大池層‎‎、ReLu 啟動函數和 3 個巨大線性層的 dropout 架構。該網路用於具有1000個類別的圖像分類任務,這在當時是非常state-of-the-art的。現在,我們可以在 35 行 ‎‎PyTorch‎‎ 代碼中實現它:‎以下分享我的colab(我不喜歡在medium上面打code,會有些縮排問題)

https://colab.research.google.com/drive/1hHgYb-_6o3lb_v6j8e5w1CF0cu_dowYa?usp=sharing

‎這是第一個在‎‎Imagenet‎‎上成功訓練的捲積模型,當時,在CUDA中實現這樣的模型要困難得多。Dropout 在線性變換中被大量使用,以用來避免過度擬合。在2015–2016年auto-differentiation出現之前,在GPU上‎‎實現反向傳播‎‎需要幾個月的時間。‎

VGG (2014)

非常有名的論文"Very Deep Convolutional Networks for Large-Scale Image Recognition”將deep這一詞的概念以傳染病般傳播開來。

這是第一項深度疊層研究,裡面數據說明只需添加更多層即可提高性能,由於是第一篇deep layers研究,所以也並沒有此一論述的反駁。

所以這一假設在當時是成立的,他們使用3*3的內核,而不適AlexNet。該架構使用224*224pixel 的RGB圖像進行練習。

主要原理是疊三層的 3*3 convolutional layers 類似於單層的 7*7 layer.(Note:VGG核心之一 -> 疊三層3x3好過於一層7x7)

而結果甚至更好!因為中間有利用三個非線性激活層,讓整個function更具有鑑別度。

再者,這樣的設計減低了途中訓練的參數。

具體來說,您需要3∗(3²)C²=27×個權重(Weights), 相比於7*7 conv. 層需要7*7C² = 49 C² 來說還要小。(81% more)

所以總的來說,減低conv layer中kernel size的大小然後疊更多層的performence會好於只有單層而且kernel size很大的performance。

直觀地說,它可以被視為對‎‎‎7×7‎轉化濾鏡,收縮它們以具有3x3非線性分解。‎

最後,這也是讓normalization成為一大議題的開端架構。

儘管如此,pretrained 的 VGGs 網路依然用在 feature matching loss在GANs中,和網路風格轉換( style transfer)還有特徵視覺化(feature visualizations)。

以下影片是應用VGG網路在真實世界任務的有趣例子:

VGG16 Neural Network Visualization — YouTube

‎最後,在Alexnet旁邊進行視覺化比較:‎

http://cs231n.stanford.edu/slides/2017/

InceptionNet/GoogleNet (2014)

‎在VGG之後,Christian Szegedy等人的論文”Going Deep with Convolutions”是一個巨大的突破。‎

‎動機‎‎:增加深度(層數)並不是使模型變大的唯一方法。增加‎‎網路的深度‎‎和寬度,同時保持計算在恆定水平,如何?‎

‎InceptionNet靈感來自人類的視覺系統,其中資訊在多個尺度上被處理,然後在本地聚合。如何在沒有記憶體爆炸的情況下實現這一目標?‎

‎答案是‎‎ ‎1×1‎卷積!主要目的是通過減少每個捲積塊的輸出通道來減小尺寸。然後,我們可以處理具有不同內核大小的輸入。只要輸出是填充的,它就是與輸入中的相同。‎

為了找到適合的padding在單個步伐且無dilation, padding p 和 kernel k 被定義為 out = in (input 和 output 空間維度):

在out = in 的條件下 。就意味著 out=in+2∗pk+1,等同於p=(k-1)/2.

在Keras中,可以簡單的設定超參數 padding=”same”.

通過這種方式,我們可以連接與不同內核卷積的功能。

然後我們需要以 1×1‎捲積層將特徵「投影」到更少的通道,以贏得計算能力。有了這些額外的資源,我們便可以添加更多的層。實際上,‎‎‎1×1‎convs的工作方式類似於低維嵌入。‎

以下影片為Andrew Ng解釋 1X1 Convolutions:

Neural Networks — Networks in Networks and 1x1 Convolutions — YouTube

下個小結論: 1X1的convolution kernel的兩大功能 → 1.做更多的非線性轉換,2.縮小輸入的通道數, 也就是所小記憶體的計算量!

加入了1X1的卷積概念後就不只是造就了增加網路深度的InceptionNet,還造就了運用InceptionNet模組再進行寬度增大後的GoogleNet.

此核心區塊被稱為 inception module, 看起來就像下面的圖所示:

Szegedy et al. 2015. Source

整個架構被稱為GoogLeNet或InceptionNet。‎從本質上講,作者聲稱他們試圖接近具有正常密集層的稀疏卷積網路(如圖所示)。‎

‎為什麼?因為他們相信只有少數神經元是有效的。這符合‎ Hebbian principle‎‎:「一起發射的神經元,最後也連接在一起,那些才是有效的神經元計算」。‎

此外‎‎它使用不同內核大小的卷積(‎‎5×5‎,‎‎‎3×3‎,‎‎‎1×1‎) 以捕獲多個比例下的細節‎.

通常,對於全域駐留(resides globally)的資訊,較大的內核是首選,對於本地分散式的資訊,較小的內核是首選的。

‎InceptionNet/GoogLeNet架構由9個堆疊在一起的inception模組組成,兩者之間有最大池化層(Maxpooling)=>(將空間維度減半)。它由22層組成(包含池化層為27層)。它在最後一個 inception 模組之後使用全域平均池層(global average pooling)。‎

以下寫了一個非常簡單的 Inception block implementation:

‎您可以‎‎在此處‎‎找到上述code的Google colab。‎

當然,您可以在啟動函數‎‎之前‎‎添加‎‎歸一化‎‎層(Normalization layer)。但是由於歸一化技術還沒有很好的建立,作者引入了兩個輔助分類器。原因是:‎‎梯度消失問題‎‎。‎

Inception V2, V3 (2015)

後來,在論文「Rethinking the Inception Architecture for Computer Vision」中,作者根據以下原則改進了 Inception 模型:‎

  • ‎將 5x5 和 7x7(在 InceptionV3 中)卷積分別分解為兩個和三個 3x3 順序卷積。這提高了計算速度。這與 VGG 的原理相同(幫大家回想一下… 降低kernel size,增加層數可以導致performence變好,乃VGG之核心概念之一(請牢記此點)。
  • 他們使用spatially separable卷積。簡單地說,一個 3x3 內核被分解成兩個較小的內核:一個 1x3 和一個 3x1 內核,且它們是按此順序應用的。‎
  • Inception module變得更寬。
  • ‎他們試圖在網路的深度和寬度之間以平衡的方式分配計算預算。
  • 他們增加了 batch normalization這個重要的概念.

之後的版本為 InceptionV4Inception-Resnet

ResNet: Deep Residual Learning for Image Recognition (2015)

‎之前所提到的一個問題,如梯度消失,都通過兩個技巧得到解決:‎

  1. batch normalization

2. short skip connections

H‎‎(‎‎x‎)=‎F‎‎(‎‎x‎), 我們要求模型學習差異(又名殘差)‎‎H’(x) = F(x) + x,這意味著‎‎H(x) — x = F(x)將是殘餘部分‎。

Source: Standford 2017 Deep Learning Lectures: CNN architectures

‎有了這個簡單但有效的block,作者設計了更深層次的架構,範圍從18(Resnet-18)到150(Resnet-150)層。‎

‎對於最深的模型,他們採用了1x1卷積,如下右圖所示:‎

Image by Kaiming He et al. 2015. Source:Deep Residual Learning for Image Recognition

‎總之,下面是整個架構的概念圖:‎

Animated GIF — Find & Share on GIPHY

有關更多詳細資訊,您可以觀看來自Henry AI Labs on ResNets:

ResNet Explained! — YouTube

我們可以通過直接從torchvision導入一堆ResNet來try他們:

import torchvisionpretrained = True# A lot of choices :Pmodel = torchvision.models.resnet18(pretrained)model = torchvision.models.resnet34(pretrained)model = torchvision.models.resnet50(pretrained)model = torchvision.models.resnet101(pretrained)model = torchvision.models.resnet152(pretrained)model = torchvision.models.wide_resnet50_2(pretrained)model = torchvision.models.wide_resnet101_2(pretrained)‎#‎試試吧!‎

DenseNet: Densely Connected Convolutional Networks (2017)

‎忽略連接是一個非常酷的想法。我們為什麼不直接跳過連接所有內容呢?‎

‎Densenet是將這個想法推向極端的一個例子。當然,與ResNets的主要區別在於,我們將連接而不是添加feature maps。‎

‎因此,其背後的核心思想是‎‎特徵重用‎‎,這導致了非常緊湊的模型。因此,它需要的參數‎‎比其他CNN少‎‎,因為沒有重複的特徵圖。

‎好吧,為什麼不呢?嗯……這裡有兩個問題:‎

  1. feature maps必須是相同的尺寸
  2. 與所有先前feature maps的串聯可能會導致記憶體爆炸‎

‎為了解決第一個問題,我們有兩種解決方案:‎

a)用 conv layer 搭配 padding超參數來保持空間維度或是

b)‎僅在Dense block內‎‎使用‎‎Dense‎‎跳過連接。 ‎

‎範例如下所示:‎

Image by author. The Dense block is taken from Gao Huang et al. Source: Densenet

Transition Layer可以使用平均池化對圖像尺寸進行下採樣(down sampleing)。‎

‎為了解決第二個問題,即記憶體爆炸,feature map通過1x1 的convs減少計算量(有點壓縮)。請注意,在圖中使用了 K,但 densenet 使用了‎‎K=featmaps/2

‎此外,當不使用數據增強(Data Augmentation)時,它們在每個捲積層之後添加一個 p=0.2 的Dropout layer。‎

Growth rate:

‎更重要的是,還有另一個參數可以控制整個體系結構的feature maps數量。即為‎‎增長率‎‎。它指定每個超密集convolution layer的輸出要素。鑒於k0​‎初始特徵圖和‎k‎增長率,可以計算出每層輸入特徵圖的數量‎l‎如‎‎k0 + k * (l − 1)‎‎.在框架中,數字 k 是 4 的倍數,稱為bottleneck size (bn_size)。‎

‎最後,我在這裡引用了‎‎DenseNet‎‎在torchvision中最重要的論點作為總結:‎

import torchvisionmodel = torchvision.models.DenseNet(growth_rate = 16, # how many filters to add each layer (`k` in paper)block_config = (6, 12, 24, 16), # how many layers in each pooling blocknum_init_features = 16, # the number of filters to learn in the first convolution layer (k0)bn_size= 4, # multiplicative factor for number of bottleneck (1x1 cons) layersdrop_rate = 0, # dropout rate after each dense conv layernum_classes = 30 # number of classification classes)print(model) # see snapshot below

‎在“dense”layer(快照中的密集層5和6)內有一個bottleneck(1x1)層,它將channels數減少至‎ bn_size*growth_rate=64。‎否則,輸入通道的數量將會爆炸式的增長。如下圖所示,每層添加‎‎ 16=growth_rate‎ channels。‎

即使DenseNet一開始被提倡用來做圖像分類的任務,但它卻已經因為其特徵功能重複性使用的關鍵功能,而使用於各個領域上。下面的Pie diagram為DenseNet的使用領域分布圖,來自DenseNet的paper with code

Big Transfer (BiT): General Visual Representation Learning (2020)

‎儘管已經提出了ResNet的許多變體,但最新和最著名的是BiT。Big Transfer(BiT)是一種可擴展的基於ResNet的模型,用於有效的圖像預訓練。

‎作者他們開發了3種基於ResNet152的BiT模型(小型,中型和大型)。對於BiT的重大改變,他們使用了ResNet152x4,這意味著每層的通道(channels)是其4倍。他們在比imagenet還要更大很多的數據集中預先訓練了該模型一次。最大的模型是在瘋狂大型的JFT數據集上訓練的,該數據集由3億張->三百個百萬(300M)標記圖像組成。‎

架構中的主要貢獻是Normalization layer的選擇。為此,作者將批次處理歸一化(BN)替換為‎‎組歸一化‎‎(GN)和‎‎權重標準化‎‎(WS)。‎

Image by Lucas Beyer and Alexander Kolesnikov. Source

‎為什麼?因為第一個BN的參數(均值和方差)需要在預訓練和轉移之間進行調整。另一方面,GN 不依賴於任何參數狀態。另一個原因是BN使用批處理級統計資訊,這對於像TPU這樣設備中的分散式訓練變得不可靠。分佈在 500 個 TPU 上的 4K 批意味著每個工作線程 8 個批次,這並不能很好地估計統計數據。通過將規範化技術更改為 GN+WS,可以避免在工作線程之間進行同步。‎

‎顯然,擴展到更大的數據集與模型大小密切相關。

Performance with more and and multiple models. Source: Alexander Kolesnikov et al. 2020

‎在此圖中,說明瞭與數據並行擴展體系結構的重要性。ILSVER是具有100萬張圖像的Imagenet數據集,ImageNet-21K擁有大約1400萬張圖像,JFT則有 300M張!‎‎

最後,這種大型預訓練模型可以微調到應用在很小的數據集上,並且也可實現其非常好的性能。

Performance of BiT models with limited data for fine tuning. Source: Alexander Kolesnikov et al. 2020

EfficientNet: Rethinking Model Scaling for Convolutional Neural Networks (2019)

‎EfficientNet是關於engineering和scale的。它證明,如果您仔細設計架構,則可以通過合理的參數獲得最佳結果。‎

Image by Mingxing Tan and Quoc V. Le 2020. Source: EfficientNet: Rethinking Model Scaling for Convolutional Neural Networks

上圖展示了 ImageNet Accuracy VS model parameters.(非常屌的是EfficientNet-B1 計算上小ResNet-152 7.6倍 然後又比ResNet-152快5.7倍)

Individual upscaling

  • ‎使用‎‎更多的圖層‎‎(深度),可以捕獲更豐富,更複雜的特徵,但此類模型很難訓練(由於漸變消失)‎
  • ‎更廣泛的網路‎‎更容易訓練。它們往往能夠捕獲更細粒度的特徵,但很快就會飽和。‎

建議從一個相對較小的baseline模型F開始。‎‎並逐漸擴展它。

為了進一步限制設計空間,作者將所有層限制為具有恆定比率的均勻縮放。這樣一來,我們就有了一個更易於處理的優化問題。最後,也必須想到我們infrastructure的最大記憶體和FLOPs數量。‎‎下圖很好地示範了這一點:‎

Image by Mingxing Tan and Quoc V. Le 2020. Source: EfficientNet: Rethinking Model Scaling for Convolutional Neural Networks

‎w是寬度,‎d為‎深度,以及‎r為‎解析度比例因數。通過縮放其中一個,其中只有一個將在一點上飽和。我們能做得更好嗎?‎

Compound scaling

暫時斷在此…

Sign up to discover human stories that deepen your understanding of the world.

--

--

No responses yet

Write a response