最近,笔者入了一个新坑:基于离散优化的思想做一些文本生成任务。简单来说,就是把我们要生成文本的目标量化地写下来,构建一个分布,然后搜索这个分布的最大值点或者从这个分布中进行采样,这个过程通常不需要标签数据的训练。由于语言是离散的,因此梯度下降之类的连续函数优化方法不可用,并且由于这个分布通常没有容易采样的形式,直接采样也不可行,因此需要一些特别设计的采样算法,比如拒绝采样(Rejection Sampling)、MCMC(Markov Chain Monte Carlo)、MH采样(Metropolis-Hastings Sampling)、吉布斯采样(Gibbs Sampling),等等。

有些读者可能会觉得有些眼熟,似乎回到了让人头大的学习LDA(Latent Dirichlet Allocation)的那些年?没错,上述采样算法其实也是理解LDA模型的必备基础。本文我们就来回顾这些形形色色的采样算法,它们将会出现在后面要介绍的丰富的文本生成应用中。

明确目标 #

很多时候,我们需要根据一些特定的信息c来生成目标文本x,用数学的话说就是条件语言模型p(x|c),不过我们无法得到足够多的语料对(x,c)去直接监督训练一个条件语言模型,而是只能训练一个无条件的语言模型p(x),但我们又可以人为地设计一个指标来定量描述xc之间的联系。那么在这种情况下,如何根据无条件的语言模型p(x)x,c之间的联系来做有条件的文本生成,便成为了我们的研究对象。我们可以称之为“受限文本生成(Constrained Text Generation)

