首页 > 其他分享 >PPLM:可控文本生成

PPLM:可控文本生成

时间:2024-07-24 15:57:36浏览次数:11  
标签:语言 可控 模型 PPLM 生成 文本 属性

最近一直捣鼓生成式模型的东西,特别是关于利用现有预训练模型的生成式,中间很多挺有意思的坑,先不说。生成式中一个比较大的需求是,可控文本生成,其中可控表示能让模型生成与所需主题相关的文本,这也涉及到文本的风格迁移。

往往即便是现有超大语言模型,如 GPT2,可以生成没有任何拼写和语法错误的句子,但却难以控制其生成的方向。而这样的语言模型就像一头巨象,完全没有方向地到处走,你只能指望它碰巧去了你需要的方向。

 

最近读到 Uber AI 的关于该主题的论文,Plug and Play Language Models: a Simple Approach to Controlled Text Generation,方法非常新颖,简单介绍一下。

我们以前都这样干

之前对于预训练语言模型(特别是超大型)可控生成的做法,主要如下三种

  • 随缘法,就是直接拿着语言模型就用。可以给语言模型些字,让它基于这个续写,生成多个结果,之后挑最好的来展示(俗称 cherry-pick)。很多 GPT2 展示出的例子就大都 cheery-pick 出来的。
  • 精调法,因为上面直接拿来用对于某些风格或主题的内容生成很难撞上,可能预训练时这方面的文本也少,于是可以先在需要的风格或主题文本上进行精调训练,或者用强化学习和人类反馈精调出想要的语言模型。
  • 条件语言模型法,这个就是在预训练阶段就将各种风格主题标签加入进去,这些标签可以来自于训练数据的元数据,之后生成的时候,在生成所需要风格主题的文本时,只需要先给个标签就行,Salesforce 的 CTRL 模型个很典型的例子。

以上三种方法,除了第一种,因为需要对整体语言模型进行训练,所以都要大量计算资源,而第一种生成可控性又特别差。对此,PPLM 则是在使用少量计算资源的同时,又达到了比较好的可控生成性。

关于这几种方法简单比较如下:

可见相比起之前的方法,PPLM 最大的不同在于建模形式不同了,然后需要训练参数也少了很多。PPLM-Discrim 的参数才 4k,相比起其控制的 345M 模型,差了百万倍,正所谓四两拨千斤。

何谓可控

其实所谓可控就是如何建模出 p(x|a) 这样的概率模型,也就是基于某个属性 a,生成文本 x,获得满意结果。

关于前面几种方法大概分别是这样获得 p(x|a):

  • 直接拿语言模型来用的,只能直接获得 p(x),最多通过给出文本注入先验,尽量将生成范围缩小,然后选出满足要求的 p(x|a).
  • 而精调法是,直接在预训练中对单个属性中的 p(x|a) 进行建模,因为 a 是隐含的,所以可以直接写成 p(x).
  • 条件语言模型法,则是将各个属性的 p(x|a) 都直接在预训练中进行训练。

而 PPLM 最关键的是将 p(x|a) 通过贝叶斯公式改写成了下面形式:

其实这个很好理解,要获得所需基于属性 a 生成文本的 p(x|a)。我们已有一个语言模型 p(x) 能够很好地生成符合自然语言的文本,那么一个非常简单的方法就是用一个分类器(也能是人)来判断语言模型生成的文本 x 是否具有 a 属性,也就是 p(a|x),于是就能获得 p(x|a). 这其实就是文中提到的 rerank 法。

当然 PPLM 则用了更精巧的方法解决该问题。

P(a|x):先得赋予属性

首先解释一点背景知识,在每个 t 时间步上,语言模型 LM 干的活就是基于过去的历史信息 H 来生成当前的输出 o,同时也将当前时间步信息存入历史,用于下一个时间步的生成:

而 p(a|x) 在这的作用是,判断当前生成是否接近属性 a 的需求,根据反馈,去修改之前的历史 H,之后语言模型根据新历史来生成更接近属性 a 需求的句子。

