TF2.0 GradientTape()類講解

概述

GradientTape()是一個Class, 其Methods有batch_jacobian, gradient, jacobian, reset, stop_recording, watch, watched_variables;
本文主要介紹其 gradient Method 的用法

用法

tensorflow.GradientTape API 會根據某個函數的輸入變量來計算它的導數。Tensorflow 會把 ‘tensorflow.GradientTape’ 上下文中執行的所有操作都記錄在一個磁帶上 (“tape”)。 然後基於這個磁帶和每次操作產生的導數,用反向微分法(“reverse mode differentiation”)來計算這些被“記錄在案”的函數的導數。

舉個小例子

接下來我們求函數f(x)=10*(x**2) - 4*x在梯度等於零的時候x的值(這個單變量的函數,其實可以理解爲梯度就是其導數)

import tensorflow as tf

定義這個函數

def f(x):
    return 10*(x**2) - 4*x

求梯度接近0的時候x變量的值

# 定義學習率
lr=0.01
# x可以理解爲可訓練的變量,初始化爲0.
x=tf.Variable(0.0)

#循環500次
for _ in range(500):
    with tf.GradientTape() as tape:
    	#函數輸出
        y=f(x)
    #根據函數的輸出以及變量求出梯度
    dy_dx=tape.gradient(y,x)
    #根據梯度更新變量值
    x.assign_sub(lr * dy_dx)

print(x.numpy())
#輸出:
#0.19999997

分析:本例中原函數是f(x)=10 * (x ** 2) - 4 * x;其梯度函數(導函數)是20 * x + 4;令20 * x + 4=0,可求得x=0.2,可以看到於0.19999997於2很接近。

進階例子

上面的例子的函數的係數是固定的(10和4),接下來舉一個係數變化的例子,做最簡單的模型訓練模型。
設g(a, x)=a*(x**2+x),我們把g(a, x)看成是一個模型,其中a是輸入,x是變量

def g(a,x):
    return a*(x**2+x)

這裏我們設定一個最終訓練好的函數,假設我們最終想把x值訓練成4,那麼我們有:(這個函數用來幫我們獲取標籤,用來計算損失值)

def G(a):
    return a*(4**2+4)

開始訓練

import random
#定義學習率
lr=0.01
#初始化變量
x=tf.Variable(0.0)
#優化器使用Adam
optimizer = tf.keras.optimizers.Adam(lr=lr)

for _ in range(500):
	#隨機獲取輸入
    inputs = random.randint(1,255)
    #把輸入傳入G(a)函數獲取標籤,用來計算損失值
    targets= G(inputs)
    with tf.GradientTape() as tape:
    	#模型的預測輸出
        predicts=g(inputs,x)
        #損失值等於預測值與真實值的差的絕對值
        loss=abs(predicts-targets)
    #根據loss值以及變量x求梯度
    gradient=tape.gradient(loss,x)
    #優化器根據梯度,學習率等更新變量x的值
    optimizer.apply_gradients([(gradient, x)])
    if _%100==0:
        print('Loss:',loss.numpy())
print('x:',x.numpy())

運行輸出:

Loss: 1480.0
Loss: 2206.015
Loss: 2872.3086
Loss: 56.464996
Loss: 1.564209
x: 3.9994457

分析:我們可以看到,500輪之後,x變量值爲3.9994457,與我們之前設定的4很接近。大家可以把x換成其他值試試,也可以換個優化器試試。

拓展昇華

通過上面兩個例子,想必大家已經能夠想象出模型訓練的步驟了,接下來就讓我們,寫一個訓練一個step的代碼吧,代碼中的my_modelmy_lossmy_optimizer,就是平時我們的模型,損失函數,以及優化器,想看實戰可以看這篇文章TF2.0模型訓練中的自定義訓練

def train_per_step(inputs, targets):
    with tf.GradientTape() as tape:
        #輸入傳入模型得到輸出
        predicts  = my_model(inputs)
        #模型輸出的預測值與目標值通過損失函數計算出loss值
        loss_value= my_loss(targets, predicts)
        #根據loss值求的梯度(我們希望loss-->0)
    gradients = tape.gradient(loss_value, my_model.trainable_variables)  
    #把梯度和變量進行綁定
    grads_and_vars = zip(gradients, my_model.trainable_variables)  
    #優化器更新變量的值(使得進一步loss-->0)
    my_optimizer.apply_gradients(grads_and_vars)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章