【PyTorch】教程:学习基础知识-(6) Autograd

news/2023/6/7 0:57:18

AUTOMATIC DIFFERENTIATION WITH torch.autograd

在训练神经网络时,最常用的算法是反向传播算法,在该算法中,参数根据损失函数相对于给定参数的梯度进行调整。

为了计算这些梯度, PyTorch 有一个内置的微分引擎 torch.autograd 。它智慧任何计算图的梯度自动计算。

考虑最简单的单层神经网络,输入 x, 参数 w 和 b, 以及一些损失函数。 它可以在 PyTorch 中以以下方式定义:

import torch 
x = torch.ones(5) # 输入
y = torch.zeros(3) # 输出
w = torch.randn(5, 3, requires_grad=True) # 权重
b = torch.randn(3, requires_grad=True) # 偏置
z = torch.matmul(x, w) + b
loss = torch.nn.functional.binary_cross_entropy_with_logits(z, y)
print(f"loss = {loss}")
loss = 0.7214622497558594

Tensors, Functions and Computational graph

上述代码定义了以下计算图

在这里插入图片描述

这个网络中,wb 是需要优化的参数。因此,我们需要能够计算关于这些变量的损失函数的梯度。为了做到这一点,我们设置了这些 tensorrequires_grad 属性。

你可以在创建一个 tensor 时设置 requires_grad 值,也可以在以后使用时利用 x.requires_grad(True) 方法。

应用于 tensor 来构建计算图的函数实际上 function 类的一个对象,该对象知道如何前向计算,也知道在反向传播时计算导数。反向传播的引用存储在 tensor 的 grad_fn 属性中。

print(f"Gradient function for z = {z.grad_fn}")
print(f"Gradient function for loss = {loss.grad_fn}")
Gradient function for z = <AddBackward0 object at 0x00000230B70C84F0>
Gradient function for loss = <BinaryCrossEntropyWithLogitsBackward object at 0x00000230B70C8D30>

Computing Gradients

为了计算神经网络的权重参数,我们需要计算 loss function 对参数的导数。即,我们需要在给定 xxxyyy 计算 ∂loss∂w\frac{\partial loss }{\partial w}wloss∂loss∂b\frac{\partial loss }{\partial b}bloss 。为了计算这些导数,我们调用 loss.backward(), 然后从 w.gradb.grad 提取值。

loss.backward()
print(w.grad)
print(b.grad)
tensor([[0.0494, 0.0666, 0.2772],[0.0494, 0.0666, 0.2772],[0.0494, 0.0666, 0.2772],[0.0494, 0.0666, 0.2772],[0.0494, 0.0666, 0.2772]])
tensor([0.0494, 0.0666, 0.2772])

我们只能获得计算图的叶节点的 grad 属性,它们的 requires_grad 属性设置为 True 。对于图中的所有其他节点,梯度将不可用。
出于性能考虑,我们只能在给定的图上反向执行一次梯度计算。如果我们需要对同一个图执行多个反向调用,我们需要将 retain_graph=True 传递给反向调用。

Disabling Gradient Tracking (不跟踪梯度)

默认情况下,所有 requires_grad=Truetensor 都在跟踪它们的计算历史并支持梯度计算。然而,有些情况下我们不需要这样做,例如,当我们训练了模型,只想对输入数据进行计算,我们只需要通过网络进行 forward 计算。我们可以用 torch.no_grad() 停止跟踪梯度计算。

z = torch.matmul(x, w) + b
print(z.requires_grad)with torch.no_grad():z = torch.matmul(x, w) + bprint(z.requires_grad)
True
False

实现相同结果的另一种方法是在 tensor 上使用 detach() 方法

z = torch.matmul(x, w) + b
z_det = z.detach()
print(z_det.requires_grad)
False

为什么要禁用梯度跟踪呢?

    1. 将神经网络中的一些参数标记为冻结参数,这是一个非常常见的场景finetuning a pretrained network
    1. 为了加速计算。因为在不跟踪梯度的 tensor 上计算会更有效。