举例来说,用关键词造句,那么c就是关键词的集合,我们可以定义示性函数:
χ(x,c)={1,如果x包含关键词集c0,如果x不包含关键词集c
继而定义
ρ(x,c)=p(x)χ(x,c)
p(x)保证了生成句子的流畅性,χ(x,c)保证了生成句子包含所要求的关键词,那么问题就可以变成最大化操作argmaxxρ(x,c)或采样操作xρ(x,c)。当然,这里的ρ(x,c)还不是概率分布,要完成归一化后才是真正的概率分布:
ρ(x,c)xρ(x,c)=p(x)χ(x,c)xp(x)χ(x,c)
但分母通常是难以显式计算出来的。那也就是说,我们对待采样分布也只了解到它正比于某个函数ρ(x,c),而不知道精确的分布表达式。

类似的例子并不少,比如说文本摘要。什么是文本摘要呢?其实就是用更少的文字x尽可能表达出跟原文c一样的意思,这时候我们可以定义:
ρ(x,c)=p(x)sim(x,c)χ(x,c)
这里的sim(x,c)是某个文本相似度函数,而χ(x,c)是长度的示性函数,即x的长度在某个范围(可能依赖于c)内,它就为1,否则为0。此时我们同样得到了一个未归一化的概率分布ρ(x,c),需要最大化它或者从它里边采样。很明显,这个目标就意味着我们要得到一段跟原文语义尽可能相似的、长度满足一定约束的文字,这不就是摘要的存在意义吗?所以,这套思路的核心出发点就在于:我们要把自己要生成的目标定量地捋清楚,然后再去执行下一步操作。

困难分析 #

所以,抛开前面的背景不说,现在我们面临的问题就是有一个分布p(x),我们只知道p(x)ρ(x),即
p(x)=ρ(x)xρ(x)
中的分母我们无法显式计算出来。在本系列文章中,x代表文本,即一个离散元素的序列,但后面的推论同样也适用于x是连续型向量的场景。现在我们要搜索最大位置argmaxxp(x)或进行采样xp(x),后面我们将会看到,搜索最大值其实也可以看成是采样的特例,因此我们主要关心采样方式。

前面说了,之所以需要设计一些特别的算法来完成采样,是因为直接从p(x)中采样是困难的,而我们需要理解采样的困难所在,才能真正理解后面所设计的采样算法的关键之处。困难在哪?如果x的候选值空间不大,哪怕有100万个候选值,我们都可以把每个p(x)都算出来,然后按照普通的类别采样来进行。然而,一般x的候选值空间远远不止100万,假如x有10个分量,每个分量有1万个选择(对应于词表大小),那么总的排列就有1040种了,不可能事先算好每一种排列的概率然后依概率采样。

那怎么办呢?所谓“不积硅步,无以至千里”,那就只能一步步来了,也就是说,我没法直接实现1040选1,那我做10次“104选1”可以吗?这就对应着所谓的“自回归生成”:
p(x)=p(x1)p(x2|x1)p(x3|x1,x2)p(xn|x1,,xn1)=nt=1p(xt|x<t)
这样我们就可以先从p(x1)采样一个x1,然后从p(x2|x1)中采样一个x2,依此递归了。但是,自回归生成只是对应于无条件的语言模型或者是有监督训练的Seq2Seq模型,而如果希望像前面举的例子那样,往无条件语言模型的生成过程中加点约束,那么对应出来的模型就不再是自回归的了,也就无法按照这样的递归采样了。

所以,我们就不得不需要后面介绍的各种采样算法了,它也是“一步步来”的思想,但所使用的分布形式更加广泛一些。

重要采样 #

《从采样看优化:可导优化与不可导优化的统一视角》《如何划分一个跟测试集更接近的验证集?》等文章里,我们介绍过“重要性采样”的概念,即如果我们想估计期望Exp(x)[f(x)],但是p(x)又不是易于采样的分布,那么我们可以找一个跟p(x)相近的、易于采样的分布q(x),然后根据下述变换
Exp(x)[f(x)]=xp(x)f(x)=xq(x)p(x)q(x)f(x)=Exq(x)[p(x)q(x)f(x)]
转化为从q(x)采样来算p(x)q(x)f(x)的期望了,也就是用p(x)q(x)对每个样本进行加权,所以它被称为“重要性采样(Importance Sampling)”。如果只知道p(x)ρ(x),那么重要性采样也是可以进行的,这是因为
1=xp(x)=xq(x)p(x)q(x)=Exq(x)[p(x)q(x)]
所以
Exq(x)[p(x)q(x)f(x)]=Exq(x)[p(x)/q(x)Exq(x)[p(x)/q(x)]f(x)]
这样一来,我们发现上式只依赖于p(x)的相对值,不依赖于它的绝对值,所以把p(x)换成跟它成正比的ρ(x)也是可以的,最终简化成:
Exp(x)[f(x)]Ni=1ρ(xi)/q(xi)f(xi)Ni=1ρ(xi)/q(xi),x1,,xNq(x)

拒绝采样 #

上一节的重要性采样实现了将复杂分布期望转化为简单分布期望,但这还不是我们的真正目的,我们要实现的是把样本从分布p(x)中采样出来,而不是估算它的某个期望。思想依然跟重要性采样一样,引入易于采样的分布q(x),然后从中随机地筛掉某些样本,使得剩下的样本服从分布p(x)

具体来说,假设有函数α(x)[0,1],我们按照如下流程进行采样,即“拒绝采样(Rejection Sampling)”:

拒绝采样q(x)采样一个样本x,从U[0,1]中采样一个随机数ε,若εα(x)则接受该样本,否则拒绝并重新按照此流程采样。

那么,此时采样出来的x真正的概率分布是什么呢?其实也不难,由于样本x被保留下来的概率是α(x),因此它的相对概率就是q(x)α(x),我们只需要将它重新归一化
q(x)α(x)xq(x)α(x)
就得到拒绝采样对应的真正的概率分布了,从这个形式也可以看出,将接受率乘以一个0到1之间的数,理论上拒绝采样对应的分布是不变的

这个过程启示我们,拒绝采样可以让我们实现从正比于q(x)α(x)的分布中采样,那么根据p(x)=q(x)p(x)q(x),我们可以让α(x)=p(x)q(x)作为接受概率,来进行从q(x)出发的拒绝采样,结果就相当于从p(x)采样了。当然,还没那么简单,根据概率的归一化性质,除非q(x)恒等于p(x),否则p(x)q(x)不可能一直都在[0,1]内。但这不要紧,只要p(x)q(x)有上界,那么我们就可以选择一个足够大的常数M,使得p(x)q(x)M[0,1],此时以α(x)=p(x)q(x)M为接受概率即可,刚才我们说了,乘以一个常数不会影响拒绝采样对应的分布。换句话说,也就是这个过程同样不依赖于完全精确的p(x),可以将p(x)换成跟它成正比的ρ(x)

关于接受率α(x),尽管理论上只要求它α(x)[0,1]就行了,但实际上还是以max为好,这是因为过小的接受率会导致拒绝太多(几乎来一个拒绝一个),采样效率太低,生成一个合理的样本的成本过大了。类似地,尽管理论上对q(\boldsymbol{x})的要求只是易于采样并且\frac{p(\boldsymbol{x})}{q(\boldsymbol{x})}有上界,但实际上q(\boldsymbol{x})p(\boldsymbol{x})仍然是越相近越好,否则依然可能造成接受率过低而导致采样成本大到难以接受。所以,尽管拒绝采样看上去提供了一种几乎能从任意分布p(\boldsymbol{x})中进行采样的方案,但实际应用时近似分布q(\boldsymbol{x})的设计依然是一个不小的难题。

本文小结 #

从本文开始,我们开了个新坑,试图从离散优化的角度来完成某些文本生成任务(受限文本生成)。它通过确定一个定量的评估目标,然后通过最大化这个目标或者从中采样就可以得到我们想要的输出,而不需要标签数据监督训练新模型。在这个过程中,所要用到的工具是一些主要是采样算法,本文先介绍了其中很基本的重要性采样和拒绝采样,后面将会继续完善该系列文章,敬请大家期待。

转载到请包括本文地址:https://spaces.ac.cn/archives/8062

更详细的转载事宜请参考:《科学空间FAQ》

如果您还有什么疑惑或建议,欢迎在下方评论区继续讨论。

如果您觉得本文还不错,欢迎分享/打赏本文。打赏并非要从中获得收益,而是希望知道科学空间获得了多少读者的真心关注。当然,如果你无视它,也不会影响你的阅读。再次表示欢迎和感谢!

如果您需要引用本文,请参考:

苏剑林. (Jan. 07, 2021). 《【搜出来的文本】⋅(一)从文本生成到搜索采样 》[Blog post]. Retrieved from https://spaces.ac.cn/archives/8062

@online{kexuefm-8062,
        title={【搜出来的文本】⋅(一)从文本生成到搜索采样},
        author={苏剑林},
        year={2021},
        month={Jan},
        url={\url{https://spaces.ac.cn/archives/8062}},
}