通俗的来说就是学习(参数更新)的方向。
简单理解,(对于低维函数来讲)就是导数(或者是变化最快的方向)
回归损失
l
o
s
s
=
(
Y
p
r
e
d
i
c
t
−
Y
t
r
u
e
)
2
loss = (Y_{predict} - Y_{true})^2
loss=(Ypredict−Ytrue)2
分类损失
l o s s = Y t r u e ⋅ l o g ( Y p r e d i c t ) loss = Y_{true} · log(Y_{predict}) loss=Ytrue⋅log(Ypredict)
J ( a , b , c ) = 3 ( a + b c ) J(a, b, c) = 3(a + bc) J(a,b,c)=3(a+bc), 令 u = a + v u = a+v u=a+v, v = b c v = bc v=bc,把它绘制成计算图可以表示为:
绘制成计算图之后,可以清楚的看到前向计算的过程。
对每个节点求偏导可以有:
反向传播就是一个从右到左的过程,自变量
a
,
b
,
c
a,b,c
a,b,c各自的骗到就是连线上梯度的乘积
对于Pytorch中的一个tensor,如果设置它的属性, .require_grad=True
,那么会追踪对于该张量的所有操作。
默认值为None
import torch
x = torch.ones(2, 2, requires_grad=True)
print(x)
y = x+2
print(y)
z = y*y*3
print(z)
输出:
tensor([[1., 1.],
[1., 1.]], requires_grad=True)
tensor([[3., 3.],
[3., 3.]], grad_fn=<AddBackward0>)
tensor([[27., 27.],
[27., 27.]], grad_fn=<MulBackward0>)
总结:
(1)之后的每次计算都会修改其grad_fn
属性,用来记录做过的操作;
(2)通过这个函数和grad_fn
可以生成计算图。
为了防止跟踪历史记录,可以将代码包装在with torch.no_grad
中。表示不需要追中这一块的计算。
import torch
x = torch.ones(2, 2, requires_grad=True)
print(x)
y = x+2
print(y)
z = y*y*3
print(z)
with torch.no_grad():
u = x+y+z
print(u)
tensor([[1., 1.],
[1., 1.]], requires_grad=True)
tensor([[3., 3.],
[3., 3.]], grad_fn=<AddBackward0>)
tensor([[27., 27.],
[27., 27.]], grad_fn=<MulBackward0>)
tensor([[31., 31.],
[31., 31.]])
可以使用backward()
方法来进行反向传播,计算梯度 out.backward()
,此时能方便求出导数。
调用x.grad()
可以获取导数值。
注意:
在输入是一个标量的情况下,可以调用输出tensor
的backward()
方法,但是在输出是一个向量的时候,调用backward
时要传入其他参数。
当tensor的require_grad
为false的时候,a.data
等同于 a
当tensor的require_grad
为True的时候,a.data
表示仅仅获取其中的数据
require_grad=True 不能够直接转换,需要用torch.detach().numpy()
detach相当于是深拷贝
相当于把原来的tensor数据“抽离”出来,并部影响原来的tensor,然后进行深拷贝,转化为numpy数据。