【Pytorch 学习笔记(二)】:AUTOGRAD相关

AUTOGRAD 相关

AUTOGRAD 包是pytorch中和神经网络关系最为密切的一部分。它可以为基于tensor的的所有操作提供自动微分的功能。它是一个在运行时定义(define-by-run)的框架,这意味着其中的反向传播是根据代码如何运行来决定的,并且每次迭代可以是不同的。

Tensor

torch.Tensor是该包中最主要的一个class。如果我们设置其属性.requires_grad = True,则torch会追踪到对该tensor上的所有操作(operation)。当计算结束后,可以通过.backward()来自动计算所有的梯度。对这个tensor的梯度会累加在.grad中。

如果想避免一个张量受历史数据的影响,可以通过.detach()来将其从计算图历史中分开,以避免之后的计算被追踪。

为了防止追踪历史(且占用内存),我们可以将代码包装在with torch.no_grad():中,这样很有效。因为在评估模型时,模型中可能会包含requires_grad = True的可训练参数,但我们可能并不需要其梯度。

Function

对autograd来说,还有另外一个非常重要的class,Fucntion

TensorFunction之间互相连接,构成了一个无环图(acyclic graph)。图中包括了计算的完整历史。每个张量都有.grad_fn属性,该属性会引用创建该tensor的Function。(除了是由用户自己创建的tensor,它们的grad_fnNone)。

如果想要计算导数,我们可以在 Tensor 上调用 .backward()。如果 Tensor 是一个标量(如它只包含一个元素的数据),则不需要为backward() 指定任何参数,但是如果它有更多的元素,则需要指定一个 gradient 参数,该参数是一个与该张量形状匹配的张量。

演示

创建一个tensor,并设置其 requires_grad=True 来追踪其计算图

import torch
x = torch.ones(2, 2, requires_grad=True)
print(x)

# output:
# tensor([[1., 1.],
#        [1., 1.]], requires_grad=True)

然后对该tensor做操作

y = x + 2
print(y)

# output:
# tensor([[3., 3.],
#         [3., 3.]], grad_fn=<AddBackward0>)

此处因为y是计算后的结果,所以它具有grad_fn属性

print(y.grad_fn)
# output:
# <AddBackward0 object at 0x7f2451155828>

再看个其它的操作

z = y * y * 3
out = z.mean()
print(z, out)

# output:
# tensor([[27., 27.],
        [27., 27.]], grad_fn=<MulBackward0>) tensor(27., grad_fn=<MeanBackward0>)

可见每一个tensor都对应找到得出该tensor的grad_fn

默认情况下,requires_gradFalse。我们可以用.requires_grad_( ... )来原地修改已有的tensor的requires_grad状态。如下面代码所示:

a = torch.randn(2, 2)
a = ((a * 3) / (a - 1))
print(a.requires_grad)
a.requires_grad_(True)
print(a.requires_grad)
b = (a * a).sum()
print(b.grad_fn)

# output:
# False
# True
# <SumBackward0 object at 0x7f2451164208>

Gradients

现来来看一下上面例子中的反向传播是怎么做的。

因为 out是一个标量(可见它最后输出了z的平均值27)。所以out.backward()就相当于out.backward(torch.tensor(1.))这个相当于是怎么的个意思,不懂

anyway,对其计算导数,并输出对x的导数 d ( o u t ) / d x d(out)/dx d(out)/dx

out.backward()
print(x.grad)

# output:
tensor([[4.5000, 4.5000],
        [4.5000, 4.5000]])

那好,为什么是4.5呢?

首先,我们把out看做张量" o o o",则我们有

∵ o = 1 4 ∑ i z i z i = 3 ( x i + 2 ) 2    且    z i ∣ x i = 1 = 27 ∴ ∂ o ∂ x i = 3 2 ( x i + 2 ) ∂ o ∂ x i ∣ x i = 1 = 9 2 = 4.54 \begin{aligned} \because \mathcal{o} &= \frac{1}{4}\sum_i z_i\\ z_i&=3(x_i + 2)^2 \ \ 且 \ \ z_i\bigg|_{x_i = 1} = 27 \\ \therefore \frac{\partial o}{\partial x_i}&= \frac{3}{2}(x_i + 2)\\ \frac{\partial o}{\partial x_i} \bigg|_{x_i = 1} &= \frac{9}{2} = 4.5 {4} \end{aligned} ozixioxioxi=1=4

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值