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

手动实现的MLP可运行但无训练效果,反向传播排查求助

手动实现MLP无法学习的常见排查点

以下是结合PyTorch新手易踩坑点整理的排查方向:

  • 参数未开启梯度跟踪
    检查手动定义的权重、偏置是否设置了requires_grad=True。如果用torch.randn()直接创建张量而不指定该属性,或者没有封装成nn.Parameter,PyTorch不会跟踪这些参数的梯度,反向传播时根本不会更新参数。正确写法示例:

    self.w1 = nn.Parameter(torch.randn(input_dim, hidden_dim), requires_grad=True)
    self.b1 = nn.Parameter(torch.zeros(hidden_dim), requires_grad=True)
    
  • Softmax与损失函数的冲突
    如果输出层手动实现了softmax,同时又使用nn.CrossEntropyLoss,会导致逻辑错误——因为CrossEntropyLoss内部已经包含了log_softmax的计算,重复计算会让梯度异常。解决方式二选一:

    1. 输出层改为log_softmax,搭配nn.NLLLoss计算损失;
    2. forward函数中去掉输出层的softmax,直接输出线性层结果,交给CrossEntropyLoss处理。
  • ReLU反向传播的掩码未正确记录
    手动实现ReLU时,必须记录正向传播时哪些神经元被激活(即输入大于0的位置),反向传播时才能将对应位置的梯度保留,其余置0。如果反向传播时没用到这个掩码,梯度计算会完全错误。示例逻辑:

    # 正向传播
    self.hidden = torch.matmul(x, self.w1) + self.b1
    self.relu_mask = self.hidden > 0
    self.hidden_relu = self.hidden * self.relu_mask.float()
    
    # 反向传播(隐藏层梯度)
    d_hidden = d_output @ self.w2.T
    d_hidden = d_hidden * self.relu_mask.float()  # 应用掩码
    
  • 梯度更新的错误操作

    1. 训练循环中是否忘记调用optimizer.zero_grad()?如果不清零梯度,每次反向传播的梯度会累加,导致参数更新方向混乱;
    2. 手动更新参数时,是否直接修改了参数张量本身(比如self.w1 -= lr * self.w1.grad)?正确的做法应该是操作data属性(旧版本),或者用optimizer的step()方法(推荐)。
  • 权重初始化不当
    如果权重初始值过大,会导致ReLU神经元饱和,梯度消失;全0初始化则会让所有神经元更新方向一致,无法学习特征。针对ReLU激活,推荐使用He初始化:

    nn.init.kaiming_normal_(self.w1, mode='fan_in', nonlinearity='relu')
    
  • 反向传播的维度匹配问题
    检查batch维度是否正确处理:比如正向传播时是否保留了batch维度,反向传播时损失的平均/求和是否对应batch维度,避免因维度压缩错误导致梯度计算偏差。

请补充以下关键代码片段以便更精准定位问题:

  • 模型的初始化代码(权重、偏置的定义与初始化)
  • forward函数的完整实现
  • 反向传播函数或自定义梯度计算逻辑
  • 训练循环的核心步骤(损失计算、梯度更新部分)

内容的提问来源于stack exchange,提问作者mt-clemente

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 14:48:23