pytorch 深度学习之自动微分

深度学习框架通过自动计算导数,即自动微分(automatic differentiation)来加快求导。 实际中,根据我们设计的模型,系统会构建一个计算图(computational graph), 来跟踪计算是哪些数据通过哪些操作组合起来产生输出。 自动微分使系统能够随后反向传播梯度。 这里,反向传播(backpropagate)意味着跟踪整个计算图,填充关于每个参数的偏导数。

例如,相对 (y = 2{x^T}x) 关于向量 (x) 求导,首先创建一个变量 (x) 并为其分配一个初始值:

import torch

x = torch.arange(4.0)
x
tensor([0., 1., 2., 3.])

需要一个地方来存储渐变。重要的是,我们不能在每次派生参数时都分配新的内存。因为我们经常数千次更新相同的参数,所以每次分配新的内存都会很快耗尽内存。请注意,标量函数相对于向量(x)的梯度是向量,其形状与(x)相同。

[En]

A place is needed to store gradients. It is important that we do not allocate new memory each time we derive a parameter. Because we often update the same parameters thousands of times, allocating new memory each time can quickly run out of memory. Note that the gradient of a scalar function with respect to the vector (x) is a vector and has the same shape as (x).

x.requires_grad_(True)  # 等价于x=torch.arange(4.0,requires_grad=True)
x.grad  # 默认值是None
y = 2 * torch.dot(x,x)
y
tensor(28., grad_fn=<mulbackward0>)
</mulbackward0>

(x) 是一个长度为 4 的向量,计算 (x) 和 (x) 的点积,得到了我们赋值给y的标量输出。 接下来,我们通过调用反向传播函数来自动计算 (y) 关于 (x) 每个分量的梯度,并打印这些梯度:

y.backward()
x.grad
tensor([ 0.,  4.,  8., 12.])

函数 (y = 2{x^T}x) 关于 (x) 的梯度应该是 (4x),验证:

x.grad == 4 * x
tensor([True, True, True, True])
tensor([1., 1., 1., 1.])

当 (y) 不是标量时,向量 (y) 关于向量 (x) 的导数的最自然解释是一个矩阵。对于高阶和高维的 (y) 和 (x),求导的结果可以是一个高阶张量。

# 对非标量调用backward需要传入一个gradient参数,该参数指定微分函数关于self的梯度。
# 在我们的例子中,我们只想求偏导数的和,所以传递一个1的梯度是合适的
x.grad.zero_()
y = x * x
# 等价于y.backward(torch.ones(len(x)))
y.sum().backward()
x.grad
tensor([0., 2., 4., 6.])

假设 (y) 是作为 (x) 的函数计算的,而 (z) 则是作为 (y) 和 (x) 的函数计算的。 想象一下,我们想计算 (z) 关于 (x) 的梯度,但由于某种原因,我们希望将 (y) 视为一个常数, 并且只考虑到 (x) 在 (y) 被计算后发挥的作用。
在这里,我们可以分离 (y) 来返回一个新变量 (u),该变量与 (y) 具有相同的值,但丢弃计算图中如何计算 (y) 的任何信息。 换句话说,梯度不会向后流经 (u) 到 (x)。 因此,下面的反向传播函数计算 (z=ux) 关于 (x) 的偏导数,同时将 (u) 作为常数处理, 而不是 (z=xx*x) 关于 (x) 的偏导数。

x.grad.zero_()
y = x * x
u = y.detach();
z = u * x

z.sum().backward()
x.grad == u
tensor([True, True, True, True])

由于记录了 (y) 的计算结果,我们可以随后在 (y) 上调用反向传播, 得到 (y=xx) 关于的 (x) 的导数,即 (2x)。

x.grad.zero_()
y.sum().backward()
x.grad == 2 * x
tensor([True, True, True, True])

在下面的代码中,while 循环的迭代次数和 if 语句的结果都取决于输入 a 的值:

def f(a):
    b = a * 2
    while b.norm() < 1000:
        b *= 2
    if b.sum() > 0:
        c = b
    else:
        c = 100 * b

    return c

a = torch.randn(size=(),requires_grad=True)
d = f(a)
d.backward()

a.grad == d / a
tensor(True)

Original: https://www.cnblogs.com/xiaojianliu/p/16160210.html
Author: 6小贱
Title: pytorch 深度学习之自动微分

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/7249/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

免费咨询
免费咨询
扫码关注
扫码关注
联系站长

站长Johngo!

大数据和算法重度研究者!

持续产出大数据、算法、LeetCode干货,以及业界好资源!

2022012703491714

微信来撩,免费咨询:xiaozhu_tec

分享本页
返回顶部