Tensorflow導數梯度相關

導數與梯度

不知道的同學可以再回去看看數學,其實數學還是很有用的。

在高中階段,我們就接觸到導數(Derivative)的概念,它被定義爲自變量𝑥產生一個微小 擾動∆𝑥後,函數輸出值的增量∆𝑦與自變量增量∆𝑥的比值在∆𝑥趨於 0 時的極限𝑎。

導數本身沒有方向,偏導數本身也沒有方向。

考慮本質上爲多元函數的神經網絡模型,比如 shape 爲[784, 256]的權值矩陣𝑾,它包 含了784 × 256個連接權值𝑤,我們需要求出784 × 256個偏導數。需要注意的是,在數學 表達習慣中,一般要討論的自變量記爲𝒙,但是在神經網絡中,𝒙一般用來表示輸入,比如 圖片、文本、語音數據等,網絡的自變量是網絡參數集𝜃 = {𝑤1, 𝑏1, 𝑤2, 𝑏2, ⋯ }。利用梯度下 降算法優化網絡時,需要求出網絡的所有偏導數。因此,我們關心的也是誤差函數輸出L 沿着自變量𝜃𝑖方向上的導數,即L對網絡參數𝜃𝑖的偏導數。

 

梯度的方向表示函數值上升最快的方向,梯度的反向則表示函數值下降最快的方向。

通過梯度下降算法並不能保證得到全局最優解,這主要是目標函數的非凸性造成的。 考慮非凸函數,深藍色區域爲極小值區域,不同的優化軌跡可能得到不同的最優數 值解,這些數值解並不一定是全局最優解。

 

 

神經網絡的模型表達式通常非常複雜,模型參數量可達千萬、數億級別,幾乎所有的 神經網絡的優化問題都是依賴於深度學習框架去自動計算網絡參數的梯度,然後採用梯度 下降算法循環迭代優化網絡的參數直至性能滿足需求。深度學習這裏主要依賴的就是反向傳播算法和梯度下降算法。

常用導數性質大家可以參考數學。

損失函數梯度?

import tensorflow as tf 
# 構建待優化變量
x = tf.constant(1.)
w1 = tf.constant(2.)
b1 = tf.constant(1.)
w2 = tf.constant(2.)
b2 = tf.constant(1.)
# 構建梯度記錄器
with tf.GradientTape(persistent=True) as tape:
    # 非 tf.Variable 類型的張量需要人爲設置記錄梯度信息 
    tape.watch([w1, b1, w2, b2])
    # 構建2層線性網絡 
    y1 = x * w1 + b1 
    y2 = y1 * w2 + b2
    
    dy2_dy1 = tape.gradient(y2, [y1])[0] 
    dy1_dw1 = tape.gradient(y1, [w1])[0] 
    dy2_dw1 = tape.gradient(y2, [w1])[0]

不同的初始狀態對梯度下降算法有影響

全連接層、激活函數層、池化層、卷積層、循環神經網絡層層類,只需要在創建時指定網絡層的相關參數,並調用__call__方法即可完成前向計算。在 調用__call__方法時,Keras 會自動調用每個層的前向傳播邏輯,這些邏輯一般實現在類的 call 函數中。

網絡容器

對於常見的網絡,需要手動調用每一層的類實例完成前向傳播運算,當網絡層數變得 較深時,這一部分代碼顯得非常臃腫。可以通過 Keras 提供的網絡容器 Sequential 將多個 網絡層封裝成一個大網絡模型,只需要調用網絡模型的實例一次即可完成數據從第一層到 最末層的順序傳播運算。

在完成網絡創建 時,網絡層類並沒有創建內部權值張量等成員變量,此時通過調用類的 build 方法並指定 輸入大小,即可自動創建所有層的內部張量。通過 summary()函數可以方便打印出網絡結 構和參數量。

可以看到 Layer 列爲每層的名字,這個名字由 TensorFlow 內部維護,與 Python 的對象名並 不一樣。Param#列爲層的參數個數,Total params 項統計出了總的參數量,Trainable params 爲總的待優化參數量,Non-trainable params 爲總的不需要優化的參數量。讀者可以簡單驗 證一下參數量的計算結果。

當我們通過 Sequential 容量封裝多個網絡層時,每層的參數列表將會自動併入 Sequential 容器的參數列表中,不需要人爲合併網絡參數列表,這也是 Sequential 容器的便 捷之處。Sequential 對象的 trainable_variables 和 variables 包含了所有層的待優化張量列表 和全部張量列表

# 打印網絡的待優化參數名與shape
for p in model.trainable_variables: 
    print(p.name, p.shape) # 參數名和形狀

dense_3/kernel:0 (9, 64)
dense_3/bias:0 (64,)
dense_4/kernel:0 (64, 64)
dense_4/bias:0 (64,)
dense_5/kernel:0 (64, 1)
dense_5/bias:0 (1,)

        在訓練網絡時,一般的流程是通過前向計算獲得網絡的輸出值,再通過損失函數計算 網絡誤差,然後通過自動求導工具計算梯度並更新,同時間隔性地測試網絡的性能。對於 這種常用的訓練邏輯,可以直接通過 Keras 提供的模型裝配與訓練等高層接口實現,簡潔 清晰。

在 Keras 中,有 2 個比較特殊的類:keras.Model 和 keras.layers.Layer 類。其中 Layer 類是網絡層的母類,定義了網絡層的一些常見功能,如添加權值、管理權值列表等。 Model 類是網絡的母類,除了具有 Layer 類的功能,還添加了保存模型、加載模型、訓練 與測試模型等便捷功能。Sequential 也是 Model 的子類,因此具有 Model 類的所有功能。

損失函數也有模塊:

# 導入優化器,損失函數模塊
from tensorflow.keras import optimizers,losses 
# 模型裝配
# 採用Adam優化器,學習率爲0.01;採用交叉熵損失函數,包含Softmax network.compile(optimizer=optimizers.Adam(lr=0.01),
    loss=losses.CategoricalCrossentropy(from_logits=True),
    metrics=['accuracy'] # 設置測量指標爲準確率 
)

模型訓練

模型裝配完成後,即可通過 fit()函數送入待訓練的數據集和驗證用的數據集,這一步

稱爲模型訓練。例如:

# 指定訓練集爲train_db,驗證集爲val_db,訓練5個epochs,每2個epoch驗證一次 # 返回訓練軌跡信息保存在history對象中
history = network.fit(train_db, epochs=5, validation_data=val_db, validation_freq=2)

history.history

第八章好好看一下

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

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