More on Computational Graphs

从概念上讲,autograd 在一个由 Function 对象组成的有向无环图 ( DAG ) 中保存数据( tensors )和所有执行的操作( 以及由此产生的新张量 )的记录。在这个 DAG 中,叶子节点是输入 tensors ,根是输出 tensors 。通过从根到叶跟踪这个图,您可以使用链式法则自动计算梯度。

在向前传播中,autograd 同时做两件事:

  1. 根据要求的操作计算结果 tensor
  2. DAG 中维护操作的梯度函数。

当在 DAG 根上调用 .backward() 时,后向传播开始,autograd 然后

  • 从每个 .grad_fn 中计算梯度;
  • 在各自的 tensor.grad 属性中累积它们
  • 利用链式法则,一直传播到叶子 tensor

PyTorch 中的 DAG 是动态的,需要注意的一件重要的事情是,图是从头开始重新创建的,在每次 .backward() 调用之后, autograd 开始填充一个新的图。 这正是允许您在模型中使用控制流语句的原因,如果需要,您可以在每次迭代中更改形状、大小和操作等。

Optional Reading: Tensor Gradients and Jacobian Products

在很多情况下,我们有一个标量损失函数,我们需要计算关于一些参数的梯度,然后,也有输出函数是任意 tensor 的情况,在这种情况下,PyTorch 允许你计算所谓的雅克比矩阵积,而不是实际的梯度。

对于一个向量函数

y→=f(x→)\overrightarrow{y} = f(\overrightarrow{x})y=f(x) , 当 $ \overrightarrow{x}=<x_1,…x_n>$, y→=<y1,...ym>\overrightarrow{y}=<y_1,...y_m>y=<y1,...ym>, y→\overrightarrow{y}yx→\overrightarrow{x}x 的导数可以利用 Jacobian matrix (雅克比矩阵):

J=(∂y1∂x1⋯∂y1∂xn⋮⋱⋮∂ym∂x1⋯∂ym∂xn)\begin{equation*} J = \begin{pmatrix} \frac{\partial y_1}{\partial x_1} & \cdots & \frac{\partial y_1}{\partial x_n} \\ \vdots & \ddots & \vdots \\ \frac{\partial y_m}{\partial x_1} & \cdots & \frac{\partial y_m}{\partial x_n} \\ \end{pmatrix} \end{equation*} J=x1y1x1ymxny1xnym

PyTorch 允许你在给定 v=(v1,...vm)v=(v_1,...v_m)v=(v1,...vm) 向量时计算雅克比矩阵的点积 vT⋅Jv^T \cdot JvTJ, 而不是雅克比矩阵本身。可以通过 backwardvvv 作为参数而获得。vvv 的大小应该与原始的 tensor 大小相同。

inp = torch.eye(4, 5, requires_grad=True)
out = (inp+1).pow(2).t()
out.backward(torch.ones_like(out), retain_graph=True)
print(f"First call\n{inp.grad}")out.backward(torch.ones_like(out), retain_graph=True)
print(f"\nSecond call\n{inp.grad}")inp.grad.zero_()out.backward(torch.ones_like(out), retain_graph=True)
print(f"\nCall after zeroing gradients\n{inp.grad}")
First call
tensor([[4., 2., 2., 2., 2.],[2., 4., 2., 2., 2.],[2., 2., 4., 2., 2.],[2., 2., 2., 4., 2.]])Second call
tensor([[8., 4., 4., 4., 4.],[4., 8., 4., 4., 4.],[4., 4., 8., 4., 4.],[4., 4., 4., 8., 4.]])Call after zeroing gradients
tensor([[4., 2., 2., 2., 2.],[2., 4., 2., 2., 2.],[2., 2., 4., 2., 2.],[2., 2., 2., 4., 2.]])

