动手学深度学习_2.2_autograd

Tensor

import torch

x = torch.ones(2, 2, requires_grad=True)  # 将其属性.requires_grad设置为True,它将开始追踪(track)在其上的所有操作。完成计算后,可以调用.backward()来完成所有梯度计算
print(x)
print(x.grad_fn)  # 每个Tensor都有一个.grad_fn属性,该属性即创建该Tensor的Function(除非用户创建的Tensors时设置了grad_fn=None)

# tensor([[1., 1.],
#        [1., 1.]], requires_grad=True)
# None 
y = x + 2
print(y)
print(y.grad_fn)

# tensor([[3., 3.],
#         [3., 3.]], grad_fn=<AddBackward0>)
# <AddBackward0 object at 0x7fecef6f5320>

attension: x是直接创建的,所以他没有grad_fn,而y通过一个加法操作创建的,所以它有一个的grad_fn

# x这种直接创建的称为叶⼦节点,叶⼦节点对应的 grad_fn 是 None 
print(x.is_leaf, y.is_leaf) 

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

# tensor([[27., 27.],
#         [27., 27.]], grad_fn=<MulBackward0>) tensor(27., grad_fn=<MeanBackward0>)
# 通过.requires_grad_()来用in-place的方式改变requires_grad属性
a = torch.randn(2, 2)  # 缺失情况下默认requires_grad=False
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 0x7fecef6d17b8>

梯度

# 因为out是一个标量,所以调用backward()时不需要指定求导变量
out.backward()  # 等价于out.backward(torch.tensor(1.))
print(x.grad)

# tensor([[4.5000, 4.5000],
#         [4.5000, 4.5000]])
# 再来一次反向传播,注意 grad 是累加的
out2 = x.sum()
out2.backward()
print(x.grad)

out3 = x.sum()
x.grad.data.zero_()
out3.backward()
print(x.grad)

# tensor([[5.5000, 5.5000],
#         [5.5000, 5.5000]])
# tensor([[1., 1.],
#         [1., 1.]])
# y.backward(w) 求的不是 y 对 x 的导数,而是 l = torch.sum(y*w) 对 x 的导数。
x = torch.tensor([1.0, 2.0, 3.0, 4.0], requires_grad=True)
y = 2 * x
z = y.view(2, 2)
print(z)

# tensor([[2., 4.],
#         [6., 8.]], grad_fn=<ViewBackward>)

现在y不是一个标量,所以在调用backward时需要传入一个和y同行的权重向量进行甲醛求和得到一个标量

v = torch.tensor([[1.0, 0.1], [0.01, 0.001]], dtype=torch.float)
z.backward(v)
print(x.grad)

# tensor([2.0000, 0.2000, 0.0200, 0.0020])
# 中断梯度追踪
x = torch.tensor(1.0, requires_grad=True)
y1 = x ** 2
with torch.no_grad():  # 与y2有关的梯度是不会回传的,只有与y1有关的梯度才会回传
    y2 = x ** 3
y3 = y1 + y2

print(x, x.requires_grad)
print(y1, y1.requires_grad)
print(y2, y2.requires_grad)  # False,所以不能调用y2.backward()
print(y3, y3.requires_grad)


# tensor(1., requires_grad=True) True
# tensor(1., grad_fn=<PowBackward0>) True
# tensor(1.) False
# tensor(2., grad_fn=<AddBackward0>) True
y3.backward()
print(x.grad)

# tensor(2.)

想修改tensor的数值,但又不希望被autograd记录(即不影响反向传播),那么可对tensor.data操作

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

print(x.data)
print(x.data.requires_grad)

y = 2 * x
x.data *= 100

y.backward()
print(x)
print(x.grad)

# tensor([1.])
# False
# tensor([100.], requires_grad=True)
# tensor([2.])
posted @ 2019-11-30 12:28  ho_ho  阅读(264)  评论(0编辑  收藏  举报