"""
注意:在y.backward()时,如果y是标量,则不需要为backward()传入任何参数;否则,需要传入一个与y同形的tensor
如果不想被继续追踪,可以调用.detach()将其从追踪记录中分离开来,这样就可以防止将来的计算被追踪,这样梯度就传不过去了,此外还可以
使用with torch.no_grad()将不想被追踪的操作代码块包裹起来,这种方法在评估模型的时候很常用
Function是另外一个很重要的类,tensor和function互相结合就可以构建一个记录有整个计算过程的有向无环图,每个tensor都有一个
.grad_fn()属性,该属性创建该tensor的function类,就是说该tensor是不是通过某些运算得到的,若是,则grad_fn返回一个与这些运算
相关的对象,否则为none
"""
import torch
x = torch.ones(2,2,requires_grad=True)
print(x)
"""
tensor([[1., 1.],
[1., 1.]], requires_grad=True)
"""
print(x.grad_fn)
y = x + 2
print(y)
"""
tensor([[3., 3.],
[3., 3.]], grad_fn=<AddBackward0>)
"""
print(y.grad_fn)
print(x.is_leaf,y.is_leaf)
z = y * y * 3
out = z.mean()
print(z,out)
"""
tensor([[27., 27.],
[27., 27.]], grad_fn=<MulBackward0>) tensor(27., grad_fn=<MeanBackward0>)
"""
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)
out.backward()
print(x.grad)
"""
tensor([[4.5000, 4.5000],
[4.5000, 4.5000]])
"""
"""
例如:假设y由自变量x计算而来,w和y是同形的张量,则y.backward(w)的含义是:先计算1 = torch.sum(y * w),则1是一个标量,然后求1
对自变量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)
print(y)
"""
tensor([[2., 4.],
[6., 8.]])
"""
v = torch.tensor([[1.0,0.1],[0.01,0.001]],dtype=torch.float)
z.backward(v)
print(x.grad)
"""
tensor([[5.5000, 5.5000],
[5.5000, 5.5000]])
"""
"""
tensor([[1., 1.],
[1., 1.]])
"""
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)
print(y2,y2.requires_grad)
print(y3,y3.requires_grad)
y3.backward()
print(x.grad)
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)