【问题标题】:training by batches leads to more over-fitting批量训练会导致更多的过拟合
【发布时间】:2020-04-09 13:43:09
【问题描述】:

我正在训练一个序列到序列 (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))

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

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

optimizer=torch.optim.Adam(model.parameters(), lr=learning_rate)
criterion = nn.MSELoss(reduction='mean')

【问题讨论】:

  • 你的批量大小是多少?
  • 如果您的 batch_size 很小,那么就好像您正在逐个查看每个单词,因此您的模型会过拟合。根据您的计算机内存,我建议 batch_size 为 32/64 或 2^{i} 的倍数。出于好奇,您当前的 batch_size 是多少?
  • 你能把memory errors也发一下吗?因为它有助于理解并使用它来重现问题
  • 您使用哪种优化器?
  • 根据有关的错误永远记住:有多种选择要处理,但更合适的解决方案是因为 mini-batch 的数据不适合到GPU memory只需减小批量大小(它肯定会起作用)。当我为cifar10 数据集设置batch size = 256 时,我得到了同样的错误;然后我设置了batch size = 128,就解决了。尝试将批量大小从 1024 减少到 512。看看它是否有效。

标签: python machine-learning neural-network pytorch training-data


【解决方案1】:

批量大小会影响正则化。一次只训练一个例子非常嘈杂,这使得过度拟合变得更加困难。批量训练可以使一切变得平滑,从而更容易过度拟合。翻译回正则化:

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

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

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

  2. 学习率不会太高,不会发散。该模型只会更快更有效地训练。如果模型太大而无法拟合数据,则训练误差将变为 0,但验证误差会因过度拟合而爆炸式增长。


更新

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

每次调用loss.backward() 都会累积梯度,直到你用optimizer.zero_grad() 重置它。当您调用optimizer.step() 时,它将根据它累积的任何内容进行操作。

按照您的代码编写方式,每次通过内循环时调用loss.backward(),然后在重置前在外循环中调用optimizer.step()。所以梯度已经在批次中的所有示例上累积,也就是求和,而不是一次仅一个示例。

在大多数假设下,这将使批量累积梯度大于单个示例的梯度。如果梯度全部对齐,对于 B 批次,它将大 B 倍。如果梯度是i.i.d.,那么它将更像sqrt(B) 的倍大。

如果您不考虑这一点,那么您实际上已通过该因素提高了学习率。其中一些将通过大批量的平滑效应得到缓解,然后可以容忍更高的学习率。较大的批次会减少正则化,较大的学习率会将其添加回去。但这不会是完美的补偿,因此您仍需要进行相应的调整。

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


Leslie N. Smith 撰写了一些关于超参数调整方法的优秀论文。一个很好的起点是A disciplined approach to neural network hyper-parameters: Part 1 -- learning rate, batch size, momentum, and weight decay。他建议您先阅读图表,这些图表做得非常好。

【讨论】:

  • 我对此事的所有研究都将我引向了正则化主题。你的回答也暗示了这一点,如果你能详细说明一下对于现在累积的梯度来说学习率很高的第一点,那将非常有帮助。
  • @YehdhihANNA 我很高兴这是在正确的轨道上。我已经用关于梯度累积的更多细节更新了我的答案。如果您需要任何其他说明,请告诉我!
  • 非常感谢您提供的 extrq 详细信息。顺便说一句,你可以放一个链接到重新调整学习率的教程(亚当优化器不是默认这样做的吗?)
  • 这其实是一个常见的误解。 Adam 将帮助网络的不同部分进行同步调整和训练,但调整整体学习率仍然至关重要。我已经用我最喜欢的关于这个主题的论文更新了我的答案。
猜你喜欢
  • 2018-06-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-25
  • 2017-12-05
  • 2018-12-06
  • 1970-01-01
相关资源
最近更新 更多