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