RNN 文本生成:如何平衡训练/测试丢失与验证丢失?

Posted

技术标签:

【中文标题】RNN 文本生成:如何平衡训练/测试丢失与验证丢失?【英文标题】:RNN Text Generation: How to balance training/test lost with validation loss? 【发布时间】:2020-08-04 12:55:36 【问题描述】:

我正在做一个涉及为文本生成实现字符 RNN 的简短项目。我的模型使用单个 LSTM 层,具有不同的单位(在 50 到 500 之间搞乱),以 0.2 的速率退出和 softmax 激活。我正在使用学习率为 0.01 的 RMSprop。

我的问题是我找不到表征验证损失的好方法。我正在使用 0.3 的验证拆分,我发现验证损失仅在几个 epoch(可能是 2-5 左右)之后就开始变得恒定,而训练损失不断减少。 验证损失在这类问题中是否占很大比重?模型的目的是生成新字符串,因此用其他字符串量化验证损失似乎……毫无意义?

我很难真正找到最好的模型,因为从质量上我感觉最好的模型训练的时间比验证损失停止变化所需的时间多,而且训练时间也比训练损失所需的时间少开始增加。我非常感谢您对这个问题的任何建议以及任何关于 RNN 文本生成的一般建议,特别是关于辍学和过度拟合的建议。谢谢!

这是为每个时期拟合模型的代码。回调是一个自定义回调,只打印一些测试。我现在意识到 history_callback.history['loss'] 可能是训练损失不是吗...

for i in range(num_epochs):
    history_callback = model.fit(x, y,
          batch_size=128,
          epochs=1,
          callbacks=[print_callback],
          validation_split=0.3)
    loss_history.append(history_callback.history['loss'])
    validation_loss_history.append(history_callback.history['val_loss'])

我对这个模型的意图不是从训练数据中复制句子,而是从我正在训练的同一分布中生成句子。

【问题讨论】:

Test loss 不断减少? 考虑通过以下两种方式澄清您的问题:1) 包含一些实际或伪代码,显示您如何使用训练/测试/验证数据。并且 2)添加关于你对这个文本生成器的意图的细节:粗略地说,如果你希望你的模型擅长反刍训练数据中的句子,那么你关心的是训练损失,你不需要担心验证数据。或者,如果您希望您的模型擅长为来自与训练数据相同分布的不可见数据生成文本,那么您需要尽可能高的验证准确度。 根据更新,您关心的是从您的训练数据中采样的分布的性能(即,您想要泛化)。但是,根据您的问题,听起来验证损失在某个点之后停止变化。它是否正确?如果它是正确的,那么您的模型的泛化(大约)与您训练的时间无关,因此您最好在达到验证损失高原时停止。 验证损失在大约 5 个时期内下降到一个常数,然后慢慢开始增加,所以我认为我需要像你建议的那样使用提前停止。我对不同时期之间的训练损失和测试损失之间的区别感到困惑,所以我会弄清楚这一点。谢谢! 没问题!欢迎来到 SO!另一方面,对您认为有用的 [1] cmets、问题和答案进行投票可以帮助其他人找到好的信息,并且是对贡献者的支持。 [1]:***.com/help/privileges/vote-up 【参考方案1】:

    是的,history_callback.history['loss'] 是训练损失,history_callback.history['val_loss'] 是验证损失。

    是的,Validation Loss 在这类问题中占有重要地位,因为您只是不想复制在训练期间给出的句子,但您想从训练数据并在看到新数据时生成新句子。

    根据您在问题中提到的信息以及从 cmets 确定的见解(感谢 Brian Bartoldson),可以理解您的模型是 overfitting。除了EarlyStoppingdropout,您还可以尝试下面提到的技术来缓解overfitting 问题。

3.a. Shuffle 数据,通过在 model.fit 中使用 shuffle=True。代码如下所示

3.b。使用recurrent_dropout。例如,如果我们在Recurrent Layer (LSTM) 中将Recurrent Dropout 的值设置为0.2,则意味着它将只考虑Time Steps 中的80% 用于该Recurrent Layer (LSTM)

3.c。使用Regularization。您可以尝试l1 Regularizationl1_l2 Regularization 以及LSTM 层的参数kernel_regularizerrecurrent_regularizerbias_regularizeractivity_regularizer

使用ShuffleEarly StoppingRecurrent_DropoutRegularization的示例代码如下所示:

from tensorflow.keras.regularizers import l2
from tensorflow.keras.models import Sequential

model = Sequential()

Regularizer = l2(0.001)

model.add(tf.keras.layers.LSTM(units = 50, activation='relu',kernel_regularizer=Regularizer ,
    recurrent_regularizer=Regularizer , bias_regularizer=Regularizer , activity_regularizer=Regularizer, dropout=0.2, recurrent_dropout=0.3))

callback = tf.keras.callbacks.EarlyStopping(monitor='val_loss', patience=15)

history_callback = model.fit(x, y,
          batch_size=128,
          epochs=1,
          callbacks=[print_callback, callback],
          validation_split=0.3, shuffle = True)

希望这会有所帮助。快乐学习!

【讨论】:

以上是关于RNN 文本生成:如何平衡训练/测试丢失与验证丢失?的主要内容,如果未能解决你的问题,请参考以下文章

Tensorflow - 使用经过训练的 RNN 生成文本

Tensorflow 对象检测 API - 验证丢失行为

在 Dynamic_RNN 中使用可变序列长度时是不是应该进行丢失屏蔽

如何在不丢失身份验证的情况下模拟Session.request?

Tensorflow:成功恢复检查点后丢失重置

利用分布类防止EF更新模型丢失验证信息