《30天吃掉那只 TensorFlow2.0》 2-3 自动微分机制

简介: 《30天吃掉那只 TensorFlow2.0》 2-3 自动微分机制

2-3 自动微分机制


网络异常,图片无法展示
|

神经网络通常依赖反向传播求梯度来更新网络参数,求梯度过程通常是一件非常复杂而容易出错的事情。


而深度学习框架可以帮助我们自动地完成这种求梯度运算。


Tensorflow一般使用梯度磁带tf.GradientTape来记录正向运算过程,然后反播磁带自动得到梯度值。


这种利用tf.GradientTape求微分的方法叫做Tensorflow的自动微分机制。


一,利用梯度磁带求导数


首先我们可以求以下二次函数的导数


image.png


首先设置


image.png

import tensorflow as tf
import numpy as np 
# f(x) = a*x**2 + b*x + c的导数
x = tf.Variable(0.0,name = "x",dtype = tf.float32)
a = tf.constant(1.0)
b = tf.constant(-2.0)
c = tf.constant(1.0)
with tf.GradientTape() as tape:
    y = a*tf.pow(x,2) + b*x + c
dy_dx = tape.gradient(y,x)
print(dy_dx)


然后求 x = 0  的时候的导数,这时候导数打印出来了,和我们计算的一样,就是-2

tf.Tensor(-2.0, shape=(), dtype=float32)

对张量求导


对常量张量也可以求导,需要增加watch

# 对常量张量也可以求导,需要增加watch
with tf.GradientTape() as tape:
    tape.watch([a,b,c])
    y = a*tf.pow(x,2) + b*x + c
dy_dx,dy_da,dy_db,dy_dc = tape.gradient(y,[x,a,b,c])
print(dy_da)
print(dy_dc)
tf.Tensor(0.0, shape=(), dtype=float32)
tf.Tensor(1.0, shape=(), dtype=float32)

求二阶导数


其次,我们也可以求二阶导数

# 可以求二阶导数
with tf.GradientTape() as tape2:
    with tf.GradientTape() as tape1:   
        y = a*tf.pow(x,2) + b*x + c
    dy_dx = tape1.gradient(y,x)   
dy2_dx2 = tape2.gradient(dy_dx,x)
print(dy2_dx2)
tf.Tensor(2.0, shape=(), dtype=float32)
# 可以在autograph中使用
@tf.function
def f(x):   
    a = tf.constant(1.0)
    b = tf.constant(-2.0)
    c = tf.constant(1.0)
    # 自变量转换成tf.float32
    x = tf.cast(x,tf.float32)
    with tf.GradientTape() as tape:
        tape.watch(x)
        y = a*tf.pow(x,2)+b*x+c
    dy_dx = tape.gradient(y,x) 
    return((dy_dx,y))
tf.print(f(tf.constant(0.0)))
tf.print(f(tf.constant(1.0)))
(-2, 1)
(0, 0)


二,利用梯度磁带和优化器求最小值


首先我们可以求以下二次函数的最小值


image.png


首先设置


image.png

我们用SGD进行一个梯度下降,寻找我们的最小值,由于二次函数是一个凸函数,所以我们很容易就能得到我们的结果,最小值为0,大约在x=x = 0.999998569取得

# 求f(x) = a*x**2 + b*x + c的最小值
# 使用optimizer.apply_gradients
x = tf.Variable(0.0,name = "x",dtype = tf.float32)
a = tf.constant(1.0)
b = tf.constant(-2.0)
c = tf.constant(1.0)
optimizer = tf.keras.optimizers.SGD(learning_rate=0.01)
for _ in range(1000):
    with tf.GradientTape() as tape:
        y = a*tf.pow(x,2) + b*x + c
    dy_dx = tape.gradient(y,x)
    optimizer.apply_gradients(grads_and_vars=[(dy_dx,x)])
tf.print("y =",y,"; x =",x)
y = 0 ; x = 0.999998569

我们还可以使用optimizer.minimize,optimizer.minimize相当于先用tape求gradient,再apply_gradient

# 求f(x) = a*x**2 + b*x + c的最小值
# 使用optimizer.minimize
# optimizer.minimize相当于先用tape求gradient,再apply_gradient
x = tf.Variable(0.0,name = "x",dtype = tf.float32)
#注意f()无参数
def f():   
    a = tf.constant(1.0)
    b = tf.constant(-2.0)
    c = tf.constant(1.0)
    y = a*tf.pow(x,2)+b*x+c
    return(y)
optimizer = tf.keras.optimizers.SGD(learning_rate=0.01)   
for _ in range(1000):
    optimizer.minimize(f,[x])   
tf.print("y =",f(),"; x =",x)
y = 0 ; x = 0.999998569

我们还可以在autograph中完成最小值求解,使用optimizer.apply_gradients

# 在autograph中完成最小值求解
# 使用optimizer.apply_gradients
x = tf.Variable(0.0,name = "x",dtype = tf.float32)
optimizer = tf.keras.optimizers.SGD(learning_rate=0.01)
@tf.function
def minimizef():
    a = tf.constant(1.0)
    b = tf.constant(-2.0)
    c = tf.constant(1.0)
    for _ in tf.range(1000): #注意autograph时使用tf.range(1000)而不是range(1000)
        with tf.GradientTape() as tape:
            y = a*tf.pow(x,2) + b*x + c
        dy_dx = tape.gradient(y,x)
        optimizer.apply_gradients(grads_and_vars=[(dy_dx,x)])
    y = a*tf.pow(x,2) + b*x + c
    return y
