探索PyTorch:自动微分模块

简介: 探索PyTorch:自动微分模块

学习目标

🍀 掌握梯度计算


自动微分(Autograd)模块对张量做了进一步的封装,具有自动求导功能。自动微分模块是构成神经网络训练的必要模块,在神经网络的反向传播过程中,Autograd 模块基于正向计算的结果对当前的参数进行微分计算,从而实现网络权重参数的更新。

🍔 梯度基本计算

我们使用 backward 方法、grad 属性来实现梯度的计算和访问.

import torch

1.1 单标量梯度的计算

 

# y = x**2 + 20
    def test01():
 
     # 定义需要求导的张量
     # 张量的值类型必须是浮点类型
     x = torch.tensor(10, requires_grad=True, dtype=torch.float64)
     # 变量经过中间运算
     f = x ** 2 + 20
     # 自动微分
     f.backward()
     # 打印 x 变量的梯度
     # backward 函数计算的梯度值会存储在张量的 grad 变量中
     print(x.grad)

1.2 单向量梯度的计算

 # y = x**2 + 20
 def test02():
 
     # 定义需要求导张量
     x = torch.tensor([10, 20, 30, 40], requires_grad=True, dtype=torch.float64)
     # 变量经过中间计算
     f1 = x ** 2 + 20
 
     # 注意:
     # 由于求导的结果必须是标量
     # 而 f 的结果是: tensor([120., 420.])
     # 所以, 不能直接自动微分
     # 需要将结果计算为标量才能进行计算
     f2 = f1.mean()  # f2 = 1/2 * x
     
     # 自动微分
     f2.backward()

     # 打印 x 变量的梯度
     print(x.grad)

1.3 多标量梯度计算

 # y = x1 ** 2 + x2 ** 2 + x1*x2
 def test03():
 
     # 定义需要计算梯度的张量
     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)

1.4 多向量梯度计算

 def test04():
 
     # 定义需要计算梯度的张量
     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
     print(y)
 
     # 将输出结果变为标量
     y = y.sum()
 
     # 自动微分
     y.backward()

     # 打印两个变量的梯度
     print(x1.grad, x2.grad)
 
 
 if __name__ == '__main__':
     test04()

1.5 运行结果💯

 tensor(20., dtype=torch.float64)
 tensor([ 5., 10., 15., 20.], dtype=torch.float64)
 tensor(40., dtype=torch.float64) tensor(50., dtype=torch.float64)
 tensor([1300., 2800.], dtype=torch.float64, grad_fn=<AddBackward0>)
 tensor([50., 80.], dtype=torch.float64) tensor([ 70., 100.], dtype=torch.float64)

🍔 控制梯度计算

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

import torch

2.1 控制不计算梯度

 def test01():
 
     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)

2.2 注意: 累计梯度

 def test02():
 
     # 定义需要求导张量
     x = torch.tensor([10, 20, 30, 40], requires_grad=True, dtype=torch.float64)
 
     for _ in range(3):
 
         f1 = x ** 2 + 20
         f2 = f1.mean()
 
         # 默认张量的 grad 属性会累计历史梯度值
         # 所以, 需要我们每次手动清理上次的梯度
         # 注意: 一开始梯度不存在, 需要做判断
         if x.grad is not None:
            x.grad.data.zero_()
 
         f2.backward()
         print(x.grad)

2.3 梯度下降优化最优解

def test03():
 
    # y = x**2
    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)
 
 
if __name__ == '__main__':
    test01()
    test02()
    test03()

2.4 运行结果💯

True
False
False
False
tensor([ 5., 10., 15., 20.], dtype=torch.float64)
tensor([ 5., 10., 15., 20.], dtype=torch.float64)
tensor([ 5., 10., 15., 20.], dtype=torch.float64)

🍔 梯度计算注意

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

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

此时, 需要先使用 detach 函数将张量进行分离, 再使用 numpy 函数.

注意: detach 之后会产生一个新的张量, 新的张量作为叶子结点,并且该张量和原来的张量共享数据, 但是分离后的张量不需要计算梯度。

import torch

3.1 detach 函数用法

def test01():
 
    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())  # 正确

3.2 detach 前后张量共享内存

def test02():
 
    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)
 
 
if __name__ == '__main__':
    test01()
    test02()

3.3 运行结果💯

10. 20.]
140495634222288 140495634222288
tensor([10., 20.], dtype=torch.float64, requires_grad=True)
tensor([100, 200])
False

🍔 小节

本小节主要讲解了 PyTorch 中非常重要的自动微分模块的使用和理解。我们对需要计算梯度的张量需要设置 requires_grad=True 属性,并且需要注意的是梯度是累计的,在每次计算梯度前需要先进行梯度清零。

