Seq2Seq 模型学会在几次迭代后只输出 EOS 令牌 (<\s>)
Posted
技术标签:
【中文标题】Seq2Seq 模型学会在几次迭代后只输出 EOS 令牌 (<\\s>)【英文标题】:Seq2Seq model learns to only output EOS token (<\s>) after a few iterationsSeq2Seq 模型学会在几次迭代后只输出 EOS 令牌 (<\s>) 【发布时间】:2019-03-04 21:32:17 【问题描述】:我正在使用NMT 创建一个在Cornell Movie Dialogs Corpus 上训练的聊天机器人。
我的代码部分来自 https://github.com/bshao001/ChatLearner 和 https://github.com/chiphuyen/stanford-tensorflow-tutorials/tree/master/assignments/chatbot
在训练期间,我打印一个随机输出答案,从批次中馈送到解码器,以及我的模型预测的相应答案,以观察学习进度。
我的问题:仅经过大约 4 次迭代训练,模型就学会了在每个时间步输出 EOS 令牌 (<\s>
)。即使在训练继续进行时,它也始终将其输出为响应(使用 logits 的 argmax 确定)。偶尔,很少,模型会输出一系列周期作为其答案。
我还在训练期间打印了前 10 个 logit 值(不仅仅是 argmax),以查看其中是否存在正确的单词,但它似乎是在预测词汇中最常见的单词(例如 i、you、 ?, .)。即使是前 10 个单词在训练期间也没有太大变化。
我已确保正确计算编码器和解码器的输入序列长度,并相应地添加了 SOS (<s>
) 和 EOS(也用于填充)令牌。我还在损失计算中执行masking。
这是一个示例输出:
训练迭代 1:
Decoder Input: <s> sure . sure . <\s> <\s> <\s> <\s> <\s> <\s> <\s>
<\s> <\s>
Predicted Answer: wildlife bakery mentality mentality administration
administration winston winston winston magazines magazines magazines
magazines
...
训练迭代 4:
Decoder Input: <s> i guess i had it coming . let us call it settled .
<\s> <\s> <\s> <\s> <\s>
Predicted Answer: <\s> <\s> <\s> <\s> <\s> <\s> <\s> <\s> <\s> <\s>
<\s> <\s> <\s> <\s> <\s> <\s> <\s> <\s>
经过几次迭代后,它决定只预测 EOS(很少预测某些时期)
我不确定是什么原因导致了这个问题,并且已经在这个问题上停留了一段时间。任何帮助将不胜感激!
更新:我让它训练了超过十万次迭代,它仍然只输出 EOS(和偶尔的周期)。几次迭代后,训练损失也没有减少(从一开始就保持在 47 左右)
【问题讨论】:
什么是“迭代”?是小批量吗?一个时代?无论哪种方式,这种行为都不会让我感到惊讶。当我训练 RNN 时,它们通常会经历一个阶段,在训练的早期,它们会重复输出相同的符号。解决方案可能只是您需要更长时间地训练模型。如果在训练了很多个 epoch 后这种行为仍然存在,那么可能是出了点问题。 这种情况下的迭代只是将梯度下降应用于单个随机批次。我让它训练了几千次迭代,预测的输出总是 EOS。即使我在训练过程中检查前 10 个 logits(不仅仅是用于预测输出的最大值),它似乎总是词汇中具有最高 logits 的频率最高(最常见)的单词。我不确定是什么导致了这个问题,因为我的代码基于NMT tutorial @myrtlecat 更新:我让它训练了超过十万次迭代,它仍然只输出 EOS(和偶尔的周期)。第一次迭代后训练损失也没有减少(保持在 47 左右) Noel,你有没有找到解决办法?我也面临同样的问题,我也遵循了@myrtlecat 的建议。我的模型获得了大约 98% 的准确率,然后下降到 5% 的准确率,然后又回升到 20%,但它仍然只是预测结束标记。我不知道为什么当它只输出始终是结束标记的 argmax 时精度甚至会发生变化 【参考方案1】:最近我也在研究 seq2seq 模型。 我之前遇到过你的问题,就我而言,我是通过改变损失函数来解决的。
你说你使用掩码,所以我猜你像我一样使用tf.contrib.seq2seq.sequence_loss
。
我改成tf.nn.softmax_cross_entropy_with_logits
,正常工作(而且计算成本较高)。
(编辑 05/10/2018。对不起,我需要编辑,因为我发现我的代码中有一个严重的错误)
tf.contrib.seq2seq.sequence_loss
可以很好地工作,如果 logits
,targets
, mask
的形状是正确的。
正如官方文档中定义的那样:
tf.contrib.seq2seq.sequence_loss
loss=tf.contrib.seq2seq.sequence_loss(logits=decoder_logits,
targets=decoder_targets,
weights=masks)
#logits: [batch_size, sequence_length, num_decoder_symbols]
#targets: [batch_size, sequence_length]
#weights: [batch_size, sequence_length]
好吧,即使形状不符合,它仍然可以工作。但结果可能很奇怪(很多#EOS #PAD...等)。
由于decoder_outputs
和decoder_targets
可能具有所需的相同形状(在我的情况下,我的decoder_targets
具有[sequence_length, batch_size]
的形状)。
所以尝试使用tf.transpose
来帮助你重塑张量。
【讨论】:
我也遇到了同样的问题,有人知道怎么解决吗?序列损失 logits 需要 softmaxed 吗?【参考方案2】:在我的情况下,这是由于优化器,我错误地设置了一个大的 lr_decay,使其不再正常工作。
检查 Lr 和 Optimizer / Scheduler 可能会有所帮助。
【讨论】:
以上是关于Seq2Seq 模型学会在几次迭代后只输出 EOS 令牌 (<\s>)的主要内容,如果未能解决你的问题,请参考以下文章
NLP⚠️学不会打我! 半小时学会基本操作 10⚠️ Seq2seq
NLP⚠️学不会打我! 半小时学会基本操作 10⚠️ Seq2seq