You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何我的Sigmoid层阻断了梯度传递?

问题分析与解答

原代码示例

import torch
import torch.optim as optim
import torch.nn as nn

input = torch.tensor([1.,2.], requires_grad=True)
sigmoid = nn.Sigmoid()

interm = sigmoid(input)

optimizer = optim.SGD([input], lr=1, momentum=0.9)

for epoch in range(5):
    optimizer.zero_grad()
    loss = torch.linalg.vector_norm(interm - torch.tensor([2.,2.]))
    print(epoch, loss, input, interm)

    loss.backward(retain_graph=True)
    optimizer.step()
    print(interm.grad)

梯度异常+目标无法达成的原因

  • 核心问题:中间结果interm仅计算一次
    你把interm = sigmoid(input)写在了循环外部,这意味着不管优化器怎么更新input,interm始终是初始input=[1.,2.]经过sigmoid计算出的固定值。循环内的loss一直基于这个固定值计算,梯度自然无法传递到更新后的input上,优化过程完全无效。

  • 逻辑错误:目标值超出sigmoid输出范围
    sigmoid函数的输出永远在(0,1)区间内,你要求interm等于[2.,2.],从数学上根本不可能实现。就算代码修正,优化过程也会朝着不可能的目标无意义迭代,最终loss收敛到固定值(即1与2的差值范数)。

  • 冗余操作:retain_graph=True无必要
    这里每次循环都是独立的计算图,不需要保留计算图,去掉该参数不影响运行。另外打印interm.grad意义不大,我们要优化的是input,应该关注input.grad的变化。

修正后的代码示例

import torch
import torch.optim as optim
import torch.nn as nn

input = torch.tensor([1.,2.], requires_grad=True)
sigmoid = nn.Sigmoid()

optimizer = optim.SGD([input], lr=1, momentum=0.9)
# 将目标改为sigmoid可达到的范围,比如[0.9,0.9]
target = torch.tensor([0.9,0.9])

for epoch in range(5):
    optimizer.zero_grad()
    # 每次循环基于当前input重新计算interm
    interm = sigmoid(input)
    loss = torch.linalg.vector_norm(interm - target)
    print(f"epoch {epoch}: loss={loss.item()}, input={input}, interm={interm}")

    loss.backward()
    optimizer.step()
    # 查看input的梯度变化
    print(f"input grad: {input.grad}")

内容的提问来源于stack exchange,提问作者JobHunter69

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 04:30:06