含无权重自定义层的神经网络梯度下降计算原理疑问
自定义常数缩放层的反向传播梯度计算解析
核心误区澄清
你混淆了「常数的导数」和「反向传播中梯度的传递逻辑」。你的自定义层是对输入张量执行 x * 0.001 的固定缩放操作,这里的0.001不是可训练参数,反向传播时不需要求它的梯度——你看到的非零梯度是前层(l1)和后层(l3)的权重梯度,这些梯度的计算会被自定义层的缩放操作影响,而非自定义层自身产生参数梯度。
反向传播的梯度传递原理
对于自定义层的前向操作 y = x * c(c=0.001,固定常数):
- 前向传播:输入x被缩放为y
- 反向传播:根据链式法则,损失L对x的梯度
dL/dx = dL/dy * dy/dx,其中dy/dx = c(y对x的导数就是常数c)。也就是说,上游传来的梯度dL/dy会被乘以c,再传递给前一层。
结合你的代码具体分析
你的网络结构是 l1(Linear)→ l2(自定义缩放)→ l3(Linear):
- 前向流程:
intermediate1 = l1(random_input)→intermediate2 = intermediate1 * 0.001→output = l3(intermediate2) - 反向流程:
- 损失
loss对output求导得到初始梯度,先传递给l3,计算l3权重的梯度l3.weight.grad - 接着,l3的输入梯度(即l2的输出梯度)被传递给l2,l2将这个梯度乘以0.001,得到l1输出的梯度
dL/d(intermediate1) - 最后,用这个梯度计算l1权重的梯度
l1.weight.grad
- 损失
- 你看到的
l1.weight.grad和l3.weight.grad非零,是因为它们的计算依赖中间张量的梯度传递,而l2的缩放操作改变了中间梯度的大小,进而影响了最终的权重梯度。
代码中Hook输出的验证
看你注册的hookFunc输出:
- 对于l2层,
gradOutput是上游(l3)传来的梯度,gradInput就是gradOutput * 0.001——这正是l2在反向传播中执行的逻辑:把上游梯度按缩放因子传递给前层。
总结
- 自定义层没有可训练参数,所以不会产生自身参数的梯度,但它作为计算图的一部分,会根据前向操作定义梯度传递的规则
- 你之前的错误在于误将「常数对自身的导数(0)」和「输入张量对自身的导数(常数c)」混淆,反向传播关注的是后者,用来传递梯度到前层
内容的提问来源于stack exchange,提问作者Vishnu s
相关产品推荐
相关产品推荐

