批量训练会导致更多的过拟合

Yeh*_*NNA 3 python machine-learning training-data neural-network pytorch

我正在训练一个序列到序列(seq2seq)模型,并且我有不同的值来训练input_sequence_length.

对于值1015,我得到了可以接受的结果,但是当我尝试使用 进行训练时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))
Run Code Online (Sandbox Code Playgroud)

编辑: 这是我正在训练的参数:

batch_size = 1024 
num_epochs = 25000
learning_rate = 10e-04

optimizer=torch.optim.Adam(model.parameters(), lr=learning_rate)
criterion = nn.MSELoss(reduction='mean')
Run Code Online (Sandbox Code Playgroud)

mcs*_*ner 8

批量大小影响正则化。一次对单个示例进行训练非常嘈杂,这使得过拟合变得更加困难。批量训练可以使一切变得平滑,从而更容易出现过拟合。转换回正则化:

  • 小批量增加了正则化。
  • 较大的批次会减少正则化。

我也很好奇你的学习率。每次调用loss.backward()都会累积梯度。如果您将学习率设置为一次期望一个示例,并且没有降低它以考虑批次累积,那么将会发生以下两种情况之一。

  1. 对于现在累积的梯度来说,学习率会太高,训练会发散,训练和验证错误都会爆炸。

  2. 学习率不会太高,不会出现任何发散。该模型只会更快、更有效地进行训练。如果模型对于拟合的数据来说太大,那么训练误差将变为 0,但验证误差将因过度拟合而爆炸。


更新

这是有关梯度累积的更多细节。

每次调用loss.backward()都会累积梯度,直到您使用 重置它optimizer.zero_grad()optimizer.step()当您调用时,它将根据它所积累的内容采取行动。

编写代码的方式是,loss.backward()每次通过内部循环都调用,然后optimizer.step()在重置之前调用外部循环。因此,梯度是在批次中的所有示例上累积的,即求和,而不仅仅是一次一个示例。

在大多数假设下,这将使批量累积的梯度大于单个示例的梯度。如果梯度全部对齐,对于B批次来说,会大B倍。如果梯度是独立同分布的,那么它会更大sqrt(B)

如果你不考虑这一点,那么你就已经有效地提高了你的学习率。其中一些问题将通过较大批次的平滑效应得到缓解,从而可以容忍更高的学习率。较大的批次会减少正则化,较大的学习率会增加正则化。但这并不是一个完美的补偿匹配,因此您仍然需要进行相应的调整。

一般来说,每当您更改批量大小时,您还需要重新调整学习率以进行补偿。


Leslie N. Smith撰写了一些关于超参数调整系统方法的优秀论文。一个很好的起点是神经网络超参数的规范方法:第 1 部分 - 学习率、批量大小、动量和权重衰减。他建议您首先阅读图表,这些图表做得非常好。