Batch Normalization應該放在ReLU非線性激活層的前面還是後面?

2021-02-20 小白學視覺

點擊上方「小白學視覺」,選擇加"星標"或「置頂

重磅乾貨,第一時間送達


編輯:CVDaily  轉載自:計算機視覺Daily

https://www.zhihu.com/question/283715823

本文僅作為學術分享,如果侵權,會刪文處理

BN 放在ReLU的前面還是後面?這個問題是AI面試的高頻題

Batch-normalized 應該放在非線性激活層的前面還是後面?

我看網上的中文資料基本都是說,將BN 層放在非線性激活層的前面,但是

在 Deep Learning for Computer Vision with Python 中,有以下討論,

作者:論智
https://www.zhihu.com/question/283715823/answer/438882036

在BN的原始論文中,BN是放在非線性激活層前面的(arXiv:1502.03167v3,第5頁)

We add the BN transform immediately before the nonlinearity

(注意:before的黑體是我加的,為了突出重點)

但是,François Chollet爆料說BN論文的作者之一Christian把BN放在ReLU後面(你的問題裡引用的文字也提到了這一段)。

I can guarantee that recent code written by Christian applies relu before BN.

另外,Jeremy Howard直接主張把BN放在非線性激活後面

You want the batchnorm after the non-linearity, and before the dropout.

「應該」放在前面還是後面?這個「應該」其實有兩種解釋:

放在前面還是後面比較好?

為什麼要放在前面還是後面?

對於第一問,目前在實踐上,傾向於把BN放在ReLU後面。也有評測表明BN放ReLU後面效果更好。

對於第二問,實際上,我們目前對BN的機制仍然不是特別清楚,這裡只能嘗試做些(玄學)解釋,不一定正確。

BN,也就是Batch-Normalization,這名字就能讓我們想到普通的normalization(歸一化),也就是將輸入傳給神經網絡之前對輸入做的normalization。這個normalization是對輸入操作的,是在輸入層之前進行的。那麼,從這個角度上來說,Batch-Normalization可以視作對傳給隱藏層的輸入的normalization。想像一下,如果我們把網絡中的某一個隱藏層前面的網絡層全部砍掉,那麼這個隱藏層就變成了輸入層,傳給它的輸入需要normalization,就在這一層之間,這個位置,就是原本的BN層的位置。從這方面來說,BN層放非線性激活之後,是很自然的。

然後,我們再來考慮一些具體的激活函數。我們看到,無論是tanh

還是sigmoid

函數圖像的兩端,相對於x的變化,y的變化都很小(這其實很正常,畢竟tanh就是拉伸過的sigmoid)。也就是說,容易出現梯度衰減的問題。那麼,如果在tanh或sigmoid之前,進行一些normalization處理,就可以緩解梯度衰減的問題。我想這可能也是最初的BN論文選擇把BN層放在非線性激活之前的原因。

但是ReLU的畫風和它們完全不一樣啊。

實際上,最初的BN論文雖然也在使用ReLU的Inception上進行了試驗,但首先研究的是sigmoid激活。因此,試驗ReLU的,我猜想作者可能就順便延續了之前把BN放前面的配置,而沒有單獨針對ReLU進行處理。

總結一下,BN層的作用機制也許是通過平滑隱藏層輸入的分布,幫助隨機梯度下降的進行,緩解隨機梯度下降權重更新對後續層的負面影響。因此,實際上,無論是放非線性激活之前,還是之後,也許都能發揮這個作用。只不過,取決於具體激活函數的不同,效果也許有一點差別(比如,對sigmoid和tanh而言,放非線性激活之前,也許順便還能緩解sigmoid/tanh的梯度衰減問題,而對ReLU而言,這個平滑作用經ReLU「扭曲」之後也許有所衰弱)。



作者:王超鋒
https://www.zhihu.com/question/283715823/answer/444230597


個人理解上和@論智差不多一致

