Pytorch-自动微分模块

简介: PyTorch的torch.autograd模块提供了自动微分功能,用于深度学习中的梯度计算。它包括自定义操作的函数、构建计算图、数值梯度检查、错误检测模式和梯度模式设置等组件。张量通过设置`requires_grad=True`来追踪计算,`backward()`用于反向传播计算梯度,`grad`属性存储张量的梯度。示例展示了如何计算标量和向量张量的梯度,并通过`torch.no_grad()`等方法控制梯度计算。在优化过程中,梯度用于更新模型参数。注意,使用numpy转换要求先`detach()`以避免影响计算图。

🥇接下来我们进入到Pytorch的自动微分模块torch.autograd~


自动微分模块是PyTorch中用于实现张量自动求导的模块。PyTorch通过torch.autograd模块提供了自动微分的功能,这对于深度学习和优化问题至关重要,因为它可以自动计算梯度,无需手动编写求导代码。torch.autograd模块的一些关键组成部分:


  1. 函数的反向传播:torch.autograd.function 包含了一系列用于定义自定义操作的函数,这些操作可以在反向传播时自动计算梯度。
  2. 计算图的反向传播:torch.autograd.functional 提供了一种构建计算图并自动进行反向传播的方式,这类似于其他框架中的符号式自动微分。
  3. 数值梯度检查:torch.autograd.gradcheck 用于检查数值梯度与自动微分得到的梯度是否一致,这是确保正确性的一个有用工具。
  4. 错误检测模式:torch.autograd.anomaly_mode 在自动求导时检测错误产生路径,有助于调试。
  5. 梯度模式设置:torch.autograd.grad_mode 允许用户设置是否需要梯度,例如在模型评估时通常不需要计算梯度。
  6. 求导方法:PyTorch提供backward()和torch.autograd.grad()两种求梯度的方法。backward()会将梯度填充到叶子节点的.grad字段,而torch.autograd.grad()直接返回梯度结果。
  7. requires_grad属性:在创建张量时,可以通过设置requires_grad=True来指定该张量是否需要进行梯度计算。这样在执行操作时,PyTorch会自动跟踪这些张量的计算过程,以便后续进行梯度计算。


梯度基本计算


def func1():
    x = torch.tensor(10, requires_grad=True, dtype=torch.float64)
    f = x ** 2 +10
    # 自动微分求导
    f.backward()   # 反向求导
    # backward 函数计算的梯度值会存储在张量的 grad 变量中
    print(x.grad)
def func2():
    x = torch.tensor([10, 20, 30, 40], requires_grad=True, dtype=torch.float64)
    # 变量经过中间计算
    f1 = x ** 2 + 10
    
    # f2 = f1.mean()  # 平均损失,相当于每个值/4
    f2 = f1.sum()  # 求和损失,相当于每个值*1
    f2.backward()
    print(x.grad)
def func3():
    x1 = torch.tensor(10, requires_grad=True, dtype=torch.float64)
    x2 = torch.tensor(20, requires_grad=True, dtype=torch.float64)
    y = x1 ** 2 + x2 ** 2 + x1 * x2
    y = y.sum()
    y.backward()
    print(x1.grad, x2.grad)
 
def func4():
    x1 = torch.tensor([10, 20], requires_grad=True, dtype=torch.float64)
    x2 = torch.tensor([30, 40], requires_grad=True, dtype=torch.float64)
 
    y = x1 ** 2 + x2 ** 2 + x1 * x2
    y = y.sum()
    y.backward()
    print(x1.grad,x2.grad)


func1和func2,它们分别处理标量张量和向量张量的梯度计算。


  • 在func1中,首先创建了一个标量张量x,并设置requires_grad=True以启用自动微分。然后计算f = x ** 2 + 10,接着使用f.backward()进行反向求导。最后,通过打印x.grad输出梯度值。
  • 在func2中,首先创建了一个向量张量x,并设置requires_grad=True以启用自动微分。然后计算f1 = x ** 2 + 10,接着使用f1.sum()对向量张量进行求和操作,得到一个标量张量f2。最后,使用f2.backward()进行反向求导。
  • func3和func4分别求多个标量和向量的情况,与上面相似。



