我正在训练一个序列到序列(seq2seq)模型,并且我有不同的input_sequence_length
值来进行训练。
对于10
和15
的值,我得到了可接受的结果,但当我尝试使用20
进行训练时,我遇到了内存错误,所以我切换到按批次训练,但模型出现了过拟合,验证损失激增,即使使用了累积梯度,我也得到了同样的行为,所以我在寻找更准确的更新方法的提示和线索。
这是我的训练函数(仅包含批次部分):
if batch_size is not None: k=len(list(np.arange(0,(X_train_tensor_1.size()[0]//batch_size-1), batch_size ))) for epoch in range(num_epochs): optimizer.zero_grad() epoch_loss=0 for i in list(np.arange(0,(X_train_tensor_1.size()[0]//batch_size-1), batch_size )): # by using equidistant batch till the last one it becomes much faster than using the X.size()[0] directly sequence = X_train_tensor[i:i+batch_size,:,:].reshape(-1, sequence_length, input_size).to(device) labels = y_train_tensor[i:i+batch_size,:,:].reshape(-1, sequence_length, output_size).to(device) # Forward pass outputs = model(sequence) loss = criterion(outputs, labels) epoch_loss+=loss.item() # Backward and optimize loss.backward() optimizer.step() epoch_loss=epoch_loss/k model.eval validation_loss,_= evaluate(model,X_test_hard_tensor_1,y_test_hard_tensor_1) model.train() training_loss_log.append(epoch_loss) print ('Epoch [{}/{}], Train MSELoss: {}, Validation : {} {}'.format(epoch+1, num_epochs,epoch_loss,validation_loss))
编辑:这里是我正在使用的训练参数:
batch_size = 1024 num_epochs = 25000learning_rate = 10e-04optimizer=torch.optim.Adam(model.parameters(), lr=learning_rate)criterion = nn.MSELoss(reduction='mean')
回答:
批次大小会影响正则化。一次训练一个样本会非常嘈杂,这使得过拟合变得更加困难。按批次训练会使一切变得平滑,从而更容易过拟合。回到正则化来说明:
- 较小的批次增加正则化效果。
- 较大的批次减少正则化效果。
我还对你的学习率感到好奇。每一次调用loss.backward()
都会累积梯度。如果你设置的学习率是期望一次处理一个样本,并且没有因为批次累积而降低它,那么会发生以下两种情况之一。
-
学习率对于现在累积的梯度来说太高了,训练会发散,训练和验证误差都会激增。
-
学习率不会太高,不会发生发散。模型只会训练得更快更有效。如果模型对于所拟合的数据来说太大了,那么训练误差会降为0,但验证误差会因为过拟合而激增。
更新
这里提供了更多关于梯度累积的细节。
每次调用loss.backward()
都会累积梯度,直到你用optimizer.zero_grad()
重置它。它会在你调用optimizer.step()
时根据累积的内容进行操作。
根据你的代码编写方式,你在内循环的每次通过中调用loss.backward()
,然后在外循环中调用optimizer.step()
之前重置。所以梯度已经在批次中的所有样本上累积,而不是一次处理一个样本。
在大多数假设下,这会使批次累积的梯度比单个样本的梯度更大。如果所有梯度都是对齐的,对于B个批次,它会大B倍。如果梯度是独立同分布的,那么它会大约是sqrt(B)
倍。
如果你不考虑这一点,那么你实际上已经按该因子增加了你的学习率。批次增大的平滑效果会减轻一些影响,这可以容忍更高的学习率。较大的批次减少正则化,较大的学习率会增加正则化。但这不会完全抵消,所以你仍然需要相应地调整。
一般来说,每当你更改批次大小时,你也需要重新调整学习率以进行补偿。
Leslie N. Smith撰写了一些关于系统化超参数调整方法的优秀论文。一个很好的起点是A disciplined approach to neural network hyper-parameters: Part 1 — learning rate, batch size, momentum, and weight decay。他建议你从阅读图表开始,这些图表做得非常好。