文章首發於我的 github 倉庫-cv演算法工程師成長之路,歡迎關注我的公眾號-嵌入式視覺。
本文分析了啟用函式對於神經網路的必要性,同時講解了幾種常見的啟用函式的原理,並給出相關公式、程式碼和示例圖。
啟用函式概述
前言
人工神經元(Artificial Neuron),簡稱神經元(Neuron),是構成神經網路的基本單元,其主要是模擬生物神經元的結構和特性,接收一組輸入訊號併產生輸出。生物神經元與人工神經元的對比圖如下所示。
從機器學習的角度來看,神經網路其實就是一個非線性模型,其基本組成單元為具有非線性啟用函式的神經元,透過大量神經元之間的連線,使得多層神經網路成為一種高度非線性的模型。神經元之間的連線權重就是需要學習的引數,其可以在機器學習的框架下透過梯度下降方法來進行學習。
啟用函式定義
啟用函式(也稱“非線性對映函式”),是深度卷積神經網路模型中必不可少的網路層。
假設一個神經元接收 \(D\) 個輸入 \(x_1, x_2,⋯, x_D\),令向量 \(x = [x_1;x_2;⋯;x_?]\) 來表示這組輸入,並用淨輸入(Net Input) \(z \in \mathbb{R}\) 表示一個神經元所獲得的輸入訊號 \(x\) 的加權和:
其中 \(w = [w_1;w_2;⋯;w_?]\in \mathbb{R}^D\) 是 \(D\) 維的權重矩陣,\(b \in \mathbb{R}\) 是偏置向量。
以上公式其實就是帶有偏置項的線性變換(類似於放射變換),本質上還是屬於線形模型。為了轉換成非線性模型,我們在淨輸入 \(z\) 後新增一個非線性函式 \(f\)(即啟用函式)。
由此,典型的神經元結構如下所示:
啟用函式性質
為了增強網路的表示能力和學習能力,啟用函式需要具備以下幾點性質:
- 連續並可導(允許少數點上不可導)的非線性函式。可導的啟用函式 可以直接利用數值最佳化的方法來學習網路引數。
- 啟用函式及其導函式要儘可能的簡單,有利於提高網路計算效率。
- 啟用函式的導函式的值域要在一個合適的區間內,不能太大也不能太小,否則會影響訓練的效率和穩定性.
Sigmoid 型函式
Sigmoid 型函式是指一類 S 型曲線函式,為兩端飽和函式。常用的 Sigmoid 型函式有 Logistic 函式和 Tanh 函式。
相關數學知識: 對於函式 \(f(x)\),若 \(x \to −\infty\) 時,其導數 \({f}'\to 0\),則稱其為左飽和。若 \(x \to +\infty\) 時,其導數 \({f}'\to 0\),則稱其為右飽和。當同時滿足左、右飽和時,就稱為兩端飽和。
Sigmoid 函式
對於一個定義域在 \(\mathbb{R}\) 中的輸入,sigmoid
函式將輸入變換為區間 (0, 1)
上的輸出(sigmoid 函式常記作 \(\sigma(x)\)):
sigmoid 函式的導數公式如下所示:
sigmoid 函式及其導數影像如下所示:
注意,當輸入為 0 時,sigmoid 函式的導數達到最大值 0.25; 而輸入在任一方向上越遠離 0 點時,導數越接近 0
。
sigmoid
函式在隱藏層中已經較少使用,其被更簡單、更容易訓練的 ReLU 啟用函式所替代。
當我們想要輸出二分類或多分類、多標籤問題的機率時,sigmoid
可用作模型最後一層的啟用函式。下表總結了常見問題型別的最後一層啟用和損失函式。
問題型別 | 最後一層啟用 | 損失函式 |
---|---|---|
二分類問題(binary) | sigmoid |
sigmoid + nn.BCELoss (): 模型最後一層需要經過 torch.sigmoid 函式 |
多分類、單標籤問題(Multiclass) | softmax |
nn.CrossEntropyLoss() : 無需手動做 softmax |
多分類、多標籤問題(Multilabel) | sigmoid |
sigmoid + nn.BCELoss() : 模型最後一層需要經過 sigmoid 函式 |
nn.BCEWithLogitsLoss()
函式等效於sigmoid + nn.BCELoss
。
Tanh 函式
Tanh
(雙曲正切)函式也是一種 Sigmoid 型函式,可以看作放大並平移 Sigmoid 函式,其能將其輸入壓縮轉換到區間 (-1, 1)
上。公式如下所示:
Sigmoid 函式和 Tanh 函式曲線如下圖所示:
兩種啟用函式實現和視覺化程式碼如下所示:
# example plot for the sigmoid activation function
from math import exp
from matplotlib import pyplot
import matplotlib.pyplot as plt
# sigmoid activation function
def sigmoid(x):
"""1.0 / (1.0 + exp(-x))
"""
return 1.0 / (1.0 + exp(-x))
def tanh(x):
"""2 * sigmoid(2*x) - 1
(e^x – e^-x) / (e^x + e^-x)
"""
# return (exp(x) - exp(-x)) / (exp(x) + exp(-x))
return 2 * sigmoid(2*x) - 1
def relu(x):
return max(0, x)
def gradient_relu(x):
if x < 0:
return 0
else:
return 1
def gradient_sigmoid(x):
"""sigmoid(x)(1−sigmoid(x))
"""
a = sigmoid(x)
b = 1 - a
return a*b
# 1, define input data
inputs = [x for x in range(-10, 11)]
# 2, calculate outputs
outputs = [sigmoid(x) for x in inputs]
outputs2 = [tanh(x) for x in inputs]
# 3, plot sigmoid and tanh function curve
plt.figure(dpi=90) # dpi 設定
plt.style.use('ggplot') # 主題設定
plt.subplot(1, 2, 1) # 繪製子圖
plt.plot(inputs, outputs, label='sigmoid')
plt.plot(inputs, outputs2, label='tanh')
plt.xlabel("x") # 設定 x 軸標籤
plt.ylabel("y")
plt.title('sigmoid and tanh') # 折線圖示題
plt.legend()
plt.show()
另外一種 Logistic 函式和 Tanh 函式的形狀對比圖:
來源: 《神經網路與深度學習》圖4.2。
Logistic 函式和 Tanh 函式都是 Sigmoid 型函式,具有飽和性,但是計算開銷較大。因為這兩個函式都是在中間(0 附近)近似線性,兩端飽和。因此,這兩個函式可以透過分段函式來近似。
ReLU 函式及其變體
ReLU 函式
ReLU
(Rectified Linear Unit,修正線性單元),是目前深度神經網路中最經常使用的啟用函式。公式如下所示:
以上公式通俗理解就是,ReLU
函式僅保留正元素並丟棄所有負元素。
1,優點:
ReLU
啟用函式計算簡單;- 具有很好的稀疏性,大約 50% 的神經元會處於啟用狀態。
- 函式在 \(x > 0\) 時導數為 1 的性質(左飽和函式),在一定程度上緩解了神經網路的梯度消失問題,加速梯度下降的收斂速度。
相關生物知識: 人腦中在同一時刻大概只有 1% ∼ 4% 的神經元處於活躍 狀態。
2,缺點:
- ReLU 函式的輸出是非零中心化的,給後一層的神經網路引入偏置偏移,會影響梯度下降的效率。
- ReLU 神經元在訓練時比較容易“死亡”。如果神經元引數值在一次不恰當的更新後,其值小於 0,那麼這個神經元自身引數的梯度永遠都會是 0,在以後的訓練過程中永遠不能被啟用,這種現象被稱作“死區”。
ReLU 啟用函式的程式碼定義如下:
# pytorch 框架對應函式: nn.ReLU(inplace=True)
def relu(x):
return max(0, x)
ReLU 啟用函式及其函式梯度圖如下所示:
Leaky ReLU/PReLU/ELU/Softplus 函式
1,Leaky ReLU
函式: 為了緩解“死區”現象,研究者將 ReLU 函式中 \(x < 0\) 的部分調整為 \(\gamma \cdot x\), 其中 \(\gamma\) 常設定為 0.01 或 0.001 數量級的較小正數。這種新型的啟用函式被稱作帶洩露的 ReLU(Leaky ReLU
)。
2,PReLU 函式: 為了解決 Leaky ReLU 中超引數 \(\gamma\) 不易設定的問題,有研究者提出了引數化 ReLU(Parametric ReLU,PReLU
)。引數化 ReLU 直接將 \(\gamma\) 也作為一個網路中可學習的變數融入模型的整體訓練過程。對於第 \(i\) 個神經元,PReLU
的 定義為:
3,ELU
函式: 2016 年,Clevert
等人提出了 ELU
(Exponential Linear Unit,指數線性單元),它是一個近似的零中心化的非線性函式。ELU 具備 ReLU 函式的優點,同時也解決了 ReLU 函式的“死區”問題,但是,其指數操作也增加了計算量。 \(\gamma ≥ 0\) 是一個超引數,決定 \(x ≤ 0\) 時的飽和曲線,並調整輸出均值在 0
附近。ELU
定義為:
4,Softplus
函式: Softplus 函式其導數剛好是 Logistic 函式.Softplus 函式雖然也具有單側抑制、寬 興奮邊界的特性,卻沒有稀疏啟用性。Softplus
定義為:
注意: ReLU 函式變體有很多,但是實際模型當中使用最多的還是 ReLU
函式本身。
ReLU、Leaky ReLU、ELU 以及 Softplus 函式示意圖如下圖所示:
Swish 函式
Swish
函式[Ramachandran et al., 2017] 是一種自門控(Self-Gated)啟用 函式,定義為
其中 \(\sigma(\cdot)\) 為 Logistic 函式,\(\beta\) 為可學習的引數或一個固定超引數。\(\sigma(\cdot) \in (0, 1)\) 可以看作一種軟性的門控機制。當 \(\sigma(\beta x)\) 接近於 1
時,門處於“開”狀態,啟用函式的輸出近似於 \(x\) 本身;當 \(\sigma(\beta x)\) 接近於 0
時,門的狀態為“關”,啟用函式的輸出近似於 0
。
Swish
函式程式碼定義如下,結合前面的畫曲線程式碼,可得 Swish 函式的示例圖。
def swish(x, beta = 0):
"""beta 是需要手動設定的引數"""
return x * sigmoid(beta*x)
Swish 函式可以看作線性函式和 ReLU 函式之間的非線性插值函式,其程度由引數 \(\beta\) 控制。
啟用函式總結
常用的啟用函式包括 ReLU
函式、sigmoid
函式和 tanh
函式。下表彙總比較了幾個啟用函式的屬性:
參考資料
- Pytorch分類問題中的交叉熵損失函式使用
- 《解析卷積神經網路-第8章》
- 《神經網路與深度學習-第4章》
- How to Choose an Activation Function for Deep Learning