控制梯度计算


我们可以通过一些方法使 requires_grad=True 的张量在某些时候计算时不进行梯度计算。


  1. 第一种方式是使用torch.no_grad()上下文管理器,在这个上下文中进行的所有操作都不会计算梯度。
  2. 第二种方式是通过装饰器@torch.no_grad()来装饰一个函数,使得这个函数中的所有操作都不会计算梯度。
  3. 第三种方式是通过torch.set_grad_enabled(False)来全局关闭梯度计算功能,之后的所有操作都不会计算梯度,直到下一次再次调用此方法torch.set_grad_enabled(True)开启梯度计算功能。


x = torch.tensor(10, requires_grad=True, dtype=torch.float64)
print(x.requires_grad)
 
# 第一种方式: 对代码进行装饰
with torch.no_grad():
    y = x ** 2
print(y.requires_grad)
 
# 第二种方式: 对函数进行装饰
@torch.no_grad()
def my_func(x):
    return x ** 2
print(my_func(x).requires_grad)
 
 
# 第三种方式
torch.set_grad_enabled(False)
y = x ** 2
print(y.requires_grad)


默认张量的 grad 属性会累计历史梯度值,如果需要重复计算每次的梯度,就需要手动清除。


x = torch.tensor([10, 20, 30, 40], requires_grad=True, dtype=torch.float64)
 
for _ in range(3):
 
    f1 = x ** 2 + 20
    f2 = f1.mean()
 
    if x.grad is not None:
        x.grad.data.zero_()   # 本身来改动
 
    f2.backward()
    print(x.grad)


x.grad不是x,因为x是一个tensor张量,而x.grad是x的梯度。在PyTorch中,张量的梯度是通过自动求导机制计算得到的,而不是直接等于张量本身。



梯度下降优化最优解

x = torch.tensor(10, requires_grad=True, dtype=torch.float64)
 
for _ in range(5000):
 
     
    f = x ** 2
 
    # 梯度清零
    if x.grad is not None:
        x.grad.data.zero_()
 
    # 反向传播计算梯度
    f.backward()
 
    # 更新参数
    x.data = x.data - 0.001 * x.grad
 
    print('%.10f' % x.data)


更新参数相当于通过学习率对当前数值进行迭代。


