【搜出来的文本】⋅(三)基于BERT的文本采样
By 苏剑林 | 2021-01-22 | 86814位读者 |从这一篇开始,我们就将前面所介绍的采样算法应用到具体的文本生成例子中。而作为第一个例子,我们将介绍如何利用BERT来进行文本随机采样。所谓文本随机采样,就是从模型中随机地产生一些自然语言句子出来,通常的观点是这种随机采样是GPT2、GPT3这种单向自回归语言模型专有的功能,而像BERT这样的双向掩码语言模型(MLM)是做不到的。
事实真的如此吗?当然不是。利用BERT的MLM模型其实也可以完成文本采样,事实上它就是上一篇文章所介绍的Gibbs采样。这一事实首先由论文《BERT has a Mouth, and It Must Speak: BERT as a Markov Random Field Language Model》明确指出。论文的标题也颇为有趣:“BERT也有嘴巴,所以它得说点什么。”现在就让我们看看BERT究竟能说出什么来~
采样流程 #
首先,我们再次回顾上一篇文章所介绍的Gibbs采样流程:
Gibbs采样
初始状态为$\boldsymbol{x}_0=(x_{0,1},x_{0,2},\cdots,x_{0,l})$,$t$时刻状态为$\boldsymbol{x}_t=(x_{t,1},x_{t,2},\cdots,x_{t,l})$。
通过如下流程采样出$\boldsymbol{x}_{t+1}$:
1、均匀地从$1,2,\cdots,l$中采样一个$i$;
2、计算$p(y|\boldsymbol{x}_{t,-i})=\frac{p(x_{t,1},\dots,x_{t,i-1},y,x_{t,i+1},\cdots,x_{t,l})}{\sum\limits_y p(x_{t,1},\dots,x_{t,i-1},y,x_{t,i+1},\cdots,x_{t,l})}$;
3、采样$y\sim p(y|\boldsymbol{x}_{t,-i})$;
4、$\boldsymbol{x}_{t+1} = {\boldsymbol{x}_t}_{[x_{t,i}=y]}$(即将$\boldsymbol{x}_t$的第$i$个位置替换为$y$作为$\boldsymbol{x}_{t+1}$)。
其中最关键的一步,就是$p(y|\boldsymbol{x}_{-i})$的计算了,它的具体含义是“通过除去第$i$个元素后的所有$l-1$个元素来预测第$i$个元素的概率”,了解BERT的读者应该都能明白过来:这不正是BERT的MLM模型所要做的事情吗?所以,MLM模型与Gibbs采样结合起来,其实就可以实现文本的随机采样了。
所以,将上述Gibbs采样流程落实到基于MLM的文本采样中,流程如下:
MLM模型随机采样
初始句子为$\boldsymbol{x}_0=(x_{0,1},x_{0,2},\cdots,x_{0,l})$,$t$时刻句子为$\boldsymbol{x}_t=(x_{t,1},x_{t,2},\cdots,x_{t,l})$。
通过如下流程采样出新的句子$\boldsymbol{x}_{t+1}$:
1、均匀地从$1,2,\cdots,l$中采样一个$i$,将第$i$的位置的token替换为[MASK],得到序列$\boldsymbol{x}_{t,-i}=(x_{t,1},\dots,x_{t,i-1},\text{[MASK]},x_{t,i+1},\cdots,x_{t,l})$;
3、将$\boldsymbol{x}_{t,-i}$送入到MLM模型中,算出第$i$个位置的概率分布,记为$p_{t+1}$;
3、从$p_{t+1}$采样一个token,记为$y$;
4、将$\boldsymbol{x}_{t}$的第$i$个token替换成$y$来作为$\boldsymbol{x}_{t+1}$。
读者或许留意到了,该采样流程只能采样出固定长度的句子,不会改变句子长度。确实如此,因为Gibbs采样只能实现用某个分布中进行采样,而不同长度的句子事实上已经是属于不同的分布了,它们理论上是不存在交集的,只不过通常我们我们建立语言模型时,是直接用自回归模型统一建模不同长度的句子分布,以至于我们没有察觉到“不同的句子事实上属于不同的概率分布”这个事实。
当然,要解决这一点也不是不可能,《BERT has a Mouth, and It Must Speak: BERT as a Markov Random Field Language Model》原论文就指出,可以将初始句子设为全部都是[MASK]的序列,这样我们就可以事先随机采样一个长度$l$,然后以$l$个[MASK]为初始句子来开始Gibbs采样过程,从而得到不同长度的句子。
参考代码 #
有了现成的MLM模型后,实现上述Gibbs采样其实是一件很简单的事情了,下面是基于bert4keras实现的参考代码:
Gibbs采样参考代码:basic_gibbs_sampling_via_mlm.py
下面是一些例子:
初始句子:
科学技术是第一生产力。
采样结果:
荣耀笔记本开箱怎么样?
微信记录没用被怎么办?
无法安装浏览器怎么办?
epf转换器a7l怎么用?
没有安装浏览器怎么办?
荣耀笔记本充电怎么用?
无法打开asp. net怎么办?
没有安装浏览器怎么办?
无法重启浏览器怎么办?
ro汉巴换mac tv版怎么用?初始句子:
北京新增3例本地确诊病例和1例无症状感染者
采样结果:
澳门录得233宗h1n1感染案例和13宗放射性感染。
庆祝仪式是学院绘画、钢铁工参与创作的盛会。
庆祝仪式后吉卜力平台其他游戏也参加了庆祝。
临床试验发现中的g染色体多来自胃肠道感染。
临床试验发现,人们通常真正享受阴蒂的快感。
庆祝模式在吉卜力平台其他游戏中更加与庆祝。
庆祝模式在吉卜力,或其他游戏上更新和庆祝。
澳门录得20宗h1n1感染病例,2宗放射性感染。
临床试验发现女性的染色体常来自胃肠道感染。
临床试验发现90% 感染病例为m型胃肠道感染。初始句子:
连续9个[MASK]
采样结果:
你每天学你妈妈啊!
那晚,眼前白茫茫。
層層青翠綠意盎然。
幼儿园想做生意了。
究竟如何才能入官?
老师、同学,您好!
云山重重,两茫茫。
梅雨,窗外霧茫茫。
那时,眼前白茫茫。
還是很棒的切蛋糕!
笔者实验所使用的是Google开源的中文BERT base。可以看到,采样出来的句子还是比较丰富的,并且具有一定的可读性,这对于一个base版本的模型来说已经算是不错了。
对于连续[MASK]作为初始值来说,重复实验可能会得到很不一样的结果:
初始句子:
连续17个[MASK]
采样结果:
其他面瘫吃什么?其他面瘫吃什么好?
小儿面瘫怎么样治疗?面瘫吃什么药?
幼儿面瘫怎么样治疗?面瘫吃什么好?
儿童头痛是什么原因荨麻疹是什么病?
其他面瘫吃什么・ 其他面瘫吃什么好?
竟然洁具要怎么装进去水龙头怎么接?
其他面瘫吃什么好其他面瘫吃什么好?
孩子头疼是什么原因荨麻疹是什么病?
竟然厨房柜子挑不进去水龙头怎么插?
不然厨房壁橱找不到热水龙头怎么办?初始句子:
连续17个[MASK]
采样结果:
フロクのツイートは下記リンクからこ覧下さい。
天方町に運行したいシステムをこ利用くたさい。
エリアあります2つクロカー専門店からこ案内まて!
当サイトては割引に合うシステムを採用しています!
同時作品ては表面のシステムを使用する。
メーカーの品は真面まてシステムを使用しています。
掲示板こ利用いたたシステムこ利用くたさい。
住中方は、生産のシステムを使用しています。
エアウェアの住所レヘルをこ一覧下さい。
フロクのサホートは下記リンクてこ覧下さい。
很神奇,日语都采样出来了,而且笔者用百度翻译看了一下,这些日语还算是可读的。一方面,这体现了随机采样结果的多样性,另一方面,这也体现了Goole版的中文BERT并没有做好去噪,训练语料应该夹杂了不少非中英文本的。
吃瓜思考 #
前段时间,Google、斯坦福、OpenAI等合作发表了一篇文章《Extracting Training Data from Large Language Models》,指出GPT2等语言模型完全是可以重现(暴露)训练数据情况的,这个不难理解,因为语言模型本质上就是在背诵句子。而基于MLM的Gibbs采样表明,其实这个问题不仅GPT2这种显式的语言模型存在,像MLM这样的双向语言模型其实也是存在的。从我们上述的采样例子就可以看出些端倪了,比如采样出日语来,说明原始语料并没有做特别完善的去噪,而我们从“北京新增3例本地确诊病例和1例无症状感染者”出发,采样出了一些h1n1相关的结果,这反映出训练语料的时代性。这些结果都意味着,如果你不想开源模型暴露你的隐私,那么对预训练的语料就要做好清理工作了。
此外,关于《BERT has a Mouth, and It Must Speak: BERT as a Markov Random Field Language Model》这篇论文,还有一个瓜可以吃,那就是原论文说MLM模型是一个Markov Random Field,但事实上这是不对的,后来作者也在自己的主页上做了澄清,有兴趣的读者可以看《BERT has a Mouth and must Speak, but it is not an MRF》。总的来说,MLM用来做随机采样是没问题的,但它不能对上Markov Random Field。
本文小结 #
本文介绍了基于BERT的MLM所进行的文本随机采样,它实际上是Gibbs采样的自然应用。总的来说,本文只是一个相当简单的例子。对于已经对Gibbs采样有所了解的读者来说,本文几乎是没有技术难度的;如果还不是很了解Gibbs采样的读者,正好也可以通过这个具体的例子,来进一步去理解Gibbs采样的流程。
转载到请包括本文地址:https://kexue.fm/archives/8119
更详细的转载事宜请参考:《科学空间FAQ》
如果您还有什么疑惑或建议,欢迎在下方评论区继续讨论。
如果您觉得本文还不错,欢迎分享/打赏本文。打赏并非要从中获得收益,而是希望知道科学空间获得了多少读者的真心关注。当然,如果你无视它,也不会影响你的阅读。再次表示欢迎和感谢!
如果您需要引用本文,请参考:
苏剑林. (Jan. 22, 2021). 《【搜出来的文本】⋅(三)基于BERT的文本采样 》[Blog post]. Retrieved from https://kexue.fm/archives/8119
@online{kexuefm-8119,
title={【搜出来的文本】⋅(三)基于BERT的文本采样},
author={苏剑林},
year={2021},
month={Jan},
url={\url{https://kexue.fm/archives/8119}},
}
January 23rd, 2021
所以這邊的部分,您還沒有用到第一篇所講到的“受限文本生成(Constrained Text Generation)”對吧?因為看起來,上面的做法沒有指定必須要出現那些關鍵字,而且生成的句子很大程度跟初始句子有關。另外,上面的做法是每次隨機替換一個字,那麼你是如何決定要替換多少次才停下來呢?
是的。受限文本生成的一般思路是“带约束的目标+MCMC方法”,前两篇文章逐步介绍MCMC方法,这篇文章属于简单的“无约束的目标+MCMC方法”,作为第一个例子是比较适合的,其他例子后面还会逐渐展开,敬请期待。
至于多少次才停下来,要注意本文的例子是Gibbs文本采样,它的目的是采样而不是搜索,所以并没有停下来的说法,换句话说,假设1000步后该状态已经进入了平稳分布了,那么从1000步开始,直到无穷步,得到的无穷多个样本,都是我们的采样结果,这些样本可能会重复,但是一般不会有收敛趋势。
所谓平稳,指的是样本所属的分布上的收敛,采样结果并不一定具有收敛性,除非模拟退火。
January 26th, 2021
苏神,如果要做社交网络的用户画像,大概每个用户发的文本(twitter)长度总和大约在5000多,只取前512个token或者取头尾的话,会丢失大量信息,而且性能与tfidf+LR模型差很多,请问在这种情况写有什么可行的解决方法?
我大概抓了10G左右的文本,都是twitter短句,长度
大概在128token以内,相对于bert预训练的corpus要小了很多,而且还有很多emoji相关的预处理文本是原bert词典里面没有的,请问在这种情况下,我是从头训练模型好,还是微调现有模型好?
感谢苏神的文章,如能回复,不胜感激
你不能单独处理每个句子,然后再整合每个用户的所有句子表征么?
January 26th, 2021
苏神,我看你之前的很多文章提到过若干个不均衡学习的方法,
前段时间我看了一篇有关小样本学习的文章,是篇NeurIPS,里面提出的半监督学习框架苏神有没有兴趣啊:
https://zhuanlan.zhihu.com/p/259710601
https://github.com/YyzHarry/imbalanced-semi-self
虽然我感觉这种方法像自己踩着自己的脚往上走一样,容易剑走偏锋,但从作者的结果来看,效果还是不错的。
个人技拙,看了源码,没办法领略其中真谛,如果苏神有兴趣看看可以相互探讨下
半监督又是另外一条路了,最近对这个问题没什么兴趣了,暂不打算研究。
February 5th, 2021
用以上代码经过修改做了一个小实验 , 在Gibbs采样时不是随机取 , 而是按顺序选择i ,即:i从1开始一直选到length , 然后再从1选到length , 如此循环 ; 思想是按顺序更新应该更符合自回归 , 10000步后直观来看句子可读性确实强了一些
另外一个问题是 , 这里的steps = 10000应该是随便写的 , 从严谨的角度说应该并不能保证一定进入了平稳分布吧,我想的办法是把用代码把细致平衡也实现出来,然后迭代10000步之后验证? 但是很有可能在5000步就进入细致平衡了 , 后面的5000步就浪费了
验证不了,你采样出来的是样本,细致平稳条件针对的是分布。
明白了 所以只能尽量把steps取大一点了
参考这一层的回答 @苏剑林|comment-15353
February 8th, 2021
苏神你好,请问对于词典例句的受控文本生成可以提供一些思路吗?例句中需要包含目标词汇。
这难道不就是给词造句?如果是的话,下一篇文章会介绍下。
February 26th, 2021
请问gibbs sampling的速度很慢,会有实用上的问题,有没有什麽方法可以加速sampling过程?
我的想法是先给出一个好的初始参数。
不知道还有没有什麽思路方向?
没有。
MCMC是对人的模拟,而Gibbs采样接受率已经恒为1了,属于最理想的情形,不会有什么改进空间了。我认为只要生成速度比人快,那么就没有实用上的问题,如果有,那就是人的要求过于不客观导致的,要反思的是人而不是模型。
March 15th, 2021
想在BERT生成语言和extract训练数据这个方向做点研究。初步实验了一下,似乎BERT/Robert很难extract出来类似与GPT2那样的训练数据。比如用Gibbs sampling从Robert生成的url,email,phone number,搜索后发现并不存在。而用GPT2-xl是挺容易重复类《Extracting Training Data from Large Language Models》文中的结果的。这是因为gibbs sampling的方法太随机了,生成的文本在LM看来概率太低?有没有更好的生成方法能降低随机性?或者因为masked language modeling比casual language modeling要简单,所以模型并不需要记住训练数据?
请问在这个方向还有哪些相关的文献能够推荐一下吗?谢谢
可以模拟退火试试,最终得到比较高概率的采样结果,或许会好点。
March 18th, 2021
苏神你好,吉布斯采样是每个时刻会对所有维进行采样,而你的MLM模型随机采样每个时刻只对其中一维进行了采样,这是为啥呀?
Gibbs采样就是每个时刻只对其中一维进行采样啊。
不是吧。Gibbs采样每个时刻会对每一维数据都进行采样吧,只不过是一维一维的采样,最终每个时刻所有的维度数据都要进行更新
理由呢?我的推导结果就是只对一维更新,我看的每一篇文章,写的都是只对一维更新。
因为不能上传图片,所以我这里发一下链接https://blog.csdn.net/pipisorry/article/details/51373090,你看看algorithm 8。我看到关于gibbs采样的都是每一时刻会对所有维进行采样。
我想了下,采一维和采所有维最终应该都会收敛,这类似SGD和BGD吧
它这里保证遍历了每一维,强行均匀化,可能会起到降低方差的作用,但事实上从Gibbs采样的推导过程就可以看到,并不存在均匀遍历每一维的要求。
苏神,我顺便再请教一下,MH采样当拒绝的时候,是令x(t+1)=x(t);这里为啥不像拒绝采样那样丢掉数据,重新采样直到满足接收条件?
@tayee|comment-15882
第二篇文章(https://kexue.fm/archives/8084)已经写得很清楚了,扔掉会改变分布。
March 22nd, 2021
@苏剑林|comment-15884
感谢苏神!
“MH采样当拒绝的时候,是令x(t+1)=x(t);这里为啥不像拒绝采样那样丢掉数据,重新采样直到满足接收条件?”
你可以这样理解:在马尔可夫链随机游走时,拒绝转移到其他状态,还是保持原来的状态。
直观来想就是停留在当前状态的时间不一样,从而影响总体的状态分布。
如果我们只是想逐渐退火来获取最终结果,那么两者没区别,但是如果我们想要的是从分布中采样,那么就会有区别。
更直观的理解就是:假如你连续中了两期彩票头奖,然后官方说第二次不算,要重新选一组中奖号码才行,那你觉得你乐意吗?结果等价吗?重新开奖并没有改变“你已经中过奖”的事实,但是改变了你获得的奖金数。