PyTorch学习笔记一

#梯度和反向传播
本文学习自莫烦教程

import torch
# 导入autograd包进行梯度运算
from torch.autograd import Variable
tensor = torch.FloatTensor([[1, 2], [3, 4]])
# variable是计算图的一部分,是自动梯度计算的一部分
variable = Variable(tensor, requires_grad=True)
print(tensor)
print(variable)

tensor([[1., 2.],
        [3., 4.]]) 
tensor([[1., 2.],
        [3., 4.]], requires_grad=True)

t_out = torch.mean(tensor*tensor)
v_out = torch.mean(variable*variable)
print(t_out)
print(v_out)

tensor(7.5000)
tensor(7.5000, grad_fn=<MeanBackward0>)     

# 计算得出的v_out可以进行反向传播
v_out.backward()

下式是 v o u t v_{out} vout的计算公式,在此基础上可以进行反向传播并且求出variable的梯度
v o u t = 1 4 s u m ( v a r i a b l e 2 ) v_{out} = \frac{1}{4}sum(variable^2) vout=41sum(variable2)

# 得出variable的梯度
variable.grad

tensor([[0.5000, 1.0000],
        [1.5000, 2.0000]])

关于autograd的一些补充:

x = torch.randn((2, 2))
y = torch.randn((2, 2))
var_x = Variable(x, requires_grad=True)
var_y = Variable(y, requires_grad=True)
print(var_x.grad_fn)  # None
var_z = var_x + var_y
print(var_z.grad_fn)   # <AddBackward0 object at 0x00000166200D1A90>

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

y = x + 2
print(y)
print(y.grad_fn)   # <AddBackward0 object at 0x000001341DB67E80>

由上面的代码可以知道,var_x是由用户自己指定的,不具有grad_fn属性,而var_z是由var_x和var_y计算得来的,所以具备grad_fn属性。

梯度计算

z = y * y * 3
out = z.mean()
print(z)
print(out)   # tensor(27., grad_fn=<MeanBackward0>)
out.backward()
print(x.grad)
	# tensor([[4.5000, 4.5000],
        	#[4.5000, 4.5000]])

out是个标量,所以.backward()方法中不需要参数,可以直接进行反向传播,out的计算公式如下,
o u t = 1 4 ∑ i = 1 4 3 ( x + 2 ) 2 out=\frac{1}{4}\sum_{i=1}^4{3(x+2)^2} out=41i=143(x+2)2
求out对x的导数,
d ( o u t ) d x i ∣ x i = 1 = 1 4 ⋅ 6 ( x i + 2 ) ∣ x i = 1 = 4.5 \frac{d(out)}{dx_i}|x_{i=1}=\frac{1}{4}\cdot6(x_i+2)|x_{i=1}=4.5 dxid(out)xi=1=416(xi+2)xi=1=4.5

中断梯度追踪的例子

x = torch.tensor(1.0, requires_grad=True)
y1 = x ** 2 
with torch.no_grad():
    y2 = x ** 3
y3 = y1 + y2

print(x.requires_grad)
print(y1, y1.requires_grad) # True
print(y2, y2.requires_grad) # False
print(y3, y3.requires_grad) # True
y3.backward()
print(x.grad)  # tensor(2.)

和y2有关的梯度不会回传,所以只计算和y1有关的梯度。

如果我们想要修改tensor的数值,但是又不希望被autograd记录(即不会影响反向传播),那么我么可以对tensor.data进行操作。

x = torch.ones(1,requires_grad=True)

print(x.data) # tensor([1.]),还是一个tensor
print(x.data.requires_grad) # False,证明已经是独立于计算图之外

y = 2 * x
x.data *= 100 # 只改变了值,不会记录在计算图,所以不会影响梯度传播

y.backward()
print(x) # tensor([100.], requires_grad=True),更改data的值也会影响tensor的值
print(x.grad)  # tensor([2.]),不会影响梯度传播
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值