😀 小言在此感谢大家的支持😀

顺便问一下大佬们,最擅长使用的编程语言是什么呢~

欢迎评论区讨论哦~

相关文章
|
7月前
|
机器学习/深度学习 数据可视化 PyTorch
PyTorch基础之模型保存与重载模块、可视化模块讲解(附源码)
PyTorch基础之模型保存与重载模块、可视化模块讲解(附源码)
162 1
|
13天前
|
人工智能 PyTorch 算法框架/工具
【AI系统】动手实现 PyTorch 微分
本文介绍了使用操作符重载(OO)编程方式实现的自动微分,特别是采用反向模式(Reverse Mode)的实现方法。文中详细解释了操作符重载的基本概念及其在自动微分中的应用,以及反向模式的工作原理。通过 Python 示例代码,演示了如何手动实现类似 PyTorch 中自动微分的核心机制,包括定义 `Variable` 类、`Tape` 结构以及实现基本的数学运算符重载。最后,通过一个具体的数学函数示例展示了如何利用上述机制计算梯度,帮助读者理解反向模式自动微分的全过程。
27 1
【AI系统】动手实现 PyTorch 微分
|
2月前
|
PyTorch 算法框架/工具
Pytorch学习笔记(一):torch.cat()模块的详解
这篇博客文章详细介绍了Pytorch中的torch.cat()函数,包括其定义、使用方法和实际代码示例,用于将两个或多个张量沿着指定维度进行拼接。
106 0
Pytorch学习笔记(一):torch.cat()模块的详解
|
2月前
|
机器学习/深度学习 算法 PyTorch
Pytorch的常用模块和用途说明
肆十二在B站分享PyTorch常用模块及其用途,涵盖核心库torch、神经网络库torch.nn、优化库torch.optim、数据加载工具torch.utils.data、计算机视觉库torchvision等,适合深度学习开发者参考学习。链接:[肆十二-哔哩哔哩](https://space.bilibili.com/161240964)
55 0
|
4月前
|
机器学习/深度学习 PyTorch 数据处理
PyTorch数据处理:torch.utils.data模块的7个核心函数详解
在机器学习和深度学习项目中,数据处理是至关重要的一环。PyTorch作为一个强大的深度学习框架,提供了多种灵活且高效的数据处理工具
40 1
|
6月前
|
机器学习/深度学习 存储 PyTorch
Pytorch-自动微分模块
PyTorch的torch.autograd模块提供了自动微分功能,用于深度学习中的梯度计算。它包括自定义操作的函数、构建计算图、数值梯度检查、错误检测模式和梯度模式设置等组件。张量通过设置`requires_grad=True`来追踪计算,`backward()`用于反向传播计算梯度,`grad`属性存储张量的梯度。示例展示了如何计算标量和向量张量的梯度,并通过`torch.no_grad()`等方法控制梯度计算。在优化过程中,梯度用于更新模型参数。注意,使用numpy转换要求先`detach()`以避免影响计算图。
|
7月前
|
机器学习/深度学习 算法 PyTorch
深入理解PyTorch自动微分:反向传播原理与实现
【4月更文挑战第17天】本文深入解析PyTorch的自动微分机制,重点讨论反向传播的原理和实现。反向传播利用链式法则计算神经网络的梯度,包括前向传播、梯度计算、反向传播及参数更新。PyTorch通过`autograd`模块实现自动微分,使用`Tensor`和计算图记录操作历史以自动计算梯度。通过示例展示了如何在PyTorch中创建张量、定义计算过程及求梯度。掌握这些有助于提升深度学习模型的训练效率。
|
7月前
|
机器学习/深度学习 自然语言处理 PyTorch
Pytorch图像处理注意力机制SENet CBAM ECA模块解读
注意力机制最初是为了解决自然语言处理(NLP)任务中的问题而提出的,它使得模型能够在处理序列数据时动态地关注不同位置的信息。随后,注意力机制被引入到图像处理任务中,为深度学习模型提供了更加灵活和有效的信息提取能力。注意力机制的核心思想是根据输入数据的不同部分,动态地调整模型的注意力,从而更加关注对当前任务有用的信息。
382 0
|
7月前
|
机器学习/深度学习 传感器 算法
PyTorch基础之优化器模块、训练和测试模块讲解(附源码)
PyTorch基础之优化器模块、训练和测试模块讲解(附源码)
165 0
|
2月前
|
算法 PyTorch 算法框架/工具
Pytorch学习笔记(九):Pytorch模型的FLOPs、模型参数量等信息输出(torchstat、thop、ptflops、torchsummary)
本文介绍了如何使用torchstat、thop、ptflops和torchsummary等工具来计算Pytorch模型的FLOPs、模型参数量等信息。
363 2
下一篇
DataWorks