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

我正在训练一个序列到序列(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 = 25000learning_rate = 10e-04optimizer=torch.optim.Adam(model.parameters(), lr=learning_rate)criterion = nn.MSELoss(reduction='mean')

回答:

批次大小会影响正则化。一次训练一个样本会非常嘈杂,这使得过拟合变得更加困难。按批次训练会使一切变得平滑,从而更容易过拟合。回到正则化来说明:

  • 较小的批次增加正则化效果。
  • 较大的批次减少正则化效果。

我还对你的学习率感到好奇。每一次调用loss.backward()都会累积梯度。如果你设置的学习率是期望一次处理一个样本,并且没有因为批次累积而降低它,那么会发生以下两种情况之一。

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

  2. 学习率不会太高,不会发生发散。模型只会训练得更快更有效。如果模型对于所拟合的数据来说太大了,那么训练误差会降为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。他建议你从阅读图表开始,这些图表做得非常好。

Related Posts

使用LSTM在Python中预测未来值

这段代码可以预测指定股票的当前日期之前的值,但不能预测…

如何在gensim的word2vec模型中查找双词组的相似性

我有一个word2vec模型,假设我使用的是googl…

dask_xgboost.predict 可以工作但无法显示 – 数据必须是一维的

我试图使用 XGBoost 创建模型。 看起来我成功地…

ML Tuning – Cross Validation in Spark

我在https://spark.apache.org/…

如何在React JS中使用fetch从REST API获取预测

我正在开发一个应用程序,其中Flask REST AP…

如何分析ML.NET中多类分类预测得分数组?

我在ML.NET中创建了一个多类分类项目。该项目可以对…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注