【自然语言处理】SeqGAN的探索(踩坑)记录

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/tudaodiaozhale/article/details/90229998

前言

SeqGAN是2017年《SeqGAN: Sequence Generative Adversarial Nets with Policy Gradient》这篇论文提出的模型,使用了强化学习的策略梯度解决了之前GAN只能应用在生成器输出为连续值的问题(文本中词与词之间的表示是离散的)。
属于比较开创的工作,之后的许多工作都是在这篇文章的基础进行的。今天主要是想研究SeqGAN这么久以来的一个踩坑记录的总结,主要是要讨论关于蒙特卡洛搜索树在这篇文章是怎么工作的。

内容

在这个模型中,分为生成器和判别器。

判别器

判别器是一个二分类器,接收的是一个生成器生成的序列(句子),预训练和对抗训练都是由交叉熵作为目标函数进行训练。

生成器

生成器是一个基于循环递归神经网络的语言模型(RNNLM)。预训练是使用极大似然估计法(交叉熵作为目标函数)。
在对抗训练中,该篇论文作者将其视为一个序列决策过程,每个序列状态是已生成的序列,使用策略梯度进行训练。这部分细节别的博客讲了很多,本文不再赘述,接下来主要描述下蒙特卡洛搜索树的过程。
在策略梯度的训练过程中,需要对每个状态序列给于一个奖励(reward)。
蒙特卡洛搜索树就是基于当前的序列状态(未生成完整的句子)进行补全。
这里举个例子。
我们将" 今天 的 天气 真的 非常好"视为一个句子。
在这里我们需要得到每个单词的奖励。
在"“状态序列时,进行补全,得到” 我 爱 吃 苹果 “(举例的),扔到判别器进行判别得到的概率作为”“的奖励。
在” 今天 “状态序列时,进行补全,得到” 今天 适合 野炊 “(举例的),扔到判别器进行判别得到的概率作"今天"的奖励。
在” 今天 的"状态序列时,进行补全,得到" 今天 的 美女 很多 “(举例的),扔到判别器进行判别得到的概率作为"的"奖励。
在” 今天 的 天气"状态序列时,进行补全,得到" 今天 的 天气 不是 非常差"(举例的),扔到判别器进行判别得到的概率作为"天气"奖励。

在" 今天 的 天气 真的 非常好"状态序列时,直接扔到判别器进行判别得到的概率作为"非常好"奖励。
那么,如何这个用代码实现,请看下面的片段。
在" 今天 的"状态序列时,我们像训练(dynamic_rnn)一样将"" 今天"输入(注意,没有输入"的"),得到最后一个隐含状态。然后将隐含层状态和"的"作为推理的输入,得到输出词,再把输出的词和当前的隐含状态想做下一步的输入。
那这里有需要注意的地方是,经过蒙特卡洛搜索树的句子扔到判别器得到概率,记得要和用判别器训练时的句子一样。
比如" 这个 饭菜 真的 很好吃 “这样的句子去训练判别器,经过蒙特卡洛搜索树的句子” 这个 饭菜 真的 很好吃 "(没有)会立即被判别器判别为假的句子(判别器非常记仇,一旦训练时句子有,然后没有的句子会判别为假)。

不足

SeqGAN的模型提出确实提高了文本生成的质量,但是目前也存在着两个问题。
1.在训练过程中可以发现,判别器太好,以至于生成器生成的句子常常得到的都是被判别为假的(概率非常小),而这个是用来作为奖励进行训练的。这样会造成训练低下,有些论文称这个现象为梯度消失(vanishing gradient)。
2.模式崩溃,这是原生GAN就存在的问题,即在让生成器学习真实样本的数据分布时只能学到一部分,以至于句子常常是重复的。

猜你喜欢

转载自blog.csdn.net/tudaodiaozhale/article/details/90229998