實驗上,放後面更有效。為什麼放後面有效,談一下我自己的理解。例如,這裡兩層卷積:

1、before, conv1-bn1-ReLU1-conv2-bn2-ReLU2

2、after,conv1-ReLU1-bn1-conv2-ReLU2-bn2

BN與常用的數據歸一化最大的區別就是有α和β兩個參數,這兩個參數主要作用是在加速收斂和表徵破壞之間做的trade off。在初期數據歸一化比較明顯,所以網絡可以迅速收斂。至於為什麼數據歸一化可以加速收斂,這篇博客解釋的不錯,可以參考下,Batch Normalization詳解。隨著訓練來到中後期這兩個參數學習到差不多的時候,主要是用來恢復上一層輸入分布。

所以這麼去理解,上面的兩個結構的斜線加粗部分。1和2中都相當於作conv2的輸入做了歸一化,從conv2的看來,其輸入都是ReLU1之後的數據,但區別在於1中ReLU1截斷了部分bn1歸一化以後的數據,所以很有可能歸一化的數據已經不再完全滿足0均值和單位方差,而2中ReLU1之後的數據做了歸一化,歸一化後仍滿足0均值和單位方差。所以放後邊更有效也是可以理解的。

以上純屬個人理解,其實可以做這麼個實驗,在1結構的中在加一個BN,conv1-bn1-ReLU1-bn-conv2-bn2-ReLU2,把截斷後的數據在做個歸一化,這樣和原始的1比較下看看是否更有效。如果有的話,說明conv2更喜歡0均值和單位方差的分布~,不過我也沒試過。不知道會不會被打臉( ̄ε(# ̄)☆╰╮( ̄▽ ̄///)



作者:王藝程
https://www.zhihu.com/question/283715823/answer/443733242


在我所見過的所有包含BN的網絡結構中,BN都是在ReLU之前的。下面給出一種解釋

為了方便大家理解,先介紹一下我們在CVPR2018發表的論文《Person Re-identification with Cascaded Pairwise Convolutions》中提出的一種簡單的層:Channel Scaling (CS, 通道放縮層)。CS層將每一輸入通道乘以一恆正因子後作為輸出。在CS層存在於卷積層後,ReLU層前時,我們認為CS層可以在網絡訓練過程中引導卷積權值取正,進而緩解零梯度問題。具體的解釋除了看論文,還可以看下圖。

BN也可以解決零梯度問題,有兩條途徑,下面直觀地定性講講:

當對於絕大部分輸入特徵圖,filter絕大部分響應值為負時,會產生零梯度問題,在卷積層後加入BN層後,BN層中該filter對應通道的均值為負,BN中的減均值處理會使得相當一部分響應值變為正,進而解決了零梯度問題。(這段討論忽略了BN中的bias項和scaling項)

BN中的scaling項初始化為1,在訓練過程中一般取值為正,因此可通過類似CS的途徑來緩解零梯度問題;其實,如果scaling項一直取值為負,也可通過類似CS的途徑來緩解零梯度問題。(這段討論中忽略了BN中的normalization計算)

前述兩條途徑均存在缺陷,使得帶BN的網絡的訓練不穩定(至少在我們的實驗中是這樣):

BN中的均值和方差不是通過隨機梯度下降法訓練的,而是逐Batch統計並滑動平均,受不同Batch中樣本情況差異的影響大,在訓練過程中可能出現較大波動或改變,進而影響網絡功能。

訓練過程中,BN層中scaling項的取值有可能由正變負或者由負變正,這種情況翻轉了對應通道的含義,可能對網絡功能造成損害;此外,如果scaling項時而取正時而取負,無法實現類似CS的功能。

---
【補充】上面提到的我們的那篇論文存在靠不合理評測方式提升分數的問題,並且第三個貢獻——Sample Rate Leaning策略的優勢在調整網絡結構後難以體現。至少根據現有實驗,我覺得CS的效果比較明顯,並且有很合理的理論解釋。

作者:star all
https://www.zhihu.com/question/283715823/answer/700870267

和一位答友類似,我見過的很多網絡也是都把bn放到激活前面。我做一下解釋:

現在我們假設所有的激活都是relu,也就是使得負半區的卷積值被抑制,正半區的卷積值被保留。而bn的作用是使得輸入值的均值為0,方差為1,也就是說假如relu之前是bn的話,會有接近一半的輸入值被抑制,一半的輸入值被保留。

所以bn放到relu之前的好處可以這樣理解:bn可以防止某一層的激活值全部都被抑制,從而防止從這一層往前傳的梯度全都變成0,也就是防止梯度消失。(當然也可以防止梯度爆炸)

還有一個好處,把bn放到激活前面是有可以把卷積的weight和bn的參數進行合併的,所以它有利於網絡在做前向inference時候進行加速。

作者:郭嘉
https://www.zhihu.com/question/283715823/answer/553603362

前面答案說了一大堆bn放在relu後面的好處和理論依據。

而我用resnet18訓練手部檢測,只改變bn和relu的順序,和有些答主一樣,bn放在relu前面效果稍微好一點。

深度學習的理論真的有那麼肯定的話,就不需要做那麼多實驗來調整網絡了,根據自己的使用場景,自己實驗才是正確的答案。

下載1:OpenCV-Contrib擴展模塊中文版教程在「小白學視覺」公眾號後臺回覆:擴展模塊中文教程即可下載全網第一份OpenCV擴展模塊教程中文版,涵蓋擴展模塊安裝、SFM算法、立體視覺、目標跟蹤、生物視覺、超解析度處理等二十多章內容。在「小白學視覺」公眾號後臺回覆:Python視覺實戰項目31講即可下載包括圖像分割、口罩檢測、車道線檢測、車輛計數、添加眼線、車牌識別、字符識別、情緒檢測、文本內容提取、面部識別等31個視覺實戰項目,助力快速學校計算機視覺。在「小白學視覺」公眾號後臺回覆:OpenCV實戰項目20講即可下載含有20個基於OpenCV實現20個實戰項目,實現OpenCV學習進階。在「小白學視覺」公眾號後臺回覆:leetcode即可下載。每題都 runtime beats 100% 的開源好書,你值得擁有!

交流群

歡迎加入公眾號讀者群一起和同行交流,目前有SLAM、三維視覺、傳感器、自動駕駛、計算攝影、檢測、分割、識別、醫學影像、GAN、算法競賽等微信群(以後會逐漸細分),請掃描下面微信號加群,備註:」暱稱+學校/公司+研究方向「,例如:」張三 + 上海交大 + 視覺SLAM「。請按照格式備註,否則不予通過。添加成功後會根據研究方向邀請進入相關微信群。請勿在群內發送廣告,否則會請出群,謝謝理解~

相關焦點

  • 理解Batch Normalization(含實現代碼)
    批量歸一化將層輸出轉換為單位高斯分布。當這些輸出通過激活功能饋送時,層激活也將變得更加正常分布。由於上一層的輸出是下一層的輸入,因此層輸入的變化在不同批次輸間的變化將顯著減少。通過減少層的輸入的變化分布,我們解決了第一個問題。數學解釋通過批量歸一化,我們為每個激活函數尋找均值為0,方差為1的分布作為輸入。在訓練期間,我們將激活輸入x減去批次均值μ以實現零中心分布。
  • 為什麼ReLu激活函數要好於tanh和sigmoid?
    當然現在也有一些對relu的改進,比如prelu,random relu等,在不同的數據集上會有一些訓練速度上或者準確率上的改進,具體的大家可以找相關的paper看。多加一句,現在主流的做法,會多做一步batch normalization,儘可能保證每一層網絡的輸入具有相同的分布[1]。
  • Batch Normalization 的實戰使用
    前言Batch normalization 有多好用我就不多說了,一般來說,做卷積神經網絡加上batch normalization,效果會得到一定的提升的。具體的batch normalization的原理可以參照(https://zhuanlan.zhihu.com/p/34879333)我在他的基礎上補充關於卷積神經網絡使用Batch normalization的一些代碼實現。
  • 什麼是批標準化 (Batch Normalization)
    比如某個神經元 x 的值為1, 某個 Weights 的初始值為 0.1, 這樣後一層神經元計算結果就是 Wx = 0.1; 又或者 x = 20, 這樣 Wx 的結果就為 2. 現在還不能看出什麼問題, 但是, 當我們加上一層激勵函數, 激活這個 Wx 值的時候, 問題就來了.
  • 乾貨 | BatchNormalization詳解與比較
    Batch NormalizationbatchNormalization就像是名字一樣,對一個batch的數據進行normalization。現在假設一個batch有3個數據,每個數據有兩個特徵:(1,2),(2,3),(0,1)如果做一個簡單的normalization,那麼就是計算均值和方差,把數據減去均值除以標準差,變成0均值1方差的標準形式。
  • Batch Normalization原理與實戰(下)
    這裡的initial_weights是一個list,list中每一個元素是一個矩陣(二維tuple),存儲了每一層的權重矩陣。build_network實現了網絡的構建,並調用了fully_connected函數(下面會提)進行計算。要注意的是,由於MNIST是多分類,在這裡我們不需要對最後一層進行激活,保留計算的logits就好。
  • 深入理解Batch Normalization
    LRN是一個非訓練層,即該層中不存在可訓練的參數。假設某一個CNN層的輸出為一個 WxHxC 的張量,要對該張量做LRN我們應該怎麼做呢。假設我們取n的大小為3,現在我們要計算(x, y, i)位置上 LRN 後的值,我們便可以以 (x,y, i)點位中心,在channel維度範圍內取一個1xn大小的網格,此時我們便可以通過(x, y, i)位置的數值和其周圍的數值對(x, y, i)位置進行正則化,具體計算公式如下
  • Batch Normalization
    我們用mini-batch來逼近損失函數真實梯度為什麼要mini-batch?因此, 我們希望每一層輸入的分布是保持固定的.飽和問題我們考慮神經網絡某層中的sigmoid激活層在每一層中, 我們都會做非線性激活, 比如用sigmoid函數, 如果所有的變量都集中在
  • 大貝貝,激活函數 sigmoid、tanh、relu
    而另一種情況,梯度爆炸(exploding gradient),則是前面層的梯度,通過訓練變大,導致後面層的梯度,以指數級增大。sigmoid的更新速率由於sigmoid的導數值小於1/4,x變化的速率要快於y變化的速率,隨著層數的增加,連續不斷執行sigmoid函數,就會導致,前面更新較大的幅度,後面更新較小的幅度,因此,網絡在學習過程中
  • 學習筆記TF014:卷積層、激活函數、池化層、歸一化層、高級層
    圖像識別分類,使用不同層類型支持卷積層,減少過擬合,加速訓練過程,降低內存佔用率。TensorFlow加速所有不同類弄卷積層卷積運算。激活函數與其他層輸出生成特徵圖,對某些運算結果平滑(微分),為神經網絡引入非線性(輸入輸出曲線關係),刻畫輸入複雜變化,訓練複雜模型。激活函數主要因素,單調,輸出隨輸入增長,可用梯度下降法找局部極值點;可微分,定義域內任意一點有導數,輸出可用梯度下降法。tf.nn.relu,修正線性單元,斜坡函數。分段線性,輸入非負輸出相同,輸入為負輸出為0。
  • 什麼是 Batch Normalization?
    sigmoid作為激活函數一個最大的問題會引起梯度消失現象,這使得神經網絡難以更新權重。使用ReLu激活函數可以有效的緩解這一問題。     ICS問題導致深度神經網絡訓練難以收斂,隱藏層輸入分布逐漸向非線性激活函數取值區間的兩端靠近,比如說sigmoid函數的兩端就是最大正值或者最小負值。這裡說一下梯度飽和和梯度敏感的概念。
  • 總結|激活函數之sigmoid、ReLU、ELU 以及更新的 Leaky ReLU、SELU、GELU
    來自丹麥技術大學的 Casper Hansen 通過公式、圖表和代碼實驗介紹了 sigmoid、ReLU、ELU 以及更新的 Leaky ReLU、SELU、GELU 這些激活函數,並比較了它們的優勢和短板。在計算每一層的激活值時,我們要用到激活函數,之後才能確定這些激活值究竟是多少。根據每一層前面的激活、權重和偏置,我們要為下一層的每個激活計算一個值。
  • 【精華】Batch Normalization理論與實踐
    我們知道網絡一旦train起來,那麼參數就要發生更新,除了輸入層的數據外(因為輸入層數據,我們已經人為的為每個樣本歸一化),後面網絡每一層的輸入數據分布是一直在發生變化的,因為在訓練的時候,前面層訓練參數的更新將導致後面層輸入數據分布的變化。
  • 面試題:人工神經網絡中為什麼ReLu要好過於tanh和sigmoid?
    第一,採用sigmoid等函數,算激活函數時(指數運算),計算量大。反向傳播求誤差梯度時,求導涉及除法和指數運算,計算量相對大,而採用Relu激活函數,整個過程的計算量節省很多。第二,對於深層網絡,sigmoid函數反向傳播時,很容易就會出現梯度消失的情況(在sigmoid接近飽和區時,變換太緩慢,導數趨於0,這種情況會造成信息丟失。)
  • 從ReLU到GELU,一文概覽神經網絡的激活函數
    根據每一層前面的激活、權重和偏置,我們要為下一層的每個激活計算一個值。但在將該值發送給下一層之前,我們要使用一個激活函數對這個輸出進行縮放。本文將介紹不同的激活函數。在閱讀本文之前,你可以閱讀我前一篇介紹神經網絡中前向傳播和反向傳播的文章,其中已經簡單地提及過激活函數,但還未介紹其實際所做的事情。
  • 詳解Batch Normalization及其反向傳播
    在神經網絡中,網絡是分層的,可以把每一層視為一個單獨的分類器,將一個網絡看成分類器的串聯。這就意味著,在訓練過程中,隨著某一層分類器的參數的改變,其輸出的分布也會改變,這就導致下一層的輸入的分布不穩定。分類器需要不斷適應新的分布,這就使得模型難以收斂。
  • 深度學習激活函數完全指南:在數據科學的諸多曲線上進行現代之旅
    通常只有網絡的最後一層(輸出層)中需要用到這些數值性質,因為它是唯一需要特殊處理的圖層。對於其他的網絡層,可以使用更簡單的非線性函數,例如 ReLU 。雖然在某些情況下,網絡中間層需要特殊激活函數,例如目標檢測模型和attention層,但這些並不常見,因此不在本文討論範圍之內。
  • 如何選擇神經網絡激活函數:有效的改善模型學習模式的能力
    這些模型的輸出如下:每層的這些輸出都將導入多層網絡(如深度神經網絡)的下一個後續層,直到獲得最終輸出為止,但默認情況下它們是線性的。 預期的輸出確定要在給定網絡中部署的激活功能的類型。 但是,由於輸出本質上是線性的,因此需要非線性激活函數才能將這些線性輸入轉換為非線性輸出。 這些激活函數是傳遞函數,可應用於線性模型的輸出以生成轉換後的非線性輸出,以備進一步處理。
  • Layer Normalization
    最近半個月因為旅遊和開學,一直沒有更新,各位沒有取關看來是真愛了,比心~~這邊生活穩定之後更新應該也會比較穩定...吧...這學期選了很多數學課,今天恰好又看到一篇數學性很強的論文,所以決心用這篇來練練手差點直接勸退...廢話不多說,進入今天的正題——layer normalization。