一个好玩的比方是把这个看作时间旅行,比如说大雄跑到未来瞅瞅静香是不是嫁给了他,如果没有就回去改变历史,然后得到一个基于新历史的结果。如何改变历史呢,现实中当然还未实现,但在这里,就可以用到我们的老朋友,反向传播。

通过每次 p(a|x) 的误差传播,可以获得一个梯度,之后用这个更新过去的历史,就可以获得一个新的历史:

变更后的历史就能比较大的概率让语言模型生成我们想要的属性的句子,整个过程大致如下:

 

总共分三步:

  1. 前向过程,包括语言模型和之后的属性判别模型,之后预测出 p(a|x);
  2. 反向过程,根据属性判别模型回传的梯度,更新语言模型内部历史状态,使得实际预测更接近想要属性;
  3. 重新采样,根据获得的新输出概率分布,采样生成一个新的词。

补充一些关于历史 H,还有其梯度更新的其他信息。

  • 论文中因为用的是 GPT2 语言模型,所以模型基本组件是 Transformer,所以历史 H 用的是每层 K 和 V 的值。而如果要用其他模型,也可以根据模型不同改变具体 H 实现。
  • 还有实际 H 更新梯度计算时,会有数次迭代过程,其中还包括一些 normalization 和 scaling 的操作,以及很重要的强度参数 α (可调节属性影响强度),建议去读源码,更好理解。

p(x) :但还得保证流利性

虽然上面赋予属性的操作很巧妙,也能保证让文本生成方向朝着属性判别器满意的方向生成,但判别器 p(a|x) 满意并不代表我们会满意。如果只用上面技巧,会导致生成一些有问题的句子,比如说要生成正面的话,那么说不定会疯狂重复,“好好好好好”,这当然不是我们想要的。

我们还是希望能够生成更多样性,并且符合语言模型的句子。因此文中采取了两个保证生成句子的语言模型尽量与原语言模型接近的方法:

  • Kullback–Leibler(KL) 散度:在计算历史 H 更新值时,向其中加入一个 KL 散度损失,最小化改变前语言模型和改变后的预测概率分布的 KL 散度;
  • Post-norm Geometric Mean Fusion(后范数几何平均融合?):其实就在上面训练时改变的同时,加入一个类似输出后处理的过程,直接让实际预测从下面式子中采样,让生成分布和语言模型直接绑定起来:

通过上面这些步骤实际上相当于完成了一个下图中的过程:

 

先通过 p(a|x) 让生成结果具有属性,之后让它生成接近自然语言的流畅 p(x).

属性判别器展示

关于具体的属性判别器 p(a|x),文中用了两种不同的方法。

第一种是BOW(词袋) 属性模型,没有额外参数。针对每个主题先总结一批有代表性的词,之后具体实现时只用在每个时间步上对输出概率分布取出对应词袋中词的位置,计算 loss,加和起来反向传播就行。方法虽然简单却意外有效,可以看些例子。

 

该方法和 weighted decoding 思想有些类似,论文中也有详细对比。

第二种是简单属性分类器,非常少参数。就是在 freeze 住大模型的情况下,拿已有的标注数据,先预训练一个分类器出来。比如文中就用感情分类数据集 SST-5,之后输入GPT2模型,最后一层向量取平均,接着输入分类器分类,训练分类器。

 

当然除了上面两种方法其实还能用其他分类器,毕竟 PPLM 只是提出一个大概的框架,判别器无论是什么,只要能回传梯度就行。

此外文中还做了很多实验来进行具体分析,包括特别搞笑的拿一个完全不相关词来生成具体领域的实验,看模型怎么强行生成相关文本。还有和之前的方法进行对比,也很值得一看。

能拿来干什么呢

很多了,首先控制情感的评论,还有各种具体领域文本生成,还有文中的文本去毒(detoxification),可控故事生成。

感兴趣还是看论文吧,满满的都是内容。另外关于之前有人用类似方法却没取得很好结果,根据论文作者说可能是当时语言模型还不够强大。

论文:

http://arxiv.org/abs/1912.02164​arxiv.org/abs/1912.02164

标签:语言,可控,模型,PPLM,生成,文本,属性
From: https://www.cnblogs.com/zhangxianrong/p/18321089

