PyTorch线性回归训练中偏置项未更新的问题排查
嘿,我看了你遇到的问题:用PyTorch做线性回归拟合10维输入的平均值,权重完美收敛到每个0.1,但偏置却纹丝不动,一直停留在初始的0.2830,完全没向预期的0靠拢。别急,咱们一步步拆解问题,找到解决办法。
为啥偏置死活不更新?
首先,你的任务目标是对的:输出是输入的平均值,模型应该学到 y = 0.1*x₁ + 0.1*x₂ + ... +0.1*x₁₀ + 0,偏置确实该是0。那问题出在哪呢?
我盯着你的代码看了一圈,发现最关键的问题是学习率太小了!你用的是lr=1e-8,这个数值小到离谱。咱们算笔账:
当权重已经收敛到0.1时,模型的预测值是 0.1*sum(x) + b,而真实标签是0.1*sum(x),此时损失就是 (b)^2(平均后)。损失对偏置b的梯度是2*b,初始b是0.2830,那梯度就是约0.566。
用1e-8的学习率,每次更新b的步长是 0.566 * 1e-8 ≈ 5.66e-9。500次迭代下来,b总共才减少了 500 * 5.66e-9 ≈ 2.83e-6——这么小的变化,打印出来自然还是0.2830,看起来跟没动一样!
另外,我也确认了你的数据集处理逻辑,从权重能收敛到0.1来看,你的标签确实是输入的平均值,数据集这块没问题。
怎么解决?
1. 直接调大学习率
这是最直接有效的办法。把学习率从1e-8改成1e-3或者1e-2试试,比如:
optimizer = th.optim.SGD(model.parameters(), lr=1e-3)
这样每次更新b的步长就变成了0.566 * 1e-3 ≈ 0.000566,500次迭代后,b正好从0.2830降到0,完美收敛到预期值。
2. 换用自适应优化器(可选)
如果觉得调SGD的学习率麻烦,可以试试Adam优化器,它能自适应调整学习率,上手更简单:
optimizer = th.optim.Adam(model.parameters(), lr=1e-3)
3. 验证一下效果
改完学习率后再跑训练,你会看到偏置开始慢慢下降,比如训练100轮左右b就会降到0.2左右,500轮后基本接近0,同时训练损失也会降到几乎为0。
举个预期的输出例子:
Epoch[1/500], bias: tensor([0.2824], device='cuda:0'), weight: ... Epoch[100/500], bias: tensor([0.2264], device='cuda:0'), weight: ... Epoch[500/500], bias: tensor([0.0001], device='cuda:0'), weight: tensor([[0.1000, 0.1000, ..., 0.1000]], device='cuda:0')
总结一下
核心问题就是学习率太小,导致偏置的更新量微乎其微,肉眼根本看不出来。只要把学习率调到合理范围,偏置就会正常向0收敛啦。
内容的提问来源于stack exchange,提问作者star-fire

