激活函數總結(Sigmoid、Tanh、Relu、LeakyRelu、pRelu、Elu、softplus)

1.介紹

    在深度學習網絡中,我們經常看到卷積層之後,會接一個激活函數,而現在比較常見的激活函數有Sigmoid和Relu,那麼卷積層之後,爲什麼要接一個激活函數呢?

    卷積層操作可以用y = w*x + b(其中w爲權重,b爲偏置)表示,如果我們在後面沒有接激活函數,那麼y_out = w2 * (w1 * (w0 * x + b0) + b1) + b2[假設網絡是三層],將此式子分解之後,y_out = w2 * w1 * w0 * x + w2 * w1 * b0 + w2 * b1 + b2, 當模型被訓練好之後,權重和偏置就是一個固定數,y_out 的表達式就成了一個線性表達式(y = a * x + b),很明顯,這樣的模型表達力是很弱。如果我們採樣非線性激活激活函數F,那麼y_out = F(w2 * F (w1 *F (w0 * x + b0) + b1) + b2),那麼y_out 輸出就可以幾乎模擬容易函數(中間輸出的是非線性映射值)。

 

2.激活函數特點

   深度學習前期用到的激活函數有Sigmoid和Tanh,後期有Relu、LeakyRelu、pRelu、Elu、softplus,接下來,我將一一介紹它們的特點。

Sigmoid 函數

特點:

         Sigmoid 函數可以把輸入的值映射到0到1之間,類似一種歸一化操作

缺點:

         1.容易引起梯度消失(當權重初始化爲0到1之間的時候,Sigmoid 函數梯度的最大值也就爲0.25,會導致反向傳播的時候,距離輸入層的梯度值越來越小),當然也可能發生梯度爆炸(當權重比較大的時候)

         2.Sigmoid 函數的輸出不是0均值,會導致梯度更新要不爲正,要不爲負,詳細證明參考:https://www.zhihu.com/question/50396271?from=profile_question_card,使得網絡很難收斂

         3.計算複雜,涉及到e的指數計算,而且這個函數對於硬件化也不友好

應用場所:

         將神經網絡的輸出值映射到0到1之間(乘以255就變換成了圖片RGB原始像素值範圍),作爲二分類網絡的輸出激活函數,激活函數(很少用它了)

 

Tanh 函數

特點:

        Tanh 函數可以把輸入的值映射到-1到1之間,解決掉了Sigmoid 輸出不是0均值的問題

缺點:

       1.梯度消失(爆炸)問題

       2.計算複雜,涉及到e的指數計算,而且這個函數對於硬件化也不友好

應用場所:

         gan中最後一層使用tanh(使得訓練更穩定),激活函數(很少用它了)

 

Relu函數

特點:

         解決掉了梯度消失問題(當x>0的時候,梯度始終爲1),計算速度快(判斷是否大於0就行)

缺點:

         1.Relu函數的輸出不是0均值

         2. 會產生'Dead ReLU Problem'問題,詳細證明參考:https://blog.csdn.net/disiwei1012/article/details/79204243,其實,在我們訓練網絡的時候,很少出現這種問題,所以大膽的用吧

應用場所:

        常見的激活函數,默認就選擇它吧

 

LeakyRelu與pRelu函數,當a=0.1的時候,可以畫出圖片中的內容

     pRelu與LeakyRelu的區別在於,pRelu中的參數a是一個可學習的參數,而LeakyRelu中,a是一個固定值

特點:

      LeakyRelu(pRelu)繼承了Relu所有的優點,同時也解決了'Dead ReLU Problem'問題,但實際應用中,Relu的效果沒有比它差

應用場所:

        常見的激活函數,有些時候用它,會取得不錯的效果,建議還是試一下爲好

 

Elu函數, 當a=10的時候,可以畫出圖片中的內容

特點:

      Elu繼承了Relu所有的優點,同時也解決了'Dead ReLU Problem'問題,但實際應用中,Relu的效果沒有比它差

缺點:

      1.計算複雜,涉及到e的指數計算,而且這個函數對於硬件化也不友好

應用場所:

        激活函數(感覺用的人並不多)

 

Softplus函數

特點:

      Softplus相對於Relu,是一種更加平滑的激活函數

缺點:

      1.計算複雜,涉及到e的指數計算,而且這個函數對於硬件化也不友好

應用場所:

        激活函數(對於有些輸出,需要更加平滑和連續性,會取到意想不到的結果),我建議有時收斂不了,可以試一下它

 

4.代碼實現 

