我正在探索PyTorch,但我不理解以下示例的输出:
# Initialize x, y and z to values 4, -3 and 5
x = torch.tensor(4., requires_grad = True)
y = torch.tensor(-3., requires_grad = True)
z = torch.tensor(5., requires_grad = True)
# Set q to sum of x and y, set f to product of q with z
q = x + y
f = q * z
# Compute the derivatives
f.backward()
# Print the gradients
print("Gradient of x is: " + str(x.grad))
print("Gradient of y is: " + str(y.grad))
print("Gradient of z is: " + str(z.grad))
输出
Gradient of x is: tensor(5.)
Gradient of y is: tensor(5.)
Gradient of z is: tensor(1.)
我毫不怀疑,我的困惑源于一个小小的误解。有人能以循序渐进的方式解释一下吗?
发布于 2021-09-28 12:29:21
我希望您能理解,当您使用f.backward()
时,您在x.grad
中得到的是
。
在你的情况下
。所以,很简单(用基础微积分)
如果你输入x,y和z的值,这就解释了输出。
但是,这并不是真正的“反向传播”算法。这只是偏导数(这就是你在问题中所问的全部)。
编辑:如果你想了解它背后的反向传播机制,请参阅@Ivan的答案。
发布于 2021-09-28 15:33:35
我可以提供一些关于反向传播的PyTorch方面的见解。
当操作需要梯度计算(requires_grad=True
)的张量时,PyTorch跟踪反向传播的操作,并构造一个特别的计算图。
让我们看一下你的例子:
q = x + y
f = q * z
其对应的计算图可以表示为:
x -------\
-> x + y = q ------\
y -------/ -> q * z = f
/
z --------------------------/
其中x
、y
和z
称为叶张量。反向传播包括计算x
、y
和y
的梯度,分别对应于dL/dx
、dL/dy
和dL/dz
。其中,L
是基于图形输出f
的标量值。执行的每个操作都需要实现一个反向函数(这是所有数学上可区分的PyTorch内置的情况)。对于每个操作,此函数可有效地用于计算输出w.r.t的梯度。输入。
向后传递将如下所示:
dL/dx <------\
x -----\ \
\ dq/dx
\ \ <--- dL/dq-----\
-> x + y = q ----\ \
/ / \ df/dq
/ dq/dy \ \ <--- dL/df ---
y -----/ / -> q * z = f
dL/dy <------/ / /
/ df/dz
z -------------------------/ /
dL/dz <--------------------------/
第一个运算符的"d(outputs)/d(inputs)"
术语是:dq/dx = 1
和dq/dy = 1
。对于第二个运算符,它们是df/dq = z
和df/dz = q
。
反向传播归结为应用链规则:dL/dx = dL/dq * dq/dx = dL/df * df/dq * dq/dx
。直观上,我们以相反的方式分解dL/dx
,而不是反向传播实际所做的,这是自下而上导航。
在不考虑形状的情况下,我们从dL/df = 1
开始。实际上,dL/df
具有f
的形状(请参阅下面链接的另一个答案)。这将导致dL/dx = 1 * z * 1 = z
。同样,对于y
和z
,我们也有dL/dy = z
和dL/dz = q = x + y
。这就是你观察到的结果。
我给出了一些相关主题的答案:
发布于 2021-09-29 08:54:08
你只需要理解什么是操作,以及你应该用来处理每个操作的偏导数是什么,例如:
x = torch.tensor(1., requires_grad = True)
q = x*x
q.backward()
print("Gradient of x is: " + str(x.grad))
会给你2
,因为x*x
的导数是2*x
。
如果我们以你的x为例,我们有:
q = x + y
f = q * z
可以修改为:
f = (x+y)*z = x*z+y*z
如果我们取f在x的函数中的偏导数,我们只得到z。
要得到这个结果,您必须将所有其他变量视为常量,并应用您已经知道的导数规则。
但请记住,pytorch执行以获得这些结果的过程不是符号或数字微分,而是自动微分,这是一种有效获得梯度的计算方法。
仔细看看:
https://www.cs.toronto.edu/~rgrosse/courses/csc321_2018/slides/lec10.pdf
https://stackoverflow.com/questions/69367939
复制相似问题