实验1

最首先的是上周提到的,VAE transformer出现了测试生成阶段的时候,不管随机采样的Encoder-output是啥,生成的结果都不变。
举例说明一下,比如说Decode的阶段,第一个decode的结果是根据【SOS】(句首标志符)的表示以及Encoder-output来解码。这个时候几乎所有的样本模型都预测为“上”(可能因为这个短文本数据集里面很多数据是对联,因此“上联”是句首最常出现的词,因此不考虑Encoder的结果预测为上。下图为测试阶段从随机正态分布里生成的结果,不管如何随机,生成结果一样。
21.10.10 VAETransformer进一步实验 - 图1
后续的预测也很显著的出现了组词的现象,即上一步是tokenA,则下一步不管原文都预测为tokenAtokenB常见搭配的tokenB。比如。输入”龙“则输出”井“,输入”游“则输出”记“,输入”为“则输出”何“,输入”插“则输出”秧“(下图中第一行是Decoder-input,第二行是Decoder-output,即输入CLS,输出”上“)
21.10.10 VAETransformer进一步实验 - 图2
于是我在Decoder-input里面,随机的替换输入为【MASK】,希望能够强迫模型去关注Encoder的结果,而不是自顾自的生成。
结果并没有改变,仍然出现了上述的现象,问题可能不在这里

实验2

在VAE Transformer里面,loss有交叉熵损失函数和KL散度损失,在默认的实现里,我的交叉熵使用的是平均,即在Seqlen和Batch上平均。而KL散度用的是Sum,就会导致KL的loss远大于交叉熵的loss,于是修改KL散度loss为平均。
训练阶段的生成质量显著提升,可见复原度远高于实验一。
21.10.10 VAETransformer进一步实验 - 图3
测试阶段,出现了正常的随机性(即不同的Encoder采样会带来不同的输出),但是输出的结果很显著的变差了。
21.10.10 VAETransformer进一步实验 - 图4

结论

  1. 对于实验1和2,我的理解是,实验1由于KLloss太大了(求和而不是平均),导致encoder output产生的随机范围太小了,压缩在一个很小的空间(可以看到实验1的Sigma远小于实验2的Sigma),模型就仅仅去依赖decoder的每一次解码的输入,因此在训练的时候生成的不太好,但是在测试的时候,因为encoder-output的波动很小,反而每一次的随机过程都很稳定,然后decoder-output就会产生不变的输出,同时生成的比较流畅。
  2. 实验2用了平均,于是在训练的时候有一个比较大的语义空间,对应的模型可以把注意力放到Encoder-output上,因此在训练的时候表现的比较好。但是在测试的时候,从一个小的正态分布里采样的Encoder-output在一个比较大的语义空间里容易产生一个“非法”的表示,又由于模型比较依赖于Encoder的结果,导致了输出的不流畅
  3. 总得感觉就是生成的难度比较大,要么就是Decoder不管Encoder自己生成,要么是Encoder生成的范围大,训练好,但是测试的时候随机采样的可能不大合法,阻碍了Decoder。(个人的猜想,就是一个合法合理的句子向量应该在空间上的分布比较的离散,也就是说A,B句子是流畅的,但是A到B的向量空间里的句子并不流畅。)
  4. 我个人感觉样本生成还是蛮有前景的,因为低资源以及一些错误样本始终存在,假如能把想要的数据进行扩充,那几乎可以从数据的角度缓解所有NLP的任务问题。不过话说回来,用VAE去生成样本来做一些生成,应该有很多前人的工作了,假如要入手这个,应该先去调研,而不是这么直接弄实验。。。说不定有人有更好的办法。

    实验3

    实验3是上周报告里讨论到的,在encoder-decoder里的中间领域是否是相似句子的表示。即encoder-decoder编码A为一个中间变量S用于Decode的时候,这个中间表示的周围是不是代表了和SentenceA相似的地方,进而可以用中间变量S的相似邻域来产生和A相似的样本

  5. 一个方面是看看,在训练后的Transformer结构里,是不是相似的句子输入得到的中间表示是相似的。

  6. 另一个方面,反过来看看中间表示相似的时候,输入是不是相似的。

于是我弄了一下实验,就是用Transformer结构,数据集是中文短句子分类数据集,我只用文本。
输入一个带MASK(我用的10%的概率)的中文短文本,输出是原文(消除MASK)
这个任务非常简单,transformer很容易就做到了比较好复原。
然后方向1,我利用训练好的Transformer encoder编码我给定的一个输入句子,然后和同样方法得到训练集里的样本的编码结果计算余弦相似度,看看匹配上的是谁。
输入:美海军几十年来第一次感到威胁
相似度最高的两个匹配结果:

  1. 《我的几十年散记》开篇三则
  2. 陆奇举刀,百度第三次重组内阁

有一个现象比较明显,那就是匹配结果有比较大的词语重复,即”几十年“,”第X次“
这个现象应该有两个原因

  1. 我匹配是把整个序列拉平(【Seqlen,hiddensize】-> 【Seqlen*Hiddensize】),然后计算相似度,并不是一个全局语义的匹配,所以在匹配的时候其实是一个词一个词的匹配,可能会匹配到这种词语重复上。
  2. 训练的任务是重构原始输入,那可能模型只学习到了Embedding的映射,self-attention并没有太多的全局语义融合,所以不同的语义,但是token相同就会被匹配。

然后是实验方向2,我采样一个句子,然后手动生成一个相似句子,然后再随机采样一个句子,看看相似度。

SentenceA SentenceB Similarity Vector Distance
日本首相退休后待遇如何? 日本首相离职后待遇怎么样? 90.12% 44.9783
日本首相退休后待遇如何? 上联:荷田雨打叶;怎么接下联? 70.04% 78.3367

感觉也是因为上述提到的两个原因导致的
综合以上我觉得,至少在简单的重构输入这种任务的Encoder-Decoder上,中间变量的相似往往来自于Token的重合相似,而不是想要的样本整体抽象特征相似。(假如可以邻域采样就可以获得相似样本,则生成样本就简单多了,但是从这里看,这个想法应该不大可能)