名字不能取太长 2024-03-10 13:04 采纳率: 75.6%
浏览 38
已结题

在训练时发现梯度范数一直是0


def forward(self, x):
    with torch.no_grad():
        x = self.vae.encode(x).latent_dist.sample().mul_(0.15)
    for layer in self.layers:
        x = layer(x)
    with torch.no_grad():
        x = self.vae.decode(x / 0.18215).sample
    x.requires_grad_(True)
    return x

以上是一个forward函数,使用VAE来进行encode和decode,但是我发现训练时梯度范数grad_norm从一开始就是0,但是损失又在慢慢下降,这是为什么?如果不加上VAE,梯度范数就是正常的,如下:


def forward(self, x):
    for layer in self.layers:
        x = layer(x)
    return x
  • 写回答

14条回答 默认 最新

  • 叫兽-郭老师 Java领域新星创作者 2024-03-10 13:05
    关注

    🌈🌈🌈参考通义千问和郭老师的小迷弟雅思莫了-编写提供🌈🌈🌈
    您可以参考如下,如果回答的不正确,及时评论区回复我,我会根据你错误描述追加回复,直到您满意为止。

    观察你的代码,问题可能是因为你在前向传播的过程中使用了torch.no_grad()。torch.no_grad()的作用是暂时禁止对tensor数据进行梯度追踪。在这个上下文管理器中完成的所有运算都不会被追踪。 在你的代码中,你对VAE的编码和解码过程使用了torch.no_grad(),这意味着这两个步骤对于梯度计算是不可见的,即使你在后面对x使用了requires_grad_(True),那也只能对x进行梯度追踪,而不能恢复你在torch.no_grad()中丢失的梯度信息。 如果在训练过程中,你对这两个步骤的梯度感兴趣,那么需要移除torch.no_grad()。不过,请注意,如果你同时更新了VAE和其他层,可能需要为VAE和其他层设置不同的学习率,因为通常在微调预训练模型时,直接使用预训练模型的学习率会导致模型快速收敛然后反弹。 可以参考这样改:

    def forward(self, x):
        # 移除torch.no_grad()
        x = self.vae.encode(x).latent_dist.sample().mul_(0.15)
        for layer in self.layers:
            x = layer(x)
        x = self.vae.decode(x / 0.18215).sample
        x.requires_grad_(True)
        return x
    
    

    以上修改只是移除了torch.no_grad(),如果你仍然希望在特定部分禁用梯度计算,但又需要梯度信息,你可能需要手动保存特定tensor的梯度,然后在禁用梯度计算之后手动恢复。具体做法会比较复杂,需要具体任务进行设计。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论 编辑记录
查看更多回答(13条)

报告相同问题?

问题事件

  • 系统已结题 3月22日
  • 已采纳回答 3月14日
  • 修改了问题 3月10日
  • 创建了问题 3月10日

悬赏问题

  • ¥30 模拟电路 logisim
  • ¥15 PVE8.2.7无法成功使用a5000的vGPU,什么原因
  • ¥15 is not in the mmseg::model registry。报错,模型注册表找不到自定义模块。
  • ¥15 安装quartus II18.1时弹出此error,怎么解决?
  • ¥15 keil官网下载psn序列号在哪
  • ¥15 想用adb命令做一个通话软件,播放录音
  • ¥30 Pytorch深度学习服务器跑不通问题解决?
  • ¥15 部分客户订单定位有误的问题
  • ¥15 如何在maya程序中利用python编写领子和褶裥的模型的方法
  • ¥15 Bug traq 数据包 大概什么价