深度學習基礎——啟用函式以及什麼時候使用它們?(附程式碼)

資料派THU發表於2020-03-06

摘要

  • 啟用函式神經網路的組成部分之一。

  • 學習深度學習中不同的啟用函式

  • 在python中編寫啟用函式並在實時編碼視窗中將結果視覺化。

本文最初發表於2017年10月,並於2020年1月進行了更新,增加了三個新的啟用函式和python程式碼。

引言

今天,因特網提供了獲取大量資訊的途徑。無論我們需要什麼,只需要谷歌搜尋一下即可。然而,當我們獲取了這麼多的資訊時,我們又面臨著如何區分相關和無關的資訊的挑戰。

當我們的大腦被同時灌輸大量資訊時,它會努力去理解這些資訊並將其分為“有用的”和“不那麼有用的”。對於神經網路而言,我們需要類似的機制來將輸入的資訊分為“有用的”或“不太有用的”。

深度學習基礎——啟用函式以及什麼時候使用它們?(附程式碼)

這是網路學習的重要方式,因為並不是所有的資訊都同樣有用。它們中的一些僅僅是噪音,而這就是啟用函式的用武之地了。啟用函式幫助神經網路使用重要資訊,並抑制不相關的資料點。

接下來讓我們來看看這些啟用函式,瞭解它們是如何工作的,並找出哪些啟用函式適合於什麼樣的問題情景。

目錄

1. 神經網路概述
2. 我們可以不使用啟用函式麼?
3. 常用的啟用函式以及什麼時候使用他們
  • Binary Step(二元階躍)
  • Linear(線性)
  • Sigmoid(S型)
  • Tanh(雙曲正切)
  • ReLU(線性整流單元)
  • Leaky ReLU(洩露型線性整流函式
  • Parameterised ReLU(引數線性整流函式
  • Exponential Linear Unit(指數化線性單元)
  • Swish
  • Softmax
4. 選擇正確的啟用函式

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/

2. 我們可以不使用啟用函式麼?

我們知道,在正向傳播期間,使用啟用函式會在每一層引入一個額外的步驟。現在我們的問題是,假如啟用函式神經網路增加了複雜性,我們可以不使用啟用函式嗎?

想象一個沒有啟用函式神經網路在這種情況下,每個神經元只會利用權重和偏差對輸入資訊進行線性變換。雖然線性變換使神經網路更簡單,但這個網路的功能會變得更弱,並無法從資料中學習複雜的模式。

沒有啟用函式神經網路本質上只是一個線性迴歸模型。

因此,我們對神經元的輸入進行非線性變換,而神經網路中的這種非線性是由啟用函式引入的。

在下一節中,我們將研究不同型別的啟用函式、它們的數學公式、圖形表示和python程式碼。

3. 常用的啟用函式以及什麼時候使用他們
  • 二元階躍函式

當我們有一個啟用函式時,首先想到的是一個基於閾值的分類器,即神經元是否應該根據線性變換的值被啟用。

換句話說,如果啟用函式的輸入大於閾值,則神經元被啟用,否則它就會失效,即它的輸出不考慮下一個隱含層。讓我們從數學的角度來看。
f(x) = 1, x>=0     = 0, x<0

深度學習基礎——啟用函式以及什麼時候使用它們?(附程式碼)

這是最簡單的啟用函式,可以用python中的一個if-else判斷來實現
def binary_step(x):    
if x<0:        
return 0    
else:        
return 1binary_step(5), binary_step(-1)
輸出:
(5,0)

在建立二分類器時,可以將二二元階躍函式用作啟用函式。可以想象,當目標變數中有多個類時,這個函式將會失效。這就是二元階躍函式的侷限性之一。

此外,階躍函式的梯度為零,在反向傳播過程中造成了障礙。也就是說,如果計算f(x)關於x的導數,結果是0。

f'(x) = 0, for all x

深度學習基礎——啟用函式以及什麼時候使用它們?(附程式碼)

反向傳播過程中的權重和偏差是透過計算梯度來更新的。因為函式的梯度是零,所以權值和偏差不會更新。
  • Linear Function

在上面,我們看到了階躍函式的問題是函式的梯度變成了0。這是由於在二元階躍函式中沒有x的分量,因此我們可以用線性函式代替二元函式。我們可以把這個函式定義為:
f(x)=ax

深度學習基礎——啟用函式以及什麼時候使用它們?(附程式碼)

這裡的活性值(activation)與輸入成正比。本例中的變數“a”可以是任何常數值。讓我們快速定義python中的函式:

def linear_function(x):
return 4*x linear_function(4), 
linear_function(-2)

輸出:

(16, -8)

你認為這種情況下的導數是什麼呢?當我們對函式關於x求導時,得到的結果將是x的係數,而這個係數是一個常數。

f'(x) = a

雖然這裡的梯度不為零,但它是一個常數,與輸入值x無關。這意味著權值和偏差在反向傳播過程中會被更新,但更新因子是相同的。

在這種情況下,神經網路並不能真正改善誤差,因為每次迭代的梯度是相同的。網路將不能很好地訓練和從資料中捕獲複雜的模式。因此,線性函式可能是需要高度解釋能力的簡單任務的理想選擇。
  • Sigmoid

我們要看的下一個啟用函式是Sigmoid函式。它是應用最廣泛的非線性啟用函式之一。Sigmoid將值轉換為0和1之間。這是sigmoid的數學表示式:
f(x) = 1/(1+e^-x)

深度學習基礎——啟用函式以及什麼時候使用它們?(附程式碼)

這裡值得注意的一點是,與二元階躍和線性函式不同,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))。讓我們來看看它的梯度圖。

