1. 程式人生 > >tensorflow中常用的啟用函式

tensorflow中常用的啟用函式

啟用函式(activation function)執行時啟用神經網路中某一部分神經元,將啟用神經元的資訊輸入到下一層神經網路中。神經網路之所以能處理非線性問題,這歸功於啟用函式的非線性表達能力。啟用函式需要滿足資料的輸入和輸出都是可微的,因為在進行反向傳播的時候,需要對啟用函式求導。

在TensorFlow中也內建了許多的啟用函式,安裝好TensorFlow之後可以在tensorflow-->python-->ops-->nn.py檔案中看到啟用函式

接下來主要介紹一些常用的啟用函式如:sigmoid、tanh、relu、dropout等。

1、sigmoid啟用函式

sigmoid函式也被稱為S型函式,它可以將整個實數區間對映到(0,1)區間,因此經常被用來計算概率,它也是在傳統神經網路中被經常使用的一種啟用函式。

    x = tf.constant([[-1,-2],[3,4],[5,6]],dtype=tf.float32)
    sess = tf.Session()
    print(sess.run(tf.sigmoid(x)))

sigmoid啟用函式的優點:輸出的對映區間(0,1)內單調連續,非常適合用作輸出層,並且比較容易求導。

sigmoid啟用函式的缺點:它具有軟飽和性,即當輸入x趨向於無窮的時候,它的導數會趨於0,導致很容易產生梯度消失。

  • log_sigmoid函式:對sigmoid函式求log,它將整個實數區間對映到了(負無窮,0)
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt

if __name__ == "__main__":
    x = tf.constant(np.arange(-10,10),dtype=tf.float32)
    sess = tf.Session()
    y = sess.run(tf.log_sigmoid(x))
    print(y)
    plt.plot(np.arange(-10,10),y)
    plt.show()

2、tanh啟用函式

tanh是雙曲正切函式,它將整個實數區間對映到了(-1,1),tanh函式也具有軟飽和性。它的輸出是以0為中心,tanh的收斂速度比sigmoid要快,由於存在軟飽和性,所以tanh也存在梯度消失的問題。

    x = tf.constant(np.arange(-10,10),dtype=tf.float32)
    sess = tf.Session()
    y = sess.run(tf.tanh(x))
    print(y)
    plt.plot(np.arange(-10,10),y)
    plt.show()

3、relu啟用函式

relu啟用函式現在是最受歡迎的啟用函式,經常被使用在神經網路中。relu函式的定義:f(x)=max(x,0)

    x = tf.constant(np.arange(-10,10),dtype=tf.float32)
    sess = tf.Session()
    y = sess.run(tf.nn.relu(x))
    print(y)
    plt.plot(np.arange(-10,10),y)
    plt.show()

relu函式在x<0時,輸出始終為0。由於x>0時,relu函式的導數為1,所以relu函式能夠在x>0時保持梯度不斷衰減,從而緩解梯度消失的問題,還能加快收斂速度,還能是神經網路具有稀疏性表達能力,這也是relu啟用函式能夠被使用在深層神經網路中的原因。由於當x<0時,relu函式的導數為0,導致對應的權重無法更新,這樣的神經元被稱為"神經元死亡"。

在TensorFlow中還包括了relu函式的擴充套件函式如:relu6和crelu,除此之外還有leaky relu、PRelu、RRelu等。

  • relu6啟用函式:定義min(max(features,0),6),也就是說它的取值區間被限定在了[0,6]之間。
    x = tf.constant(np.arange(-10,10),dtype=tf.float32)
    sess = tf.Session()
    y = sess.run(tf.nn.relu6(x))
    print(y)
    plt.plot(np.arange(-10,10),y)
    plt.show()

  • crelu啟用函式:定義為[relu(x),relu(-x)]相對於relu(x),crelu的輸出會增加一倍。
    x = tf.constant(np.arange(-10,10),dtype=tf.float32)
    sess = tf.Session()
    y = sess.run(tf.nn.crelu(x))
    print(y)

  • softplus啟用函式:定義為log((e^x)+1),被稱為平滑的relu。
    x = tf.constant(np.arange(-10,10),dtype=tf.float32)
    sess = tf.Session()
    y = sess.run(tf.nn.softplus(x))
    print(y)
    plt.plot(np.arange(-10,10),y)
    plt.show()

  • leak_relu啟用函式:leak_relu啟用函式會給x<0,一個斜率,而不是將所有x<0都輸出0,預設斜率是0.2,x>0的部分仍然輸出是x,即斜率為1,保持不變。
    x = tf.constant(np.arange(-10,10),dtype=tf.float32)
    sess = tf.Session()
    y = sess.run(tf.nn.leaky_relu(x,alpha=0.2))
    print(y)
    plt.plot(np.arange(-10,10),y)
    plt.show()

4、dropout函式

dropout函式會以一個概率為keep_prob來決定神經元是否被抑制。如果被抑制,該神經元輸出為0,如果不被抑制則該神經元的輸出為輸入的1/keep_probbe倍,每個神經元是否會被抑制是相互獨立的。神經元是否被抑制還可以通過調節noise_shape來調節,當noise_shape[i] == shape(x)[i],x中的元素是相互獨立的。如果shape(x)=[k,l,m,n](k表示資料的個數,l表示資料的行數,m表示資料的列,n表示通道),當noise_shape=[k,1,1,n],表示資料的個數與通道是相互獨立的,但是與資料的行和列是有關聯的,即要麼都為0,要麼都為輸入的1/keep_prob倍。

    x = tf.constant(np.array([np.arange(-5,5)]),dtype=tf.float32)
    sess = tf.Session()
    #元素之間互不干擾
    y = sess.run(tf.nn.dropout(x,keep_prob=0.5))
    print(y)
    #元素之間互不干擾
    y = sess.run(tf.nn.dropout(x,keep_prob=0.5,noise_shape=[1,10]))
    print(y)
    #元素之間存在關聯
    y = sess.run(tf.nn.dropout(x,keep_prob=0.5,noise_shape=[1]))
    print(y)