本文最初發表於2017年10月,並於2020年1月進行了更新,增加了三個新的啟用函式和python程式碼。引言
今天,因特網提供了獲取大量資訊的途徑。無論我們需要什麼,只需要谷歌搜尋一下即可。然而,當我們獲取了這麼多的資訊時,我們又面臨著如何區分相關和無關的資訊的挑戰。當我們的大腦被同時灌輸大量資訊時,它會努力去理解這些資訊並將其分為“有用的”和“不那麼有用的”。對於神經網路而言,我們需要類似的機制來將輸入的資訊分為“有用的”或“不太有用的”。這是網路學習的重要方式,因為並不是所有的資訊都同樣有用。它們中的一些僅僅是噪音,而這就是啟用函式的用武之地了。啟用函式幫助神經網路使用重要資訊,並抑制不相關的資料點。接下來讓我們來看看這些啟用函式,瞭解它們是如何工作的,並找出哪些啟用函式適合於什麼樣的問題情景。目錄
- Parameterised ReLU(引數化線性整流函式)
- Exponential Linear Unit(指數化線性單元)
1. 神經網路概述
在我深入研究啟用函式的細節之前,讓我們先快速瞭解一下神經網路的概念以及它們是如何工作的。神經網路是一種非常強大的模仿人腦學習方式的機器學習機制。
大腦接收外界的刺激,對輸入進行處理,然後產生輸出。當任務變得複雜時,多個神經元形成一個複雜的網路,相互傳遞資訊。
人工神經網路試圖模仿類似的行為。你下面看到的網路是由相互連線的神經元構成的神經網路。每個神經元的特徵是其權重、偏置和啟用函式。輸入資訊被輸入到輸入層,神經元使用權重和偏差對輸入進行線性變換。x = (weight * input) + bias
最後,啟用函式的輸出移動到下一個隱藏層,重複相同的過程。這種資訊的前向移動稱為前向傳播。如果生成的輸出與實際值相距甚遠怎麼辦?利用前向傳播的輸出來計算誤差。根據這個誤差值,更新神經元的權值和偏差。這個過程稱為反向傳播。注:要詳細理解正向傳播和反向傳播,您可以閱讀下面的文章:Understanding and coding neural network from scratch附連結:https://www.analyticsvidhya.com/blog/2017/05/neural-network-from-scratch-in-python-and-r/我們知道,在正向傳播期間,使用啟用函式會在每一層引入一個額外的步驟。現在我們的問題是,假如啟用函式給神經網路增加了複雜性,我們可以不使用啟用函式嗎?想象一個沒有啟用函式的神經網路。在這種情況下,每個神經元只會利用權重和偏差對輸入資訊進行線性變換。雖然線性變換使神經網路更簡單,但這個網路的功能會變得更弱,並無法從資料中學習複雜的模式。沒有啟用函式的神經網路本質上只是一個線性迴歸模型。因此,我們對神經元的輸入進行非線性變換,而神經網路中的這種非線性是由啟用函式引入的。在下一節中,我們將研究不同型別的啟用函式、它們的數學公式、圖形表示和python程式碼。當我們有一個啟用函式時,首先想到的是一個基於閾值的分類器,即神經元是否應該根據線性變換的值被啟用。換句話說,如果啟用函式的輸入大於閾值,則神經元被啟用,否則它就會失效,即它的輸出不考慮下一個隱含層。讓我們從數學的角度來看。這是最簡單的啟用函式,可以用python中的一個if-else判斷來實現def binary_step(x):
if x<0:
return 0
else:
return 1binary_step(5), binary_step(-1)
在建立二分類器時,可以將二二元階躍函式用作啟用函式。可以想象,當目標變數中有多個類時,這個函式將會失效。這就是二元階躍函式的侷限性之一。此外,階躍函式的梯度為零,在反向傳播過程中造成了障礙。也就是說,如果計算f(x)關於x的導數,結果是0。
反向傳播過程中的權重和偏差是通過計算梯度來更新的。因為函式的梯度是零,所以權值和偏差不會更新。在上面,我們看到了階躍函式的問題是函式的梯度變成了0。這是由於在二元階躍函式中沒有x的分量,因此我們可以用線性函式代替二元函式。我們可以把這個函式定義為:這裡的活性值(activation)與輸入成正比。本例中的變數“a”可以是任何常數值。讓我們快速定義python中的函式:
def linear_function(x):
return 4*x linear_function(4),
linear_function(-2)
輸出:
你認為這種情況下的導數是什麼呢?當我們對函式關於x求導時,得到的結果將是x的係數,而這個係數是一個常數。
雖然這裡的梯度不為零,但它是一個常數,與輸入值x無關。這意味著權值和偏差在反向傳播過程中會被更新,但更新因子是相同的。
在這種情況下,神經網路並不能真正改善誤差,因為每次迭代的梯度是相同的。網路將不能很好地訓練和從資料中捕獲複雜的模式。因此,線性函式可能是需要高度解釋能力的簡單任務的理想選擇。我們要看的下一個啟用函式是Sigmoid函式。它是應用最廣泛的非線性啟用函式之一。Sigmoid將值轉換為0和1之間。這是sigmoid的數學表示式:這裡值得注意的一點是,與二元階躍和線性函式不同,sigmoid是一個非線性函式。這本質上意味著,當我有多個神經元以sigmoid啟用函式作為它們的啟用函式時,它們的輸出也是非線性的。下面是在python定義函式的python程式碼:import numpy as np
def sigmoid_function
(x): z = (1/(1 + np.exp(-x)))
return z sigmoid_function(7),sigmoid_function(-22)
輸出:
(0.9990889488055994, 2.7894680920908113e-10)
另外,正如你在上圖中看到的,這是一個光滑的s型函式,並且是連續可微的。這個函式的導數是(1-sigmoid(x))。讓我們來看看它的梯度圖。
梯度值在-3和3範圍內是顯著的,但在其他區域,圖形變得更平坦。這意味著對於大於3或小於-3的值,梯度非常小。當梯度值趨近於0時,網路就不是真的在學習。另外,sigmoid函式不是關於0對稱的。所以所有神經元的輸出都是相同的符號。這可以通過縮放sigmoid函式來解決,這正是tanh函式所做的。請讓我們繼續讀下去。tanh函式與sigmoid函式非常相似。唯一不同的是它是關於原點對稱的。本例中值的範圍是從-1到1。因此,下一層的輸入並不總是相同的符號。tanh函式定義為:為了使用python編寫程式碼,讓我們簡化前面的表示式。tanh(x) = 2sigmoid(2x)-1
tanh(x) = 2/(1+e^(-2x)) -1
def tanh_function(x):
z = (2/(1 + np.exp(-2*x))) -1
return z tanh_function(0.5),
tanh_function(-1)
(0.4621171572600098, -0.7615941559557646)
就像你看到的,值的範圍是-1到1。除此之外,tanh函式的其他性質都與sigmoid函式相同。與sigmoid相似,tanh函式在所有點上都是連續可微的。
與sigmoid函式相比,tanh函式的梯度更陡。你可能會好奇,我們如何決定選擇哪個啟用函式。通常tanh比sigmoid函式更受歡迎,因為它是以0為中心的,而且梯度不受一定方向的限制。ReLU函式是另一個在深度學習領域得到廣泛應用的非線性啟用函式。ReLU表示線性整流單元(Rectified Linear Unit)。與其他啟用函式相比,使用ReLU函式的主要優點是它不會同時啟用所有神經元。這意味著只有當線性變換的輸出小於0時,神經元才會失效。下圖將幫助你更好地理解這一點:對於負的輸入值,結果是零,這意味著神經元沒有被啟用。由於只有一定數量的神經元被啟用,ReLU函式的計算效率遠高於sigmoid和tanh函式。下面是ReLU的python函式:
def relu_function(x):
if x<0:
return 0
else:
return x relu_function(7), relu_function(-7)
輸出:
如果你觀察圖形的負方向,你會注意到梯度值是零。由於這個原因,在反向傳播過程中,一些神經元的權重和偏差沒有更新。這可能會產生從未被啟用的死亡神經元。這種情況可通過“洩漏”ReLU函式來處理。Leaky ReLU函式只是ReLU函式的一個改進版本。如我們所見,對於ReLU函式,當x<0時,梯度為0,這將使該區域的神經元失活。定義Leaky ReLU是為了解決這個問題。我們不把x的負值定義為0,而是定義為x的一個極小的線性分量,這裡給出它的數學定義:f(x)= 0.01x, x<0
= x, x>=0
通過這個小的修改,圖形左邊的梯度就變成了一個非零值。因此,我們將不再在那個區域遇到死亡的神經元。這是Leaky ReLU函式的導數:
f'(x) = 1, x>=0
=0.01, x<0
因為Leaky ReLU是ReLU的一個變體,所以python程式碼可以通過一個小的修改來實現:def leaky_relu_function(x):
if x<0:
return 0.01*x
else:
return x leaky_relu_function(7), leaky_relu_function(-7)
除了Leaky ReLU,還有一些其他的ReLU變體,最流行的是Parameterised ReLU函式和Exponential Liner Unit。這是ReLU的另一個變體,旨在解決軸的左半部分的梯度為零的問題。顧名思義,引數化ReLU引入了一個新引數作為函式負部分的斜率。下面是如何修改ReLU函式以體現包含的斜率引數-當a的值固定為0.01時,函式就變成了Leaky ReLU函式。然而,對於Parameterised ReLU函式,‘a’也是一個可訓練的引數。該網路還學習了' a '的值,以便更快、更優地收斂。這個函式的導數和Leaky ReLu函式是一樣的,除了0.01的值會被替換成a的值。當使用Leaky ReLU函式仍然不能解決未啟用神經元問題,相關資訊無法成功傳遞到下一層時,我們就可以使用Parameterised ReLU函式。指數化線性單元(簡稱ELU)也是線性整流單元(ReLU)的一種變體,它改變了函式負部分的斜率。與Leaky Relu和parametric Relu函式不同,ELU使用了Log曲線來代替直線定義函式的負數部分。它被定義為f(x) = x, x>=0
= a(e^x-1), x<0
def elu_function(x, a):
if x<0:
return a*(np.exp(x)-1)
else:
return x elu_function(5, 0.1),elu_function(-5, 0.1)
(5, -0.09932620530009145)
ELU函式對於x大於0的值的導數是1,就像所有ReLU變體一樣。但對於x<0的值,導數是a.e ^x 。f'(x) = x, x>=0
= a(e^x), x<0
Swish是一個不太為人所知的啟用函式,它是由谷歌的研究人員發現的。Swish的計算效率與ReLU相當,並且在層次更深的模型上顯示出比ReLU更好的效能。swish的值從負無窮到正無窮。函式定義為-
f(x) = x*sigmoid(x)
f(x) = x/(1-e^-x)
正如你所看到的,函式曲線是平滑且在所有點上都是可微的。這在模型優化過程中是有幫助的,也是Swish被認為優於Relu的原因之一。關於這個函式的一個獨特的特徵是,swich函式不是單調的。這意味著即使輸入值增加,函式值也可能減少。讓我們看看swish函式的python程式碼:def swish_function(x):
return x/(1-np.exp(-x))
swish_function(-67), swish_function(4)
(5.349885844610276e-28, 4.074629441455096)
Softmax函式通常被描述為多個sigmoid的組合。我們知道sigmoid返回0到1之間的值,可將函式值視為資料點屬於特定類的概率。因此,sigmoid被廣泛應用於二分類問題。softmax函式可用於多類分類問題。這個函式返回屬於每個類的資料點的概率。這是相同的數學表示式:在為一個多類問題構建神經網路時,輸出層的神經元數量與目標中的類的數量相同。例如,如果你有三個類,在輸出層會有三個神經元。假設神經元的輸出是[1.2,0.9,0.75]。對這些值應用softmax函式,您將得到以下結果—[0.42,0.31,0.27]。這些值表示這些資料點屬於每個類的概率。值得注意的是,所有值的和為1。讓我們在python中編碼:def softmax_function(x):
z = np.exp(x)
z_ = z/z.sum()
return z_
softmax_function([0.8, 1.2, 3.1])
softmax_function([1.2 , 0.9 , 0.75])
4.選擇正確的啟用函式
現在我們已經看到了這麼多的啟用函式,我們需要一些邏輯/啟示來了解在什麼情況下應該使用哪個啟用函式。好或壞的判斷並沒有經驗法則。
然而,根據問題的性質,我們可以做出更好的選擇,使網路更容易、更快地收斂。
對於分類器,Sigmoid函式及其組合通常工作得更好。
由於有梯度消失的問題,有時會避免使用sigmoid和tanh函式。
ReLU函式是一種通用的啟用函式,目前被廣泛使用。
如果在我們的網路中遇到神經元未啟用的情況,Leaky ReLU函式是最好的選擇。
始終記住,ReLU函式應該只在隱藏層中使用。
根據經驗,您可以從使用ReLU函式開始,然後在ReLU不能提供最佳結果的情況下轉移到其他啟用函式。
現在,是時候冒險嘗試一下其他真實的資料集了。那麼你準備好接受挑戰了嗎?通過以下實踐問題加速你的深度學習之旅:l Practice Problem: Identify the Apparels(見下面連結)https://datahack.analyticsvidhya.com/contest/practice-problem-identify-the-apparels/?utm_source=fundamentals-deep-learning-activation-functions-when-to-use-them&utm_medium=blogl Practice Problem: Identify the Digits(見下面連結)
https://datahack.analyticsvidhya.com/contest/practice-problem-identify-the-digits/?utm_source=fundamentals-deep-learning-activation-functions-when-to-use-them&utm_medium=blog
結語:在本文中,我討論了各種型別的啟用函式,以及在使用它們時可能遇到的問題型別。我建議你先從ReLU函式開始,並隨著你慢慢深入時,探索其他函式。你還可以設計自己的啟用函式,為你的神經網路提供一個非線性元件。如果您使用了自己的啟用函式並且效果非常好,請與我們分享,我們將很樂意將其納入列表。https://www.analyticsvidhya.com/blog/2020/01/fundamentals-deep-learning-activation-functions-when-to-use-them/Fundamentals of Deep Learning – Activation Functions and When to Use Them?