f'(x) = 1-sigmoid(x)

深度學習基礎——啟用函式以及什麼時候使用它們?(附程式碼)

梯度值在-3和3範圍內是顯著的,但在其他區域,圖形變得更平坦。這意味著對於大於3或小於-3的值,梯度非常小。當梯度值趨近於0時,網路就不是真的在學習。

另外,sigmoid函式不是關於0對稱的。所以所有神經元的輸出都是相同的符號。這可以透過縮放sigmoid函式來解決,這正是tanh函式所做的。請讓我們繼續讀下去。
  • Tanh

tanh函式與sigmoid函式非常相似。唯一不同的是它是關於原點對稱的。本例中值的範圍是從-1到1。因此,下一層的輸入並不總是相同的符號。tanh函式定義為:
tanh(x)=2sigmoid(2x)-1

深度學習基礎——啟用函式以及什麼時候使用它們?(附程式碼)

為了使用python編寫程式碼,讓我們簡化前面的表示式。
tanh(x) = 2sigmoid(2x)-1
tanh(x) = 2/(1+e^(-2x)) -1
下面是它的python程式碼:
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函式在所有點上都是連續可微的。

我們來看看tanh函式的梯度。

深度學習基礎——啟用函式以及什麼時候使用它們?(附程式碼)

與sigmoid函式相比,tanh函式的梯度更陡。你可能會好奇,我們如何決定選擇哪個啟用函式。通常tanh比sigmoid函式更受歡迎,因為它是以0為中心的,而且梯度不受一定方向的限制。
  • ReLU

ReLU函式是另一個在深度學習領域得到廣泛應用的非線性啟用函式。ReLU表示線性整流單元(Rectified Linear Unit)。與其他啟用函式相比,使用ReLU函式的主要優點是它不會同時啟用所有神經元

這意味著只有當線性變換的輸出小於0時,神經元才會失效。下圖將幫助你更好地理解這一點:
f(x)=max(0,x)

深度學習基礎——啟用函式以及什麼時候使用它們?(附程式碼)對於負的輸入值,結果是零,這意味著神經元沒有被啟用。由於只有一定數量的神經元被啟用,ReLU函式的計算效率遠高於sigmoid和tanh函式。下面是ReLU的python函式:

def relu_function(x):    
if x<0:        
return 0    
else:        
return x relu_function(7), relu_function(-7)

輸出:

(7, 0)
我們來看看ReLU函式的梯度。
f'(x) = 1, x>=0      
= 0, x<0

深度學習基礎——啟用函式以及什麼時候使用它們?(附程式碼)

如果你觀察圖形的負方向,你會注意到梯度值是零。由於這個原因,在反向傳播過程中,一些神經元權重和偏差沒有更新。這可能會產生從未被啟用的死亡神經元這種情況可透過“洩漏”ReLU函式來處理。
  • Leaky 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)
輸出:
(7, -0.07)
除了Leaky ReLU,還有一些其他的ReLU變體,最流行的是Parameterised ReLU函式和Exponential Liner Unit。
  • Parameterised ReLU

這是ReLU的另一個變體,旨在解決軸的左半部分的梯度為零的問題。顧名思義,引數化ReLU引入了一個新引數作為函式負部分的斜率。下面是如何修改ReLU函式以體現包含的斜率引數-
f(x) = x, x>=0    
= ax, x<0

深度學習基礎——啟用函式以及什麼時候使用它們?(附程式碼)

當a的值固定為0.01時,函式就變成了Leaky ReLU函式。然而,對於Parameterised ReLU函式,‘a’也是一個可訓練的引數。該網路還學習了' a '的值,以便更快、更優地收斂

這個函式的導數和Leaky ReLu函式是一樣的,除了0.01的值會被替換成a的值。
f'(x) = 1, x>=0       
= a, x<0

當使用Leaky ReLU函式仍然不能解決未啟用神經元問題,相關資訊無法成功傳遞到下一層時,我們就可以使用Parameterised ReLU函式。
  • Exponential Linear Unit

指數化線性單元(簡稱ELU)也是線性整流單元(ReLU)的一種變體,它改變了函式負部分的斜率。與Leaky Relu和parametric Relu函式不同,ELU使用了Log曲線來代替直線定義函式的負數部分。它被定義為
f(x) = x,   x>=0    
= a(e^x-1), x<0

深度學習基礎——啟用函式以及什麼時候使用它們?(附程式碼)

讓我們在python中定義這個函式:
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是一個不太為人所知的啟用函式,它是由谷歌的研究人員發現的。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

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=blog

l 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?

相關文章