注意: 当我们用相同的参数第二次调用 backward() 时,梯度值是不同的。这是因为在进行反向传播时,PyTorch 会累积梯度,即计算梯度的值被添加到计算图的所有叶节点的 grad 属性中,如果逆向计算合适的梯度,你需要在之前讲梯度属性归零。在现实训练中,优化器可以帮助我们做到这一点。
以前我们调用 backward() 函数时不带参数。这本质上相当于调用 backward(torch.tensor(1.0)),这是一种有用的方法,可以在标量值函数的情况下计算梯度,例如神经网络训练期间的损失。

【参考】

Automatic Differentiation with torch.autograd — PyTorch Tutorials 1.13.1+cu117 documentation

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.exyb.cn/news/show-4565596.html

如若内容造成侵权/违法违规/事实不符,请联系郑州代理记账网进行投诉反馈,一经查实,立即删除!

相关文章

随机存取 随机存储_随机存取存储器(RAM)

随机存取 随机存储In random-access memory(RAM) the memory cells can be accessed for information transfer from any desired random location. That is, the process of locating a word in memory is the same and requires an equal amount of time no matter where the…

python画三角函数--cosx

结果&#xff1a; 代码&#xff1a; import ax as ax import numpy as np import matplotlib.pyplot as mpx np.linspace(-np.pi, np.pi,1000) y np.cos(x)#设置坐标范围 mp.xlim(-np.pi-0.5,np.pi0.5) mp.ylim(-1.1,1.1)#设置刻度线 mp.xticks(np.linspace(-np.pi,np.pi,5)…

mysql 为什么说加上了索引,查询速度就快了呢?(文末附视频)

一天&#xff0c;老板跟我们提出说网站访问的速度太慢&#xff0c;要求我们尽快优化一下。我赶快去查询了一下&#xff0c;发现有几条 SQL 查询的时间异常&#xff0c;我相信这个时候很多小伙伴的大脑里浮现出来的第一个解决办法就是&#xff1a;加索引。 那么到底什么是索引呢…

图层样式探秘——等高线本质完全剖析

摘自:http://blog.sina.com.cn/s/blog_51a59b4d0100a493.html 文章早已重新整理完毕&#xff0c;只是最近一直忙于杂事&#xff0c;未能及时进行更新。汗。 投影样式中等高线: 等高线编辑器横轴从左向右意味着从外至内的距离&#xff0c;是说在不同的距离上我们输入了多少数值…

LINUX学习之文件处理常用命令(三)

ls 命令描述 ls命令是linux系统中用来列出文件和目录的常用命令&#xff0c;它可以显示文件和目录的名称、权限、大小、修改时间等信息 以下是ls命令的常用参数: -a &#xff1a;列出全部的文件&#xff0c;连同隐藏文件-d &#xff1a;仅列出文件目录&#xff0c;而不是列…

人才流动:互联网化背后的无奈---TOMsInsight 2014.10.30

人才流动&#xff1a;互联网化背后的无奈 2014-10-30 TOMsInsight北京&#xff0c;入秋&#xff0c;雾霾天及社交网络的分享&#xff0c;让大家忽略了这个三千多年六朝古都传承下来的秋悲寂寥。北京的天气如二进制码般分明&#xff1a;今天重度污染&#xff0c;明天就晴空万里。…

一个小故事(技术无关)

北 京&#xff0c;入秋&#xff0c;雾霾天及社交网络的分享&#xff0c;让大家忽略了这个三千多年六朝古都传承下来的秋悲寂寥。北京的天气如二进制码般分明&#xff1a;今天重度污染&#xff0c;明天就晴空万里。 而TMT行业也是如此&#xff0c;成王败寇&#xff1a;一方面是热…

互联网乱世之下 一将功成万骨枯

&#xff08;转自虎嗅&#xff09;北京&#xff0c;入秋&#xff0c;雾霾天及社交网络的分享&#xff0c;让大家忽略了这个三千多年六朝古都传承下来的秋悲寂寥。北京的天气如二进制码般分明&#xff1a;今天重度污染&#xff0c;明天就晴空万里。而TMT行业也是如此&#xff0c…