文章目录
- 1 什么是Text Style Transfer
- 2 Cycle GAN
- 2.1 Gumbel-softmax
- 2.2 Continuous Input for Discriminator
- 2.3 Reinforcement Learning
- 2.4 效果
- 3 Star GAN
- 4 Feature Disentangle
- 5 Unsupervised Abstractive Summarization
- 6 Unsupervised Translation
- 7 Unsupervised Speech Recognition
本文为李弘毅老师【Text Style Transfer】的课程笔记,课程视频youtube地址,点这里👈(需翻墙)。
下文中用到的图片均来自于李宏毅老师的PPT,若有侵权,必定删除。
文章索引:
上篇 - 7-5 Multilingual BERT
下篇 - 7-7 Deep Learning for Coreference Resolution
总目录
1 什么是Text Style Transfer
style transfer这个概念对我们而言并不陌生,就算不是做技术的,也在日常生活中会看到过一些图像风格转换的东西,比如把正常的照片变成梵高风格的画等等。语音上的风格转换我们在之前讲voice conversion的时候也由讲到过,比如把男声变成女声就是一种风格转换。
而文本的风格转换一个典型的例子就是正面情绪的语言和负面情绪语言的相互转换。不过,文本风格转换的实际应用场景要比我们想象的多得多。
2 Cycle GAN
文本风格转换用到的技术也是cycle gan,我们会需要一个generator(G),G会吃一个负面的句子,然后吐出一个正面的句子;我们也会需要一个discriminator(D),D已经用一堆句子训练过了,知道什么是正面的句子,什么是负面的句子,把G生成的句子丢给D,D判断G生成的句子是正面的还是负面的;同时我们还需要一个generator,这里我们可以将其称之为reconstructor®,他就是要把G生成的句子再变回换来的句子,没有R的话,G只要一直生成同一句话就可以骗过D了。
我们的G是一个seq2seq的模型,这个大家应该已经很熟悉了,它就是输入文本的第一个token的feature和前一个token,然后RNN会输出这个time step预测出来的token distribution,在distribution中进行sample,最后得到预测的一串tokens,把这些tokens输入D,D就会吐出一个scalar,就表示现在输出的句子,是不是有某种风格,比如是不是正面情绪的句子。我们一般会把G和D串起来end2end这样train,但在这里,由于sample这个过程是不可微的,所以不能串起来train。
那怎么办呢?没有了D这个下游任务,loss怎么算?这其实是一个比较大的话题,这里我们只略讲一下。解决方法目前大致可以分为三大类:Gumbel-softmax,Continuous Input for Discriminator和Reinforcement Learning。Gumbel-softmax不常用,Continuous Input for Discriminator和Reinforcement Learning孰强孰弱不好说。
2.1 Gumbel-softmax
Gumbel-softmax这一招没有后面那两招那么流行,它用了VAE中叫做reparameterization的trick,使得不可微分的sample变成可微分的了。具体怎么回事,李老师也没说,想了解的小伙伴可以参考GANS for Sequences of Discrete Elements with the Gumbel-softmax Distribution和RelGAN:
Relational Generative Adversarial Networks for Text Generation。
2.2 Continuous Input for Discriminator
第二招非常直接,既然sample这个步骤不可微,那么我们就干脆跳过这个步骤,把token distribution直接塞给D,这不就可以微分了吗?
那这样做的问题是什么呢?问题就是,D在预训练是看到的数据都是one-hot的,而G生成的distribution不是one-hot的,D只需要学到说one-hot的是real的,不是one-hot的是generated的就可以了。这样就会发现模型什么都没学到。所以一般还会用WGAN中类似的技术,给D加一些约束条件,让它不那么重要,那模型也许就可以学到些东西。还有一种做法是,把distribution经过embedding之后变成特征向量,这样模型就没法一下子从表面认出来了。
2.3 Reinforcement Learning
最后一招就是用RL,怎么用RL呢?我们只要把不能微分的地方用RL去做就可以了,这里的话,就是把sample出来的token当作action,把D当作environment,然后scalar当作reward就可以了。
但是这里的D是在更新的,也就是environment一直在变,这会让RL非常难train,同时GAN也是非常难train的,难上加难会让这个训练非常困难。所以我们需要一些tips,这个可以参考ScratchGAN,上面罗列了一些可用的技巧。其中有一个必用的技巧叫做SeqGAN-step,这里稍微说一下。
RL之所以难train是因为当D输出一个低分数,从G的角度来说,它并不知道为什么分数这么低,它不知道句子的哪个部分导致了分数低。所以我们希望每生成一个token都可以有一个评分,这样G就知道哪里错了。
让D在每个generation step都做出评价的方法这里不细讲,有兴趣的小伙伴可自行查资料学习一下,主要有三种:
- Monte Carlo (MC) Search
- Discriminator For Partially Decoded Sequences
- Step-wise evaluation
2.4 效果
Cycle GAN产生的句子是长什么样子呢?李老师的学生做了实验之后的结果如下所示。出来的结果还是有点奇怪的,不过也有几分道理。
3 Star GAN
当我们需要在多种风格之间转换时,用Cycle GAN就需要train很多的G和D,这样太麻烦了。图像和语音中一般会考虑使用Star GAN。Sytle Transformer就是文字版的Star GAN。这里只是提一下多个风格之间转换该怎么办,想了解详情的小伙伴可以自行看论文。
4 Feature Disentangle
我们在做voice conversion的时候除了GAN之外,还有feature disentangle的方法。这个方法也可以同样用在text上,我们的目标就是train一个content encoder只抽取content的特征,同时train一个style encoder只抽取style的特征。然后要换style,只需要把style这部分的特征换掉就可以了。不过这种方法近几年并没有被用的很多,效果不如GAN,因为要做句子的embedding,把句子压到一个latent space是比较困难的。
既然content encoder把句子做embedding比较困难,那不妨我们就让content encoder输出离散的特征,也就是句子,然后我们希望content encoder可以学会把风格有关的一些词汇给盖掉。这样再结合style的特征,decoder只需要把盖掉的部分替换成对应风格的词汇即可。
不过新的问题又来了,如何找到这个和风格有关的词汇并盖掉呢?有兴趣的小伙伴可以参考Delete, Retrieve, Generate: A Simple Approach to Sentiment and Style Transfer和Unpaired Sentiment-to-Sentiment Translation: A Cycled Reinforcement Learning Approach。
5 Unsupervised Abstractive Summarization
风格转换不光可以把正面情绪的句子转化为负面情绪的句子,如果我们把完整的文章作为一种风格,摘要作为一种风格,那么我们就可以利用风格转换的方法来做无监督的摘要生成。有监督的摘要生成需要收集大堆的成对的数据,成本很高,无监督无疑是大家的福音。
做法与之前情绪转换的做法一样,我们需要有一个G把文章转成摘要;然后需要一个D来判别输入的是不是摘要;最后还需要一个R来吧G生成的摘要重新变回原来的文章。
那么,这种做法做出来的摘要效果如何呢?下面是某篇文章中的结果,用的评价指标是ROUGE,越大表示和人写的摘要越接近,越好。第一行是有监督的结果,是效果最好的。第二行是取文章前几句话的结果,相当于是个基于规则的baseline。第三行是用同一个数据集里的文章和摘要做训练得到的结果,第四行是不同数据集的文章和摘要训练得到的结果。可见无监督的结果,还行。
6 Unsupervised Translation
我们也可以把不同语言当作不同的风格,来实现无监督的翻译。
无监督的翻译有一种做法就是利用word embedding取逐个词地翻译。假设我们已经有了中文的embedding和英文的embedding,如下图所示,那么很有可能两个语言的embedding之间只需要一个线性变换就可以把一种语言的embedding对应到另一种语言上,比如下图这样的就只需要经过一个逆时针的旋转即可使得对应意思的词重合。
那么我们的问题就变成了如何找这个线性变换WWW。不同语言之间有一些相同token且相同意思的词汇,比如阿拉伯数字,那我们就可以根据阿拉伯数字的embedding去学习这个WWW。我们也可以利用GAN的技术,把WWW当作一个Generator,然后再训练一个Discriminator来判别经过G之后的embedding和右边的接近程度。甚至也有人直接用PCA,这两边的embedding就对齐了。
下面来说一下用类似GAN的技术来做Unsupervised Translation的方法。假设我们有语言A和语言B。我们分别对语言A和语言B训练各自的自编码器,得到encoder A,decoder A,encoder B和decoder B。在训练的时候,我们会对输入加一些noise,防止模型变成一个只会”复制粘贴“的模型。然后,我们想要在encoder A中输入语言A的句子之后,再经过decoder B就得到句子在语言B中的翻译结果。
这说起来轻松,但谁也没法保证encoder A和encoder B是按照同样的方式去encoder的。所以我们需要一些tricks。
第一个trick,就是加一个discriminator,用来区别encoder的输出是encoder A的还是encoder B的。这样一来,就可以迫使encoder A和encoder B尽可能用同样的方式去encode。我们希望这样做之后,decoder B不仅可以看懂encoder B的结果,也可以看懂encoder A的结果。
第二个trick是,我们把encoder A的输出输入到decoder B,然后把decoder B的输出输入到encoder B,最后把encoder B的输出输入到decoder A,希望这种情况下encoder A的输入和decoder A的输出越接近越好。但是这样模型并不能具备翻译的能力,它可能会把“再见”对应成“How are you”。
所以我们需要另一个模型,这个模型是一个烂一点的模型,它可以就是刚才讲到的用word embedding做mapping得到的模型,用这个模型来代替encoder A和decoder B,这样可以在训练前期把结果引导到相对正确的句子上去训练encoder B和decoder A,在后期train的差不多了之后,再固定住encoder B和decoder A,来训练encoder A和decoder B,如此交替迭代。
这样做出来的结果如下图所示,有监督的翻译训练会随着训练样本的增加而越来越好,但无监督的翻译训练再刚开始就会有一个比较好的结果,随着训练样本的增加,效果提升并不明显。这样的结果挺奇怪的。
7 Unsupervised Speech Recognition
最后要讲的是无监督的语音辨识,也就是把语音认为是一种风格,文字认为是一种风格。用到的方法还是和之前一样,只不过有语音进来所以会做一些处理,会把phoneme作为中间媒介。然后这部分就不细讲了,有兴趣的小伙伴去听一下李老师的课吧,李老师讲的比较简略,我也一知半解。
总之,用这种方法可以得到还不错的结果,接近有监督的语音识别。