tf.print(minimizef())
tf.print(x)
0
0.999998569

在autograph中完成最小值求解,使用optimizer.minimize

# 在autograph中完成最小值求解
# 使用optimizer.minimize
x = tf.Variable(0.0,name = "x",dtype = tf.float32)
optimizer = tf.keras.optimizers.SGD(learning_rate=0.01)   
@tf.function
def f():   
    a = tf.constant(1.0)
    b = tf.constant(-2.0)
    c = tf.constant(1.0)
    y = a*tf.pow(x,2)+b*x+c
    return(y)
@tf.function
def train(epoch):  
    for _ in tf.range(epoch):  
        optimizer.minimize(f,[x])
    return(f())
tf.print(train(1000))
tf.print(x)
0
0.999998569


相关文章
|
7月前
|
机器学习/深度学习 算法 PyTorch
Pytorch自动求导机制详解
在深度学习中,我们通常需要训练一个模型来最小化损失函数。这个过程可以通过梯度下降等优化算法来实现。梯度是函数在某一点上的变化率,可以告诉我们如何调整模型的参数以使损失函数最小化。自动求导是一种计算梯度的技术,它允许我们在定义模型时不需要手动推导梯度计算公式。PyTorch 提供了自动求导的功能,使得梯度的计算变得非常简单和高效。
142 0
|
2月前
|
机器学习/深度学习 PyTorch 算法框架/工具
探索PyTorch:自动微分模块
探索PyTorch:自动微分模块
|
4月前
|
机器学习/深度学习 PyTorch 算法框架/工具
PyTorch中的自动微分机制:深入理解反向传播
【8月更文第27天】PyTorch 是一个强大的机器学习框架,它因其灵活性和易用性而受到广泛欢迎。其中一个关键特性就是它的自动微分机制,这个机制使得 PyTorch 能够自动计算任何张量操作的梯度,这对于训练深度学习模型至关重要。本文将详细介绍 PyTorch 中自动微分机制的工作原理,并通过具体的代码示例来展示如何使用这一机制来实现反向传播。
285 1
|
6月前
|
机器学习/深度学习 存储 PyTorch
Pytorch-自动微分模块
PyTorch的torch.autograd模块提供了自动微分功能,用于深度学习中的梯度计算。它包括自定义操作的函数、构建计算图、数值梯度检查、错误检测模式和梯度模式设置等组件。张量通过设置`requires_grad=True`来追踪计算,`backward()`用于反向传播计算梯度,`grad`属性存储张量的梯度。示例展示了如何计算标量和向量张量的梯度,并通过`torch.no_grad()`等方法控制梯度计算。在优化过程中,梯度用于更新模型参数。注意,使用numpy转换要求先`detach()`以避免影响计算图。
|
7月前
|
机器学习/深度学习 算法 TensorFlow
TensorFlow的自动微分与梯度下降
【4月更文挑战第17天】本文探讨了TensorFlow中的自动微分和梯度下降在机器学习模型优化中的作用。自动微分通过计算图实现,简化了深度学习模型中梯度的计算。TensorFlow利用`tf.GradientTape`进行反向传播以求梯度。梯度下降算法用于更新参数,`tf.train.GradientDescentOptimizer`是实现这一过程的一种方式。此外,TensorFlow还提供了其他优化器以提升性能。理解这些概念有助于更有效地构建和优化机器学习模型。
|
7月前
|
机器学习/深度学习 算法 PyTorch
深入理解PyTorch自动微分:反向传播原理与实现
【4月更文挑战第17天】本文深入解析PyTorch的自动微分机制,重点讨论反向传播的原理和实现。反向传播利用链式法则计算神经网络的梯度,包括前向传播、梯度计算、反向传播及参数更新。PyTorch通过`autograd`模块实现自动微分,使用`Tensor`和计算图记录操作历史以自动计算梯度。通过示例展示了如何在PyTorch中创建张量、定义计算过程及求梯度。掌握这些有助于提升深度学习模型的训练效率。
|
7月前
|
机器学习/深度学习 存储 算法
PyTorch 中的自动求导
PyTorch 中的自动求导
38 0
|
7月前
|
机器学习/深度学习 PyTorch 算法框架/工具
PyTorch深度学习基础之Reduction归约和自动微分操作讲解及实战(附源码 超详细必看)
PyTorch深度学习基础之Reduction归约和自动微分操作讲解及实战(附源码 超详细必看)
127 0
|
机器学习/深度学习 TensorFlow 算法框架/工具
tensorflow keras 双向lstm gru的水库水位预测 完整代码+数据 毕业设计
tensorflow keras 双向lstm gru的水库水位预测 完整代码+数据 毕业设计
109 0
|
PyTorch Serverless 算法框架/工具
Pytorch与autograd自动求导
Pytorch与autograd自动求导
86 0