PGN 网络可用于文本生成,文本生成任务是从序列到序列的模型,马上就想到了 Seq2Seq 架构的模型。当我们要实现一个文本摘要的文本生成任务时,基本思路是什么样的呢?
- 输入一串文本到编码器,提取句子的语义表示向量
- 由解码器在编码器对句子理解的基础上来生成目标的文本
具体的过程可以这么理解:
- 我们先构建一个词表,当然我们会去除一些低频的词,这是由于低频词由于出现的频率很低,很难得到有效的训练。
- 将输入文本进行数值化,即: 转换为索引值序列。
- 然后数据送入编码器的词嵌入层,循环网络层得到各个词的语义表示,以及最后的隐藏状态向量。我们可以把经过循环网络层得到的各个时间步的隐藏状态向量理解为每个词在句子中的语义表示,把最终时间步生成的向量理解为对整个句子含义的浓缩的表示。
- 然后到了解码器,解码器将编码器最后时间步的输出作为初始隐藏状态,然后计算和编码器各个时间步输出的注意力张量,拼接到输入作为解码器的输出,得到预测结果。
但是,这么个思路有个问题,问题出现在我们构建的词典上。大家想一想,我们几乎在所有 NLP 任务之前都要构建词典,训练词向量。在构建词典时,由于某些词汇在语料中出现的频率过低,比如出现次数低于 5 次,所以会将这些低频的词从词典中去除,这就带来一个问题了。
回到 Seq2Seq 中,由于字典中不存在低频词,意味着我们的解码器无法预测出这部分不在词典中的词(oov,out of vocabulary),我们说这些词只是出现频率低,不利于训练,并不是说这些词一点也没有用。我们在生成文本时,有时候还得生成这些词,才能使得生成的句子更加合理一些,那怎么办 ?
PGN 网络就能够解决这样的问题,它是如何解决的呢?
我们观察上图会发现,图中多了一个 Pgen,这个 Pgen 的计算是由注意力机制计算出张量和解码器对应时间步输出的隐藏状态张量得来的。
这个 Pgen 值计算出之后,会使用 sigmoid 函数将其变为 Pgen 权重和 (1-Pgen) 权重,这俩权重主要是为了将注意力计算出的各个词的概率分布(包括OOV)和解码器输出的概率(不包括OOV)分布合并在一起得到最终的包含了输入序列中 oov 词和词表中所有的词的概率分布。这样,我们最终的得到的概率分布就可以预测出一些词表不存在的词了。所以说,PGN 网络在 Seq2Seq 基本结构基础上,增加了 Pgen 解决了 OOV 词的问题。
假设我们最终预测出的某个词(OOV)的概率很低,在反向传播时,就可以调整 Pgen 里的相关参数进而影响到 OOV 词在最终概率分布中的概率值。
在该网络中,还存在一种对注意力的惩罚机制。如果在预测每个词时,我们发现注意力机制总是经常注意到少数的一些词,对于这些词则进行惩罚,降低对其的关注。
另外对解码的输出结果也要进行一些优化,我们知道目前模型的输出主要依据的是一种贪心思想,即每一时间只输出当前概率值最大的结果,但是这样在很多场景下发现生成的句子并不是很好。如果使用穷举法则计算量太大,所以我们最终使用 BeamSearch 算法来优化模型最后的输出结果,注意该算法只用在模型的 eval 时,训练时由于已经指定的目标值,所以是不需要的。
所以,我们可以把 PGN 网络理解为 Seq2Seq + 注意力 + Pgen + 注意力惩罚机制(Coverage机制)+BeamSearch 的一种网络模型。