当前位置: 首页 > ai >正文

自动微分模块

一.前言

本章节我们是要学习梯队计算,⾃动微分(Autograd)模块对张量做了进⼀步的封装,具有⾃动求导功能。⾃动微分模块是构成神经⽹络 训练的必要模块,在神经⽹络的反向传播过程中,Autograd 模块基于正向计算的结果对当前的参数进⾏微 分计算,从⽽实现⽹络权重参数的更新。

二.梯度基本计算

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

import torch# 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)# 2. 单向量梯度的计算# y = x**2 + 20def 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   2x/4# ⾃动微分f2.backward()# 打印 x 变量的梯度print(x.grad)if __name__ == '__main__':test01()test02()

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

三.控制梯度计算 

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

import torch# 1. 控制不计算梯度
def test01():x = torch.tensor(10, requires_grad=True, dtype=torch.float64)print(x.requires_grad)# 第⼀种⽅式: 对代码进⾏装饰with torch.no_grad():y = x ** 2print(y.requires_grad)# 第⼆种⽅式: 对函数进⾏装饰@torch.no_grad()def my_func(x):return x ** 2print(my_func(x).requires_grad)# 第三种⽅式torch.set_grad_enabled(False)y = x ** 2print(y.requires_grad)# 2. 注意: 累计梯度
def test02():# 定义需要求导张量x = torch.tensor([10, 20, 30, 40], requires_grad=True, dtype=torch.float64)for _ in range(3):f1 = x ** 2 + 20f2 = f1.mean()# 默认张量的 grad 属性会累计历史梯度值# 所以, 需要我们每次⼿动清理上次的梯度# 注意: ⼀开始梯度不存在, 需要做判断if x.grad is not None:x.grad.data.zero_()f2.backward()print(x.grad)# 3. 梯度下降优化最优解
def test03():# y = x**2x = 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.gradprint('%.10f' % x.data)if __name__ == '__main__':test01()# print('--------------------')# test02()# print('--------------------')# test03()

这里得分开打印,就不在展示结果了,大家打印一下看看。

四.梯度计算注意

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

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

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

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

import torch# 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())  # 正确# 2. detach 前后张量共享内存
def test02():x1 = torch.tensor([10, 20], requires_grad=True, dtype=torch.float64)# x2 作为叶⼦结点x2 = x1.detach()# 两个张量的值⼀样: 140421811165776 140421811165776print(id(x1.data), id(x2.data))x2.data = torch.tensor([100, 200])print(x1)print(x2)# x2 不会⾃动计算梯度: Falseprint(x2.requires_grad)if __name__ == '__main__':test01()test02()

结果展示: 

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

五.总结 

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

http://www.xdnf.cn/news/15373.html

相关文章:

  • JAR 包冲突排雷指南:原理、现象与 Maven 一站式解决
  • 机载激光雷达目标识别:从点云到凝视成像的算法全景
  • Datawhale AI夏令营——用户新增预测挑战赛
  • xss-lab靶场通关
  • 苦练Python第18天:Python异常处理锦囊
  • 从 JSON 到 Python 对象:一次通透的序列化与反序列化之旅
  • 云原生技术与应用-Containerd容器技术详解
  • Android系统的问题分析笔记 - Android上的调试方式 bugreport
  • RAG索引流程中的文档解析:工业级实践方案与最佳实践
  • iOS —— 网易云仿写
  • 大数据系列之:通过trino查询hive表
  • 直播推流技术底层逻辑详解与私有化实现方案-以rmtp rtc hls为例-优雅草卓伊凡
  • 在Linux下git的使用
  • 量子计算新突破!阿里“太章3.0”实现512量子比特模拟(2025中国量子算力巅峰)
  • MYOJ_8512:CSP初赛题单1:计算机常识
  • 计算机网络通信的相关知识总结
  • Linux进程优先级机制深度解析:从Nice值到实时调度
  • 图机器学习(1)——图论基础
  • Django Admin 配置详解
  • 【C语言进阶】指针面试题详解(2)
  • 玩转Docker | 使用Docker部署TeamMapper思维导图应用程序
  • 使⽤Pytorch构建⼀个神经⽹络
  • Android Studio C++/JNI/Kotlin 示例 三
  • IDEA实现纯java项目并打包jar(不使用Maven,Spring)
  • Bash vs PowerShell | 从 CMD 到跨平台工具:Bash 与 PowerShell 的全方位对比
  • 单片机(STM32-串口通信)
  • 名片管理系统IV
  • 位置编码类型彩色图解
  • android Perfetto cpu分析教程及案例
  • (5)LangGraph4j框架ReActAgent实现