PyTorch中优化器运行顺序为何影响线性回归预测效果?
优化器训练顺序影响线性回归结果的原因分析
问题现象
在多优化器线性回归对比实验中发现:
- 若先运行SGD优化器,后续Adam、RMSprop的预测精度表现良好;
- 若先运行Adam或RMSprop,这两个优化器的模型调整效果极差,预测结果几乎无拟合效果。
实验代码
原始代码(非SGD先运行)
# Generate synthetic data X_numpy, y_numpy = datasets.make_regression(n_samples=100, n_features=1, noise=20, random_state=15) X = torch.from_numpy(X_numpy.astype(np.float32)) y = torch.from_numpy(y_numpy.astype(np.float32)) y = y.view(y.shape[0], 1) # Define the model n_samples, n_features = X.shape input_size = n_features output_size = 1 model = nn.Linear(input_size, output_size) # Define learning rate learning_rate = 0.01 # Define criteria criterion = nn.MSELoss() # Define different optimizers optimizers = { "Adam": torch.optim.Adam(model.parameters(), lr=learning_rate), "RMSprop": torch.optim.RMSprop(model.parameters(), lr=learning_rate), "SGD": torch.optim.SGD(model.parameters(), lr=learning_rate), } # Training loop for each optimizer num_epochs = 100 predictions = {} for optimizer_name, optimizer in optimizers.items(): print(f"Optimizer: {optimizer_name}") predictions[optimizer_name] = [] for epoch in range(num_epochs): y_predicted = model(X) loss = criterion(y_predicted, y) loss.backward() optimizer.step() #update weights optimizer.zero_grad() #zero the gradients predictions[optimizer_name] = model(X).detach().numpy() # Plotting predictions with different colors plt.figure(figsize=(10, 6)) plt.plot(X_numpy, y_numpy, 'ro', label='Original Data') for optimizer_name, prediction in predictions.items(): plt.plot(X_numpy, prediction, label=optimizer_name) plt.legend() plt.show()
修改后代码(SGD先运行)
仅调整优化器字典的顺序:
optimizers = { "SGD": torch.optim.SGD(model.parameters(), lr=learning_rate), "Adam": torch.optim.Adam(model.parameters(), lr=learning_rate), "RMSprop": torch.optim.RMSprop(model.parameters(), lr=learning_rate), }
实验结果
非SGD先运行的预测结果

SGD先运行的预测结果

原因解析
出现这种现象的核心问题是所有优化器共享同一个模型实例,且未在训练不同优化器前重置模型参数与优化器状态,结合自适应优化器的特性具体分析:
自适应优化器的初始步长限制
Adam、RMSprop这类自适应优化器会维护参数的梯度矩估计(一阶矩、二阶矩)。初始训练时模型参数为随机值,损失值大、梯度幅值高,会导致二阶矩估计快速增大,使得实际更新步长($\text{lr} \times \text{一阶矩} / \text{二阶矩}$)被压缩到极小,几乎无法更新模型参数。因此当先运行Adam/RMSprop时,训练100轮后模型参数仍接近初始随机值,预测结果自然无法拟合数据。SGD的无自适应特性
SGD没有梯度矩估计机制,直接使用固定学习率更新参数,即使初始梯度大,也能快速调整参数到接近拟合的状态。当先运行SGD时,模型参数已被优化到接近最优值,此时再训练Adam/RMSprop,梯度幅值变小,自适应优化器的步长恢复到合理范围,能够继续优化参数,因此表现良好。共享模型与优化器状态的连锁影响
代码中所有优化器绑定到同一个模型的参数,且训练完一个优化器后未重置模型参数,也未重新初始化优化器的内部状态。这导致后续优化器是基于前一个优化器训练后的参数继续训练,而非从初始状态开始,进一步放大了自适应优化器的初始步长问题。
解决方法
要做公平的对比实验,需保证每个优化器都从相同的初始状态开始训练:
- 针对每个优化器,重新创建模型实例或重置模型参数到初始值;
- 每个优化器都基于新的模型参数重新初始化,避免共享内部状态。
示例修改后的训练循环:
predictions = {} # 针对每个优化器单独初始化模型和优化器 for optimizer_name in ["Adam", "RMSprop", "SGD"]: # 重置模型 model = nn.Linear(input_size, output_size) # 初始化对应优化器 if optimizer_name == "Adam": optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate) elif optimizer_name == "RMSprop": optimizer = torch.optim.RMSprop(model.parameters(), lr=learning_rate) elif optimizer_name == "SGD": optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate) print(f"Optimizer: {optimizer_name}") # 训练 for epoch in range(num_epochs): y_predicted = model(X) loss = criterion(y_predicted, y) loss.backward() optimizer.step() optimizer.zero_grad() predictions[optimizer_name] = model(X).detach().numpy()
内容的提问来源于stack exchange,提问作者joaovitorpigozzo
相关产品推荐
相关产品推荐

