Pytorch学习笔记--1 AUTOGRAD

Pytorch学习笔记--1 AUTOGRAD

AUTOGRAD:全自动微分

Autograd–automatic gradient,顾名思义,是能够帮我们自动求解梯度的包。所有Pytorch神经网络的核心都是autograd包,因此在正式开始训练我们的第一个网络之前,先让我们看看autograd具体能做些什么。
不论是深度学习还是更为基础的神经网络,它们“学习”的能力都是围绕Back Propagation(BP)(即反向传播)建立起来的,而BP的数学基础就是微分。想对BP做进一步了解的朋友可以移步这里,几个高赞回答都解答的很完善了。对于一个庞大的网络,为其中的每一个运算求微分是极其繁琐的,而autograd包将我们从数学的深渊中解放了出来。
对于所有的张量运算,autograd包都可以为我们提供其所对应的微分。auotgrad是一种由运行流程定义的(define-by-run)框架,也就意味着整个网络后向传播的过程将取决与代码的执行流程。在某些情况下或许用户需要在迭代中对输入的张量做不同的操作,那么autograd会自动根据操作的改变进行调整。
下面让我们结合一些简单例子来进一步了解autograd。

Tensor

在上一篇文章中我们已经了解过torch.Tensor这个包了。如果将一个tensor的属性.requires_grad设为True,那么框架就会自动追踪所有基于该tensor的运算。在运算结束后执行.backward(),所有运算相关的梯度都将会被自动求解出来,并且该张量对应的梯度会被累加到属性.grad上。
如果想要将某个tensor移出追踪的列表,可以使用.detach()函数完成解绑,解绑完成后在该张量上的后续计算都不会被autograd追踪。
如果只是想要暂时停止追踪(有助于节省内存消耗),可以通过with torch.no_grad():将指定代码块包裹住。这个方法在评估模型时尤其有用,在模型评估的代码块中不涉及梯度计算以及参数更新,暂时停止梯度计算有助于提升程序的运行效率。
autograd的实现中还有一个非常重要的类:Function
Tensor之间通过Function进行相互连接并建立起一张无环图,这张无环图包含了完整的计算流程。每个tensor都有.grad_fn属性来描述创造该张量所使用的Function。需要注意这里有一个特例,用户创建的tensor的grad_fnNone
在计算导数的时候可以直接调用Tensor的方法:.backward()。如果该tensor是一个标量(即张量内部只有一个元素),那么用户不需要为backward()指定任何参数。反之则需为gradient参数传入一个大小匹配的张量,稍后我们会做讨论,现在先来看看标量的后向传播。

动手创建一个张量,并将requires_grad设为True:

import torch

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

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

执行一次张量运算:

y = x + 2
print(y)
print(y.grad_fn)

# Out:
# tensor([[3., 3.],
#         [3., 3.]], grad_fn=<AddBackward0>)
# <AddBackward0 object at 0x7fac3a8d0080>	生成该张量相关的运算

再试试其他的运算:

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

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

.requires_grad_(...)能够修改Tensor中requires_grad属性的值,其默认为False

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)

False
True
<SumBackward0 object at 0x7fac3a8d0c18>

梯度

现在我们可以在刚才创建的名为out的张量上做后向传播(BP)了,由于out中仅有一个元素,out.backward()等价于out.backward(torch.tensor(1.))

out.backward()
print(x.grad)

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

程序最终输出了大小为2x2的矩阵,其中每个值均为4.5。
这个结果是如何得到的呢?方便起见,我们简写out o o o,根据上述操作可以写出 o o o的实际表达式为: o = 1 4 ∑ i z i o=\frac{1}{4}\sum_{i}z_i o=41izi,且 z i = 3 ( x i + 2 ) 2 z_i=3(x_i+2)^2 zi=3(xi+2)2。很容易求得 ∂ o ∂ x i = 3 2 ( x i + 2 ) \frac{\partial o}{\partial x_i}=\frac{3}{2}(x_i+2) xio=23(xi+2),在 x i = 1 x_i=1 xi=1时有 ∂ o ∂ x i ∣ x i = 1 = 9 2 \frac{\partial o}{\partial x_i}|_{x_i=1}=\frac{9}{2} xi

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值