
在pytorch模型训练中,参数不更新是一个常见问题,通常是由于学习率设置过低,导致每次迭代的参数更新幅度远小于参数自身的量级或梯度幅度。本文将深入分析这一现象,并通过示例代码演示,解释如何通过调整学习率来有效解决参数停滞不前的问题,并提供优化学习率的实践建议。
在使用PyTorch进行深度学习模型训练时,开发者有时会遇到模型参数似乎没有更新的困惑。尽管代码逻辑看起来正确,包括计算损失、反向传播和优化器步进,但参数值却保持不变或变化微乎其微。这通常不是代码逻辑错误,而是超参数设置不当,特别是学习率(learning rate)过低所致。
考虑以下一个简单的优化问题示例,目标是调整 x_param 以使其经过一系列计算后得到的权重向量 w 尽可能接近 target_weights_vec:
import torch
import numpy as np
np.random.seed(10)
def optimize(final_shares: torch.Tensor, target_weight, prices, loss_func=None):
"""
计算基于当前份额的权重向量,并与目标权重计算损失。
"""
final_shares = final_shares.clamp(0.) # 确保份额非负
mv = torch.multiply(final_shares, prices)
w = torch.div(mv, torch.sum(mv))
# print(w) # 调试时可打印权重
return loss_func(w, target_weight)
def main():
position_count = 16
cash_buffer = .001
starting_shares = torch.tensor(np.random.uniform(low=1, high=50, size=position_count), dtype=torch.float64)
prices = torch.tensor(np.random.uniform(low=1, high=100, size=position_count), dtype=torch.float64)
prices[-1] = 1.
# 待优化的参数,requires_grad=True 确保其梯度会被计算
x_param = torch.nn.Parameter(starting_shares, requires_grad=True)
# 定义目标权重
target_weights = ((1 - cash_buffer) / (position_count - 1))
target_weights_vec = [target_weights] * (position_count - 1)
target_weights_vec.append(cash_buffer)
target_weights_vec = torch.tensor(target_weights_vec, dtype=torch.float64)
loss_func = torch.nn.MSELoss() # 使用均方误差作为损失函数
eta = 0.01 # 学习率
optimizer = torch.optim.SGD([x_param], lr=eta) # 使用SGD优化器
for epoch in range(10000):
optimizer.zero_grad() # 清零梯度
loss_incurred = optimize(final_shares=x_param, target_weight=target_weights_vec,
prices=prices, loss_func=loss_func)
loss_incurred.backward() # 反向传播计算梯度
# 打印梯度信息 (可选,用于诊断)
# if epoch % 1000 == 0:
# print(f"Epoch {epoch}, Loss: {loss_incurred.item():.6f}, Avg Grad: {x_param.grad.abs().mean().item():.8f}")
optimizer.step() # 更新参数
print("\nOptimization finished. Final x_param:")
print(x_param)
print("Final loss:")
final_loss = optimize(final_shares=x_param.data, target_weight=target_weights_vec,
prices=prices, loss_func=loss_func)
print(final_loss.item())
if __name__ == '__main__':
main()运行上述代码,即使经过10000个epoch,x_param 的值可能看起来并没有发生显著变化,或者损失值下降非常缓慢。
问题的核心在于学习率 eta(0.01)相对于梯度的平均幅度和参数自身的量级来说太小了。
因此,即使进行了10000次迭代,参数的累积变化也只有 10000 * 1e-7 = 1e-3,这在视觉上几乎无法察觉,也无法有效降低损失。
解决这个问题的直接方法是显著提高学习率。
# ... eta = 100 # 将学习率显著提高 optimizer = torch.optim.SGD([x_param], lr=eta) # ...
通过这种调整,参数在10000次迭代中的累积变化将达到 10000 * 1e-3 = 10,这将导致参数发生显著变化,并使损失函数有效收敛。
当PyTorch模型参数在训练循环中不更新时,首先应检查学习率的设置。一个过低的学习率是导致参数停滞不前的最常见原因。通过分析梯度和参数的量级,并相应地调整学习率,通常可以解决这个问题。同时,结合学习率调度器、学习率范围测试以及适当的优化器选择,可以更有效地训练深度学习模型,确保参数能够正确且高效地更新。
以上就是PyTorch参数不更新:诊断与解决低学习率问题的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号