import numpy as np
import matplotlib.pyplot as plt

'''
def sigmoid(x):
    return 1 / (1 + np.exp(-x))


def sigmoid_d(x):
    return sigmoid(x) * (1 - sigmoid(x))


x = np.arange(-5, 5, 0.1)
p1 = plt.subplot(211)
y = sigmoid(x)
p1.plot(x, y)
p1.set_title('sigmoid')
p1.axhline(0.5, ls='--', color='r')
p1.axvline(ls='--', color='r')

p2 = plt.subplot(212)
y = sigmoid_d(x)
p2.plot(x, y)
p2.set_title('sigmoid_d')
p2.axhline(0.5, ls='--', color='r')
p2.axvline(ls='--', color='r')
'''

'''
def tanh(x):
    return (np.exp(x) - np.exp(-x)) / (np.exp(x) + np.exp(-x))


def tanh_d(x):
    return 1-tanh(x)*tanh(x)


x = np.arange(-5, 5, 0.1)
p1 = plt.subplot(211)
y = tanh(x)
p1.plot(x, y)
p1.set_title('tanh')
p1.axhline(0.5, ls='--', color='r')
p1.axvline(ls='--', color='r')

p2 = plt.subplot(212)
y = tanh_d(x)
p2.plot(x, y)
p2.set_title('tanh_d')
p2.axhline(0.5, ls='--', color='r')
p2.axvline(ls='--', color='r')
'''




'''
def relu(x):
    return np.maximum(0, x)

def relu_d(x):
    x_d = x.copy()
    x_d[x>=0]=1
    x_d[x<0]=0
    return x_d


x = np.arange(-5, 5, 0.1)
p1 = plt.subplot(211)
y = relu(x)
p1.plot(x, y)
p1.set_title('relu')
p1.axhline(0.5, ls='--', color='r')
p1.axvline(ls='--', color='r')

p2 = plt.subplot(212)
y = relu_d(x)
p2.plot(x, y)
p2.set_title('relu_d')
p2.axhline(0.5, ls='--', color='r')
p2.axvline(ls='--', color='r')
'''

'''
def pRelu(x, a=0.1):
    return np.maximum(a*x, x)

def pRelu_d(x, a=0.1):
    x_d = x.copy()
    x_d[x>=0]=1
    x_d[x<0]=a
    return x_d


x = np.arange(-5, 5, 0.1)
p1 = plt.subplot(211)
y = pRelu(x)
p1.plot(x, y)
p1.set_title('pRelu')
p1.axhline(0.5, ls='--', color='r')
p1.axvline(ls='--', color='r')

p2 = plt.subplot(212)
y = pRelu_d(x)
p2.plot(x, y)
p2.set_title('pRelu_d')
p2.axhline(0.5, ls='--', color='r')
p2.axvline(ls='--', color='r')
'''

'''
def Elu(x, a=10):
    x_copy = x.copy()
    for i in range(x_copy.shape[0]):
        if x_copy[i] < 0:
            x_copy[i] = a * (np.exp(x_copy[i]) - 1)

    return x_copy

def Elu_d(x, a=10):
    x_copy = x.copy()
    for i in range(x_copy.shape[0]):
        if x_copy[i] < 0:
            x_copy[i] = a * (np.exp(y[i]))
        else:
            x_copy[i] = 1
    return x_copy


x = np.arange(-5, 5, 0.1)
p1 = plt.subplot(211)
y = Elu(x)
p1.plot(x, y)
p1.set_title('Elu')
p1.axhline(0.5, ls='--', color='r')
p1.axvline(ls='--', color='r')

p2 = plt.subplot(212)
y = Elu_d(x)
p2.plot(x, y)
p2.set_title('Elu_d')
p2.axhline(0.5, ls='--', color='r')
p2.axvline(ls='--', color='r')
'''


def Softplus(x):
    return np.log(1 + np.exp(x))


def Softplus_d(x):
    return 1 / (1 + np.exp(-x))


x = np.arange(-5, 5, 0.1)
p1 = plt.subplot(211)
y = Softplus(x)
p1.plot(x, y)
p1.set_title('Softplus')
p1.axhline(0.5, ls='--', color='r')
p1.axvline(ls='--', color='r')

p2 = plt.subplot(212)
y = Softplus_d(x)
p2.plot(x, y)
p2.set_title('Softplus_d')
p2.axhline(0.5, ls='--', color='r')
p2.axvline(ls='--', color='r')


plt.subplots_adjust(hspace=1)
plt.show()

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章