PyTorch神经网络训练后期损失曲线出现振荡的原因探究
为何我的PyTorch神经网络训练后期会出现损失曲线振荡?
我使用了一个基础的序列神经网络,搭配Adam optimizer,学习率设为0.0001。
模型代码
class ANN(nn.Module): def __init__(self): super().__init__() self.fc1 = nn.Linear(in_features=956, out_features=500) self.fc2 = nn.Linear(in_features=500, out_features=500) self.fc3 = nn.Linear(in_features=500, out_features=100) self.output = nn.Linear(in_features=100, out_features=2) def forward(self, x): x = F.relu(self.fc1(x)) x = F.relu(self.fc2(x)) x = F.relu(self.fc3(x)) x = self.output(x) return x
损失函数、优化器及训练代码
criterion = nn.CrossEntropyLoss() optimizer = torch.optim.Adam(model.parameters(), lr=0.0001) epochs = 400 loss_arr = [] for i in range(epochs): y_hat = model.forward(X_train) loss = criterion(y_hat, y_train) loss_arr.append(loss) if i % 10 == 0: print(f'Epoch: {i} Loss: {loss}') optimizer.zero_grad() loss.backward() optimizer.step()
损失曲线

我预期损失曲线会随训练正常下降,或在模型过拟合时骤升,但实际后期出现振荡。由于数据量不足,无法划分验证集监测过拟合,只能通过反复训练来避免过拟合。
可能的原因及解决办法
学习率适配问题:训练后期模型参数接近最优解时,固定的0.0001学习率可能导致参数在最优值附近来回跳动。可以引入学习率衰减机制,比如用
ReduceLROnPlateau,当损失连续多轮不再下降时自动降低学习率:scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, 'min', patience=5, factor=0.5) # 训练循环中添加 scheduler.step(loss)模型容量过剩:你的模型有两层500维的隐藏层,对于小数据集来说容量过大,容易在后期拟合数据中的噪声,引发损失振荡。可以尝试:
- 缩小隐藏层维度,比如把500改成256或128;
- 在隐藏层后加入Dropout层抑制过拟合:
def forward(self, x): x = F.relu(self.fc1(x)) x = nn.Dropout(0.2)(x) # 添加Dropout x = F.relu(self.fc2(x)) x = nn.Dropout(0.2)(x) x = F.relu(self.fc3(x)) x = self.output(x) return x
全量训练的不稳定性:当前用全量数据计算梯度并更新参数,后期梯度波动会直接导致参数大幅跳动。改成小批量训练,用
DataLoader拆分数据,每次用一个batch更新,让梯度更平稳:from torch.utils.data import TensorDataset, DataLoader dataset = TensorDataset(X_train, y_train) dataloader = DataLoader(dataset, batch_size=32, shuffle=True) # 修改训练循环 for i in range(epochs): total_loss = 0 for batch_x, batch_y in dataloader: y_hat = model(batch_x) loss = criterion(y_hat, batch_y) total_loss += loss.item() optimizer.zero_grad() loss.backward() optimizer.step() avg_loss = total_loss / len(dataloader) loss_arr.append(avg_loss) if i % 10 == 0: print(f'Epoch: {i} Loss: {avg_loss}')数据预处理缺失:输入特征维度达956,若不同特征尺度差异大,会干扰梯度更新的稳定性。确保对输入数据做标准化/归一化,比如用
StandardScaler将特征缩放到均值0、方差1的范围。标签格式验证:CrossEntropyLoss要求目标标签是类别索引(不是one-hot编码),如果
y_train格式错误,也可能导致损失异常波动,检查标签的形状和数值范围是否符合要求。
内容的提问来源于stack exchange,提问作者Mudit Aggarwal
相关产品推荐
相关产品推荐