相关文章

  • Linux 文本文件编辑相关命令简介【Linux 常用命令系列二】
    〇、前言本文介绍了如何通过vim命令,对文本文件进行打开、编辑、保存等相关操作,并通过简单的示例演示了常用用法。一、关于文本文件的操作1.1打开,查看(cat)、编辑(vim)打开文本文件,有查看和编辑两种状态。1.1.1仅查看cat可以使用cat命令,加上文件的绝对路径或者进入目标路......
  • Tools - 通过PlantUML进行文本方式绘图
    PlantUML简介PlantUML是支持多系统多编辑器的一个以文字方式绘图的工具,可以根据文字表述直接生成图,支持时序图、流程图、用例图、状态图、组件图等。能够以插件形式被Idea、VSCode、PyCharm等编辑工具所集成需先安装Java和开源图片渲染库Graphviz,否则无法正常显示需要先熟悉......
  • Unity 富文本 link 标签使用办法
    varstring=<link=url><u><#0076FF>openurl</u></color></link>text里面设置这个字符串 publicvoidOnPointerClick(PointerEventDataeventData){intlinkIndex=TMP_TextUtilities.Fin......
  • 加速数字化转型,信创自主可控:TapData 为银行业数据管理能力建设提供新思路
    使用TapData,化繁为简,摆脱手动搭建、维护数据管道的诸多烦扰,轻量代替OGG、DSG等同步工具,「CDC+流处理+数据集成」组合拳,加速仓内数据流转,帮助企业将真正具有业务价值的数据作用到实处,将“实时数仓”方法论落进现实。TapData持续迭代产品能力,优化用户体验的同时,也在不断探......
  • 【Python正则表达式】:文本解析与模式匹配
    文章目录1.正则表达式2.re模块3.修饰符3.元字符3-1字符匹配元字符3-2重复次数限定元字符3-3字符集合匹配元字符3-4分组元字符3-5边界匹配元字符3-6字符类别匹配元字符4.技巧4-1贪婪与非贪婪5.案例1.正则表达式正则表达式面向什么样的问题?1、判断一个字......
  • 力扣68. 文本左右对齐
    给定一个单词数组 words 和一个长度 maxWidth ,重新排版单词,使其成为每行恰好有 maxWidth 个字符,且左右两端对齐的文本。你应该使用“贪心算法”来放置给定的单词;也就是说,尽可能多地往每行中放置单词。必要时可用空格 '' 填充,使得每行恰好有 maxWidth 个字符。要......
  • Linux 行文本处理工具sed
    sed(streameditor)是Linux和Unix系统中非常强大的文本处理工具,它可以对文本进行过滤和转换。sed以行为单位处理文本,可以通过读取输入文件(或标准输入),应用一系列的编辑命令,然后将结果输出到标准输出(通常是屏幕)或文件中。基本语法sed[选项]...{脚本-地址}{命令}[输入文件]......
  • 如何使用 Selenium Python 搜索 Excel 文件中的文本
    我有一些数据在Excel文件中。我想要转到Excel文件,然后搜索文本(取自网站表),然后获取该行的所有数据,这些数据将用于在浏览器中填充表格。示例:我希望selenium搜索ST0003然后获取名称,该学生ID的父亲姓名,以便我可以在大学网站中填写此信息。我想我会从网站......
  • 使用 beautifulsoup python 更改内部标签的文本
    我想更改使用Beautifulsoup获得的HTML中标签的内部文本。示例:<ahref="index.html"id="websiteName">Foo</a>变成:<ahref="index.html"id="websiteName">Bar</a>我已经设法通过其id获取标签:HTMLDocument.find(id......
  • Python 实现Excel和TXT文本格式之间的相互转换
    Excel是一种具有强大的数据处理和图表制作功能的电子表格文件,而TXT则是一种简单通用、易于编辑的纯文本文件。将Excel转换为TXT可以帮助我们将复杂的数据表格以文本的形式保存,方便其他程序读取和处理。而将TXT转换为Excel则可以将文本文件中的数据导入到Excel中进行进一步的分析和......