给定前馈步骤中张量的索引版本,pytorch 如何执行反向微分?
Posted
技术标签:
【中文标题】给定前馈步骤中张量的索引版本,pytorch 如何执行反向微分?【英文标题】:How does pytorch perform the reverse-differentiation given an indexed version of a tensor in the feedforward step? 【发布时间】:2021-09-26 05:37:42 【问题描述】:部分代码改编自 Deep learning with Pytorch 一书
脚本:线性回归(尝试在给定 t_u 的情况下预测 t_c)
t_c = torch.tensor([0.5, 14.0, 15.0, 28.0, 11.0, 8.0,
3.0, -4.0, 6.0, 13.0, 21.0])
t_u = torch.tensor([35.7, 55.9, 58.2, 81.9, 56.3, 48.9,
33.9, 21.8, 48.4, 60.4, 68.4])
def model(t_u, w, b):
return w * t_u + b
def loss_fn(t_p, t_c):
squared_diffs = (t_p - t_c)**2
return squared_diffs.mean()
params = torch.tensor([1.0, 0.0], requires_grad=True)
loss = loss_fn(model(t_u, params[0], params[1]), t_c)
loss.backward()
print(params.grad)
在这里,我将 params
的第 0 和第 1 个索引作为输入传递给 model
函数,该函数执行标量到向量的乘法和加法。
我的问题是,PyTorch 究竟在做什么来计算 params
张量的梯度? “前馈”步骤使用params
张量的两个子张量,而不是我所熟悉的用于偏差和权重的单独张量。
我的猜测是:params[0]
和 params[1]
都是对 params
中元素的引用,并且它们都有自己独特的渐变存储在 params.grad
的某处。所以.backward()
调用将params[0]
和params[1]
视为新的单独张量(好像我们暂时有两个单独的张量-weight
和bias
)并更新它们的梯度(params[0].grad
,params[1].grad
) ,因此更新params.grad
,因为它们是对它的引用。
【问题讨论】:
【参考方案1】:这里的主要思想是索引操作返回张量的新视图。如果您不使用就地操作(+=、-= 等),则“视图”并不重要,您可以将其视为另一个张量。
在这种情况下,索引操作与加法或矩阵乘法等其他操作没有什么不同——输入(原始张量)、输出(选择的张量)和梯度(如果选择,则为 1,否则为零*)。然后像往常一样进行反向传播。
* 更具体地说,如果从输入条目中选择输出条目,则输入条目相对于输出条目的梯度为 1;否则为 0。
编辑: 也许这样看更容易:
a = d_params[0]
c = W*a+b
--------------------------
dc/d_params
= dc/d_params[0], d_params[1], d_params[2], ...
--------------------------
dc/d_params[0]
= dc/da * da/d_params[0]
= dc/da * 1
= W
--------------------------
dc/d_params[1], dc/d_params[2], ... = 0
【讨论】:
嗯,我不确定我是否完全理解。你的意思是 d_params/d_params[0] = 1?对于这个例子,如果我们有单独的权重和偏置张量,我们将有 dC/dW 和 dC/dB。现在有了可微分索引操作,我将如何表达 dC/d_params 的链式规则表达式?以上是关于给定前馈步骤中张量的索引版本,pytorch 如何执行反向微分?的主要内容,如果未能解决你的问题,请参考以下文章