f.backward()是PyTorch中自动梯度计算的函数,用于计算张量`f`关于其所有可学习参数的梯度。在这个例子中,`f`是一个标量张量,它只有一个可学习参数`x`。当调用f.backward()`时,PyTorch会自动计算`f`关于`x`的梯度,并将结果存储在`x.grad`中。这样,我们就可以使用这个梯度来更新`x`的值,以便最小化损失函数`f`。


梯度计算注意


当对设置 requires_grad=True 的张量使用 numpy 函数进行转换时, 会出现如下报错:


Can't call numpy() on Tensor that requires grad. Use tensor.detach().numpy() instead.


此时, 需要先使用 detach 函数将张量进行分离, 再使用 numpy 函数。detach 之后会产生一个新的张量, 新的张量作为叶子结点,并且该张量和原来的张量共享数据, 但是分离后的张量不需要计算梯度。

import torch
 
def func1():
 
    x = torch.tensor([10, 20], requires_grad=True, dtype=torch.float64)
 
    # Can't call numpy() on Tensor that requires grad. Use tensor.detach().numpy() instead.
    # print(x.numpy())  # 错
    print(x.detach().numpy())  
 
 
def func2():
 
    x1 = torch.tensor([10, 20], requires_grad=True, dtype=torch.float64)
 
    # x2 作为叶子结点
    x2 = x1.detach()
 
    # 两个张量的值一样: 140421811165776 140421811165776
    print(id(x1.data), id(x2.data))
    x2.data = torch.tensor([100, 200])
    print(x1)
    print(x2)
 
    # x2 不会自动计算梯度: False
    print(x2.requires_grad)
相关文章
|
4月前
|
机器学习/深度学习 数据可视化 PyTorch
PyTorch基础之模型保存与重载模块、可视化模块讲解(附源码)
PyTorch基础之模型保存与重载模块、可视化模块讲解(附源码)
98 1
|
4月前
|
机器学习/深度学习 PyTorch 算法框架/工具
PyTorch基础之网络模块torch.nn中函数和模板类的使用详解(附源码)
PyTorch基础之网络模块torch.nn中函数和模板类的使用详解(附源码)
363 0
|
4月前
|
机器学习/深度学习 PyTorch 算法框架/工具
PyTorch基础之激活函数模块中Sigmoid、Tanh、ReLU、LeakyReLU函数讲解(附源码)
PyTorch基础之激活函数模块中Sigmoid、Tanh、ReLU、LeakyReLU函数讲解(附源码)
220 0
|
4月前
|
数据采集 PyTorch 算法框架/工具
PyTorch基础之数据模块Dataset、DataLoader用法详解(附源码)
PyTorch基础之数据模块Dataset、DataLoader用法详解(附源码)
851 0
|
4月前
|
机器学习/深度学习 PyTorch 算法框架/工具
PyTorch基础之张量模块数据类型、基本操作、与Numpy数组的操作详解(附源码 简单全面)
PyTorch基础之张量模块数据类型、基本操作、与Numpy数组的操作详解(附源码 简单全面)
62 0
|
22天前
|
机器学习/深度学习 PyTorch 数据处理
PyTorch数据处理:torch.utils.data模块的7个核心函数详解
在机器学习和深度学习项目中,数据处理是至关重要的一环。PyTorch作为一个强大的深度学习框架,提供了多种灵活且高效的数据处理工具
17 1
|
4月前
|
机器学习/深度学习 算法 PyTorch
深入理解PyTorch自动微分:反向传播原理与实现
【4月更文挑战第17天】本文深入解析PyTorch的自动微分机制,重点讨论反向传播的原理和实现。反向传播利用链式法则计算神经网络的梯度,包括前向传播、梯度计算、反向传播及参数更新。PyTorch通过`autograd`模块实现自动微分,使用`Tensor`和计算图记录操作历史以自动计算梯度。通过示例展示了如何在PyTorch中创建张量、定义计算过程及求梯度。掌握这些有助于提升深度学习模型的训练效率。
|
4月前
|
机器学习/深度学习 自然语言处理 PyTorch
Pytorch图像处理注意力机制SENet CBAM ECA模块解读
注意力机制最初是为了解决自然语言处理(NLP)任务中的问题而提出的,它使得模型能够在处理序列数据时动态地关注不同位置的信息。随后,注意力机制被引入到图像处理任务中,为深度学习模型提供了更加灵活和有效的信息提取能力。注意力机制的核心思想是根据输入数据的不同部分,动态地调整模型的注意力,从而更加关注对当前任务有用的信息。
283 0
|
4月前
|
机器学习/深度学习 传感器 算法
PyTorch基础之优化器模块、训练和测试模块讲解(附源码)
PyTorch基础之优化器模块、训练和测试模块讲解(附源码)
119 0
|
25天前
|
机器学习/深度学习 PyTorch 编译器
PyTorch 与 TorchScript:模型的序列化与加速
【8月更文第27天】PyTorch 是一个非常流行的深度学习框架,它以其灵活性和易用性而著称。然而,当涉及到模型的部署和性能优化时,PyTorch 的动态计算图可能会带来一些挑战。为了解决这些问题,PyTorch 引入了 TorchScript,这是一个用于序列化和优化 PyTorch 模型的工具。本文将详细介绍如何使用 TorchScript 来序列化 PyTorch 模型以及如何加速模型的执行。
34 4