1. sigmod函數
函數公式和圖表如下圖


在sigmod函數中我們可以看到,其輸出是在(0,1)這個開區間內,這點很有意思,可以聯想到概率,但是嚴格意義上講,不要當成概率。sigmod函數曾經是比較流行的,它可以想象成一個神經元的放電率,在中間斜率比較大的地方是神經元的敏感區,在兩邊斜率很平緩的地方是神經元的抑制區。
當然,流行也是曾經流行,這說明函數本身是有一定的缺陷的。
1) 當輸入稍微遠離了坐標原點,函數的梯度就變得很小了,幾乎為零。在神經網絡反向傳播的過程中,我們都是通過微分的鏈式法則來計算各個權重w的微分的。當反向傳播經過了sigmod函數,這個鏈條上的微分就很小很小了,況且還可能經過很多個sigmod函數,最后會導致權重w對損失函數幾乎沒影響,這樣不利於權重的優化,這個問題叫做梯度飽和,也可以叫梯度彌散。
2) 函數輸出不是以0為中心的,這樣會使權重更新效率降低。對於這個缺陷,在斯坦福的課程里面有詳細的解釋。
3) sigmod函數要進行指數運算,這個對於計算機來說是比較慢的。
2.tanh函數
tanh函數公式和曲線如下

tanh是雙曲正切函數,tanh函數和sigmod函數的曲線是比較相近的,咱們來比較一下看看。首先相同的是,這兩個函數在輸入很大或是很小的時候,輸出都幾乎平滑,梯度很小,不利於權重更新;不同的是輸出區間,tanh的輸出區間是在(-1,1)之間,而且整個函數是以0為中心的,這個特點比sigmod的好。
一般二分類問題中,隱藏層用tanh函數,輸出層用sigmod函數。不過這些也都不是一成不變的,具體使用什么激活函數,還是要根據具體的問題來具體分析,還是要靠調試的。
3.ReLU函數
ReLU函數公式和曲線如下

ReLU(Rectified Linear Unit)函數是目前比較火的一個激活函數,相比於sigmod函數和tanh函數,它有以下幾個優點:
1) 在輸入為正數的時候,不存在梯度飽和問題。
2) 計算速度要快很多。ReLU函數只有線性關系,不管是前向傳播還是反向傳播,都比sigmod和tanh要快很多。(sigmod和tanh要計算指數,計算速度會比較慢)
當然,缺點也是有的:
1) 當輸入是負數的時候,ReLU是完全不被激活的,這就表明一旦輸入到了負數,ReLU就會死掉。這樣在前向傳播過程中,還不算什么問題,有的區域是敏感的,有的是不敏感的。但是到了反向傳播過程中,輸入負數,梯度就會完全到0,這個和sigmod函數、tanh函數有一樣的問題。
2) 我們發現ReLU函數的輸出要么是0,要么是正數,這也就是說,ReLU函數也不是以0為中心的函數。
4.ELU函數
ELU函數公式和曲線如下圖


ELU函數是針對ReLU函數的一個改進型,相比於ReLU函數,在輸入為負數的情況下,是有一定的輸出的,而且這部分輸出還具有一定的抗干擾能力。這樣可以消除ReLU死掉的問題,不過還是有梯度飽和和指數運算的問題。
5.PReLU函數
PReLU函數公式和曲線如下圖


PReLU也是針對ReLU的一個改進型,在負數區域內,PReLU有一個很小的斜率,這樣也可以避免ReLU死掉的問題。相比於ELU,PReLU在負數區域內是線性運算,斜率雖然小,但是不會趨於0,這算是一定的優勢吧。
我們看PReLU的公式,里面的參數α一般是取0~1之間的數,而且一般還是比較小的,如零點零幾。當α=0.01時,我們叫PReLU為Leaky ReLU,算是PReLU的一種特殊情況吧。
總體來看,這些激活函數都有自己的優點和缺點,沒有一條說法表明哪些就是不行,哪些激活函數就是好的,所有的好壞都要自己去實驗中得到。
畫出激勵函數的代碼如下
import torch from torch.autograd import Variable import matplotlib.pyplot as plt import torch.nn.functional as F x= torch.linspace(-5,5,200) x= Variable(x) x_np=x.data.numpy() y_relu = torch.relu(x).data.numpy() y_sigmoid =torch.sigmoid(x).data.numpy() y_tanh = torch.tanh(x).data.numpy() y_softplus = F.softplus(x).data.numpy() plt.figure(1,figsize=(8,6)) plt.subplot(221) plt.plot(x_np,y_relu,c='red',label='relu') plt.ylim(-1,5) plt.legend(loc='best') plt.subplot(222) plt.plot(x_np,y_sigmoid,c='red',label='sigmoid') plt.ylim(-0.2,1.2) plt.legend(loc='best') plt.subplot(223) plt.plot(x_np,y_tanh,c='red',label='tanh') plt.ylim(-1.2,1.2) plt.legend(loc='best') plt.subplot(224) plt.plot(x_np,y_softplus,c='red',label='softplus') plt.ylim(-0.2,6) plt.legend(loc='best') plt.show()