1. 程式人生 > >演算法工程師修仙之路:TensorFlow(六)

演算法工程師修仙之路:TensorFlow(六)

TensorFlow 入門

TensorFlow實現神經網路


神經網路引數與 TensorFlow 變數

  • 在 TensorFlow 中,變數(tf.Variable)的作用就是儲存和更新神經網路中的引數。

  • 和其他程式語言類似,TensorFlow中的變數也需要指定初始值。因為在神經網路中,給引數賦予隨機初始值最為常見,所以一般也使用隨機數給 TensorFlow 中的變數初始化。

    # 宣告一個2*3的矩陣變數
    weights = tf.Variable(tf.random_normal([2, 3], stddev=2.0))
    
    • 這段程式碼呼叫了 TensorFlow 變數的宣告函式 tf.Variable。
    • 在變數宣告函式中給出了初始化這個變數的方法。
    • tf.random_normal([2, 3], stddev=2)會產生一個 2 3 2*3 的矩 陣,矩陣中的元素是均值為0,標準差為2的隨機數。
    • tf.random_normal 函式可以通過引數 mean 來指定平均值,在沒有指定時預設為0。
  • TensorFlow 中變數的初始值可以設定成隨機數、常數或者是通過其他變數的初始值計算得到。

  • 通過滿足正態分佈的隨機數來初始化神經網路中的引數是一個非常常用的方法,除了正態分佈的隨機數,TensorFlow 還提供了一些其他的隨機數生成器:
    在這裡插入圖片描述

  • TensorFlow 也支援通過常數來初始化一個變數:
    在這裡插入圖片描述

  • 在神經網路中,偏置項(bias)通常會使用常數來設定初始值。

    biases = tf.Variable(tf.zeros([3]))     # 生成一個初始值全部為0且長度為3的變數。
    
  • 除了使用隨機數或者常數,TensorFlow 也支援通過其他變數的初始值來初始化新的變數。

    # w2的初始值被設定成了與weights變數相同。
    w2 = tf.Variable(weights.initialized_value())   
    # w3的初始值則是weights初始值的兩倍。    
    w3 = tf.Variable(weights.initialized_value() * 2.0)    
    
  • 在 TensorFlow 中,一個變數的值在被使用之前,這個變數的初始化過程需要被明確地呼叫。

  • 通過變數實現神經網路的引數並實現前向傳播:

    import tensorflow as tf 
    
    """ 
    宣告wl、w2兩個變數。這裡還通過seed引數設定了隨機種子,
    這樣可以保證每次執行得到的結果是一樣的。 
    """
    
    """ 
    當聲明瞭變數wl、w2之後,可以通過wl和w2來定義神經網路的前向傳播過程並得到中間結果a和最後答案y。
    定義wl、w2, a和y的過程對應了TensorFlow程式的第一步。
    這一步定義了TensorFlow計算圖中所有的計算,但這些被定義的計算在這一步中並不真正地執行。
    當需要執行這些計算並得到具體數字時,需要進入TensorFlow程式的第二步。 
    """
    
    w1 = tf.Variable(tf.random_normal([2, 3], stddev=1, seed=1))
    w2 = tf.Variable(tf.random_normal([3, 1], stddev=1, seed=1))
    
    # 暫時將輸入的特徵向量定義為一個常量。注意這裡x是一個1*2的矩陣。
    x = tf.constant([[0.7, 0.9]])
    
    # 通過前向傳播演算法獲得神經網路的輸出。
    a = tf.matmul(x, w1)
    y = tf.matmul(a, w2)
    
    """ 
    在TensorFlow程式的第二步會宣告一個會話(session),並通過會話計算結果。
    當會話定義完成之後就可以開始真正執行定義好的計算了。
    但在計算y之前,需要將所有用到的變數初始化。
    也就是說,雖然在變數定義時給出了變數初始化的方法,但這個方法並沒有被真正執行。
    所以在計算y之前,需要通過執行w1.initializer和w2.initializer來給變數賦值。 
    """
    
    sess = tf.Session()
    
    # 第一種方法,不主張
    """ 
    這裡不能直接通過sess.run(y)來獲取y的取值,
    因為wl和w2都還沒有執行初始化過程。
    以下兩行分別初始化了wl和w2兩個變數。 
    sess.run(w1.initializer)      # 初始化w1。
    sess.run(w2.initializer)      # 初始化w2。 
    """
    
    # 第二種方法,常用
    init_op = tf.global_variables_initializer()
    sess.run(init_op)
    
    # 輸出[[ 3.95757794]]。
    print(sess.run(y))
    sess.close()
    
    • 雖然方法一直接呼叫每個變數的初始化過程是一個可行的方案,但是當變數數目增多,或者變數之間存在依賴關係時,單個呼叫的方案就比較麻煩了。
    • 為了解決這個問題, TensorFlow 提供了一種更加便捷的方法二來完成變數初始化過程。通過 tf.global_variables_initializer 函式,就不需要將變數一個一個初始化了。這個函式也會自動處理變數之間的依賴關係。
  • 在 TensorFlow 中,變數的宣告函式 tf.Variable 是一個運算,這個運算的輸出結果就是一個張量,這個張量也就是變數,所以變數只是一種特殊的張量。

  • 通過 tf.global_variables()函式可以拿到當前計算圖上所有的變數。

    • 拿到計算圖上所有的變數有助於持久化整個計算圖的執行狀態。
    • 當構建機器學習模型時,比如神經網路,可以通過變數宣告函式中的 trainable 引數來區分需要優化的引數(比如神經網路中的引數)和其他引數(比如迭代的輪數)。
    • 如果宣告變數時引數 trainable 為 True ,那麼這個變數將會被加入到GraphKeys.TRAINABLE_VARJABLES 集合。
    • 在 TensorFlow 中可以通過 tf.trainable_variables函式得到所有需要優化的引數。
    • TensorFlow 中提供的神經網路優化演算法會將GraphKeys.TRAINABLE_VARIABLES 集合中的變數作為預設的優化物件。
  • 類似張量,維度(shape)和型別 (type)也是變數最重要的兩個屬性。和大部分程式語言類似,變數的型別是不可改變的。一個變數在構建之後,它的型別就不能再改變了。維度是變數另一個重要的屬性。和型別不大一樣的是,維度在程式執行中是有可能改變的,但是需要通過設定引數 validate_shape=False。雖然 TensorFlow 支援更改變數的維度,但是這種用法在實踐中比較罕見。