為什么引入激活函數?
如果不用激勵函數(其實相當於激勵函數是f(x) = x),在這種情況下你每一層輸出都是上層輸入的線性函數,很容易驗證,無論你神經網絡有多少層,輸出都是輸入的線性組合,與沒有隱藏層效果相當,這種情況就是最原始的感知機(Perceptron)了。
正因為上面的原因,我們決定引入非線性函數作為激勵函數,這樣深層神經網絡就有意義了(不再是輸入的線性組合,可以逼近任意函數)。最早的想法是sigmoid函數或者tanh函數,輸出有界,很容易充當下一層輸入(以及一些人的生物解釋balabala)。激活函數的作用是為了增加神經網絡模型的非線性。否則你想想,沒有激活函數的每層都相當於矩陣相乘。就算你疊加了若干層之后,無非還是個矩陣相乘罷了。所以你沒有非線性結構的話,根本就算不上什么神經網絡。
為什么引入Relu呢?
第一,采用sigmoid等函數,算激活函數時(指數運算),計算量大,反向傳播求誤差梯度時,求導涉及除法,計算量相對大,而采用Relu激活函數,整個過程的計算量節省很多。
第二,對於深層網絡,sigmoid函數反向傳播時,很容易就會出現梯度消失的情況(在sigmoid接近飽和區時,變換太緩慢,導數趨於0,這種情況會造成信息丟失,從而無法完成深層網絡的訓練。
第三,Relu會使一部分神經元的輸出為0,這樣就造成了網絡的稀疏性,並且減少了參數的相互依存關系,緩解了過擬合問題的發生(以及一些人的生物解釋balabala)。
當然現在也有一些對relu的改進,比如prelu,random relu等,在不同的數據集上會有一些訓練速度上或者准確率上的改進,具體的大家可以找相關的paper看。
多加一句,現在主流的做法,會多做一步batch normalization,盡可能保證每一層網絡的輸入具有相同的分布[1]。而最新的paper[2],他們在加入bypass connection之后,發現改變batch normalization的位置會有更好的效果。大家有興趣可以看下。
深度學習的基本原理是基於人工神經網絡,信號從一個神經元進入,經過非線性的activation function,傳入到下一層神經元;再經過該層神經元的activate,繼續往下傳遞,如此循環往復,直到輸出層。正是由於這些非線性函數的反復疊加,才使得神經網絡有足夠的capacity來抓取復雜的pattern,在各個領域取得state-of-the-art的結果。顯而易見,activation function在深度學習中舉足輕重,也是很活躍的研究領域之一。目前來講,選擇怎樣的activation function不在於它能否模擬真正的神經元,而在於能否便於優化整個深度神經網絡。下面我們簡單聊一下各類函數的特點以及為什么現在優先推薦ReLU函數。
Sigmoid函數
Sigmoid函數是深度學習領域開始時使用頻率最高的activation function。它是便於求導的平滑函數,其導數為,這是優點。然而,Sigmoid有三大缺點:
-
容易出現gradient vanishing
-
函數輸出並不是zero-centered
-
冪運算相對來講比較耗時
Gradient Vanishing
優化神經網絡的方法是Back Propagation,即導數的后向傳遞:先計算輸出層對應的loss,然后將loss以導數的形式不斷向上一層網絡傳遞,修正相應的參數,達到降低loss的目的。 Sigmoid函數在深度網絡中常常會導致導數逐漸變為0,使得參數無法被更新,神經網絡無法被優化。原因在於兩點:(1) 在上圖中容易看出,當中較大或較小時,導數接近0,而后向傳遞的數學依據是微積分求導的鏈式法則,當前層的導數需要之前各層導數的乘積,幾個小數的相乘,結果會很接近0 (2) Sigmoid導數的最大值是0.25,這意味着導數在每一層至少會被壓縮為原來的1/4,通過兩層后被變為1/16,…,通過10層后為1/1048576。請注意這里是“至少”,導數達到最大值這種情況還是很少見的。
輸出不是zero-centered
Sigmoid函數的輸出值恆大於0,這會導致模型訓練的收斂速度變慢。舉例來講,對,如果所有均為正數或負數,那么其對的導數總是正數或負數,這會導致如下圖紅色箭頭所示的階梯式更新,這顯然並非一個好的優化路徑。深度學習往往需要大量時間來處理大量數據,模型的收斂速度是尤為重要的。所以,總體上來講,訓練深度學習網絡盡量使用zero-centered數據 (可以經過數據預處理實現) 和zero-centered輸出。
冪運算相對耗時
相對於前兩項,這其實並不是一個大問題,我們目前是具備相應計算能力的,但面對深度學習中龐大的計算量,最好是能省則省 :-)。之后我們會看到,在ReLU函數中,需要做的僅僅是一個thresholding,相對於冪運算來講會快很多。
tanh函數
tanh讀作Hyperbolic Tangent,如上圖所示,它解決了zero-centered的輸出問題,然而,gradient vanishing的問題和冪運算的問題仍然存在。
ReLU函數
ReLU函數其實就是一個取最大值函數,注意這並不是全區間可導的,但是我們可以取sub-gradient,如上圖所示。ReLU雖然簡單,但卻是近幾年的重要成果,有以下幾大優點:
-
解決了gradient vanishing問題 (在正區間)
-
計算速度非常快,只需要判斷輸入是否大於0
-
收斂速度遠快於sigmoid和tanh
ReLU也有幾個需要特別注意的問題:
-
ReLU的輸出不是zero-centered
-
Dead ReLU Problem,指的是某些神經元可能永遠不會被激活,導致相應的參數永遠不能被更新。有兩個主要原因可能導致這種情況產生: (1) 非常不幸的參數初始化,這種情況比較少見 (2) learning rate太高導致在訓練過程中參數更新太大,不幸使網絡進入這種狀態。解決方法是可以采用Xavier初始化方法,以及避免將learning rate設置太大或使用adagrad等自動調節learning rate的算法。
盡管存在這兩個問題,ReLU目前仍是最常用的activation function,在搭建人工神經網絡的時候推薦優先嘗試!
Leaky ReLU函數
人們為了解決Dead ReLU Problem,提出了將ReLU的前半段設為而非0。另外一種直觀的想法是基於參數的方法,即Parametric ReLU:,其中可由back propagation學出來。理論上來講,Leaky ReLU有ReLU的所有優點,外加不會有Dead ReLU問題,但是在實際操作當中,並沒有完全證明Leaky ReLU總是好於ReLU。
ELU (Exponential Linear Units) 函數
ELU也是為解決ReLU存在的問題而提出,顯然,ELU有ReLU的基本所有優點,以及:
-
不會有Deal ReLU問題
-
輸出的均值接近0,zero-centered
它的一個小問題在於計算量稍大。類似於Leaky ReLU,理論上雖然好於ReLU,但在實際使用中目前並沒有好的證據ELU總是優於ReLU。
小結
建議使用ReLU函數,但是要注意初始化和learning rate的設置;可以嘗試使用Leaky ReLU或ELU函數;不建議使用tanh,尤其是sigmoid函數。
更多關於激活函數的知識
via : https://www.zhihu.com/question/29021768