提纲
1 简介
2 Prompt Mining
3 Prompt Paraphrasing
3.1 Paraphrasing-based Generation
3.2 BARTSCORE-Prompt
3.3 BERTese
4 Gradient-based Search
4.1 Trigger Search Algorithm
4.2 AUTOPROMPT
5 Prompt Generation
6 Prompt Scoring
7 总结
参考文献
1 简介
在上一章节中我们分享了人工构建prompt的若干样例,虽然这种方式直观,但是 **人工构建prompt的方式有两个弊端,一方面人工构建prompt和测试prompt效果耗费时间跟精力,另一方面是即便是专业人士也不一定能通过人工的方式构建最优的prompt。** 为了解决这个问题,自然而然就衍生自动构建prompt的方式,自动构建prompt可以分为离散型的prompt(prompt可以用具体的字符表示)和连续型的prompt(prompt由向量替代)。 **在这个章节中,我们聚焦在几种不同的自动构建离散型prompt的方法,至于连续型prompt的方法,在后面的章节再分享。**
2 Prompt Mining【1】
这是通过挖掘的方式去自动构建prompt的方法。 对于数据集LAMA中的三元组(头部实体,关系,尾部实体),可以通过mask掉尾部实体去构建相应的完形填空格式,如果模型能正确预测出对应的尾部实体,就说明模型具有这个知识。 选择合适的prompt,对于最终的效果有深远影响。那么该怎么去自动选择合适的prompt?
**a) 首先是去挖掘可能的prompt,构建prompt的候选集。** 对于每一种关系,去寻找包含这种关系的数据,然后有两种挖掘到prompt的方式。第一种是直接找那些位于头部实体跟尾部实体之间的片段,将相应的头部实体跟尾部实体替换为占位符即可。例如涉及出生地点的数据“Barack Obama was born in Hawaii”可以被转换为相应的prompt ”<x> was born in <y>”。第二种是依赖于句法分析,找到从头部实体到尾部实体之间的最短依存路径,然后将该依存路径作为挖掘到的prompt。例如“France<<pobjof<<prepcapital<<nsubj is<<attr Paris”,找到介于France和Paris的最短依存路径,就可以得到相应的prompt“capital of <x> is <y>”。
**b) 筛选prompt。** 通过第一步可以挖掘得到数量繁多的prompt,同一种关系也有多个prompt与之对应,但是这些prompt的效果会有一定差异,所以需要进行筛选。首先会在模型会分别使用这些prompt在监督数据上做测试,记录同一种关系下不同prompt的指标。后续比较简单的方式可以用每种关系下效果最好的prompt作为最终选择,也可以去集成多种prompt的效果,将同一种关系下的多种prompt根据在训练集上的效果进行排序,选择其中topK个,通过直接平均得到模型在这个K个prompt的效果,最终每个关系对应的是K个prompt的集成。在前面集成多个prompt的基础上,还能多进一步的优化,通过训练得到每个prompt的权重。
**实验证明了使用人工构建prompt的下限会更低,只使用Top1的prompt的效果平均比人工构建prompt的方式更好,使用多个prompt集成的效果会优于只使用Top1的prompt。**
3 Prompt Paraphrasing
**这种方式依赖于现有的种子prompt,通过把种子prompt扩充得到更多的候选prompt,然后从中选取在目标任务表现最好的prompt作为最后选择。扩充的方式可以分为很多种。**
3.1 Paraphrasing-based Generation[1]
对于一个种子prompt,首先将这个种子prompt翻译成另外一种语言,得到翻译结果的B个候选,然后将这B个候选再翻译回最初的语言,每个候选又有B个候选。所以一个种子prompt可以由此获取B*B个候选prompt,对这个B*B个候选prompt排序,将得分最高的K个prompt,作为自动构建prompt的结果。
3.2 BARTSCORE-Prompt【2】
在文本生成任务中怎么去评估生成的文本是否通顺,准确或者有效呢?一个通用的想法就是生成的文本质量越高,模型会给它打上更高的分数。BARTSCOR是一个语言模型,在计算根据源文本生成目标文本的概率时会引入预测token的权重,不同的token具备不同的权重,类似于逆文档权重。
图1: BARTSCORE的计算公式
BARTSCORE-Prompt是在BARTSCORE引进了prompt learning,这里的prompt可以直接加到源文本的后面,也可以加到目标文本的前面。另外,这里采用的自动搜索prompt的方式,是先人工构建种子prompt,然后根据这些prompt的解释去扩充prompt,可以理解为同义词替换,将prompt中的词用它的同义词去替换,从而得以扩充prompt,最后可以根据在测试集上的表现选取效果最好的prompt或者集成所有prompt。结果也显示了几乎所有涉及prompt的方式相比没有prompt的在效果上都有所提升。
图2: BARTSCORE-Prompt的扩充prompt方式
3.3 BERTese【3】
图3: BERTese框架
在过去,构建合适的query和将query输入预训练模型去抽取知识是通过一个分开的pipeline实现的,由此提出了BERTese,能够自动改写query然后输入预训练模型去抽取知识。这里为什么要改写呢?不能直接将原始query输入模型吗?因为直接输入的结果可能会比较糟糕,改写的目的是加进相关的任务提示,适配语言模型,让模型能更好的理解query,从而更好的抽取知识。例如”Obama was born in [MASK]”跟“Obama was born in the state of [MASK]”两句话意思一样,都是想让模型去预测[MASK]的位置,从而抽取Obama的出生地点,但是这两句话输入到预训练模型导致的预测结果却不一样,改写的目的就是希望能保证最后模型的预测效果。
**它的推理过程比较直接,将原始query输入第一个Bert得到相应的隐状态,计算跟每一个时刻隐状态最接近的token的Bert词嵌入,将对应的token作为改写后query的内容,进而得到改写后的query,然后输入到第二个Bert去预测就可以得到最后的答案。(这里可能有疑问,这样得到不还是原始输入的结果吗?其实不然,这里的隐状态跟原始的词嵌入有可能差异很大,基于attention的计算会使得当前时刻的隐状态受到其他其他位置的影响)。**
训练过程比较复杂,包括三部分的目标函数,
a) Valid Token Loss,
希望经过第一个Bert得到的向量跟单个token的词嵌入的距离足够接近。
图4: Valid Token Loss
b) Single [MASK] Loss,
改写后的query必须要含有[MASK],不然去第二个BERT怎么去预测答案,为此需要鼓励Rewriter去输出[MASK]。
c) Prediction Loss,
计算第二个BERT在[MASK]位置上的预测概率跟真实结果之间的交叉熵,从而评估模型最终是否可以抽取到正确的知识。
可以理解为BERTese利用了神经网络为每个query构建了一个prompt,然后融合得到改写后的结果,通过这种方式往往可以让模型预测到正确的答案。
图5: BERTese成功改写的样例
4 Gradient-based Search
这是基于梯度去搜索prompt的方式,
4.1 Trigger Search Algorithm【4】
模型攻击的一种方式就是通过给输入加入特定的信号,让模型去生成特定的输出。对于NLP分类任务而言,往模型中加入哪些trigger,可以让模型生成特定的结果呢?(加入这些trigger后,不管输入的内容是什么,模型只会生成特定结果,也就是模型遭受到攻击后没法正常服务了)。
图6: trigger的样例
**在给定模型f,我们想要搜寻trigger,使得dui yu对于任意的输入x,模型最终分类的结果都是不变的,也就是f(trigger;x)=y。** 首先选择trigger的长度,较长的trigger会更加有效,但是较短的trigger会更加多样化,接着通过重复”the”,“a”等方式初始化trigger的片段,然后将这些trigger片段跟输入拼接到一起, **不断迭代去替换trigger片段里的token使得模型预测结果f(trigger;x)跟期望的目标之间的距离最小化。迭代优化需要用到预测结果跟期望目标之间的损失在模型中的梯度,所以属于基于梯度的方法。**
图7: trigger更新的过程
4.2 AUTOPROMPT【5】
AUTOPROMPT是一种为下游任务自动搜索prompt的方式,它的目标是在搜寻合适的prompt,使得下游任务的表现最佳。 **我们想去搜寻那些可以在所有prompt共享使用的trigger** ,这里的trigger会先用[MASK]进行初始化,然后不断迭代去更新,使得相应的最大似然函数尽可能大。 **在每一步中,首先计算将某个trigger的token替换为另一个token的对数似然函数的变化的一阶近似,从而可以得到变化最大的K个token(这里的变化是计算相应的token的词嵌入跟对应trigger的token在嵌入层的梯度的乘积,变化越大说明越合适),将其作为候选集。对于候选集的元素,计算在相应prompt在数据中的表现,保留效果最好的部分,作为更新得到的prompt。**
图8: AUTOPROMPT候选集构建
5 Prompt Generation【6】【7】
**利用模型T5通过生成的方式去构建prompt。** 模型T5预训练任务就是去预测那些[MASK]位置的token,所以可以简单的将句子输入T5,然后让T5去生成相应的prompt,这样也就不用去指定prompt对应的token数量了。例如图中左边是原始的数据,通过规则可以转化为右边的格式,M(y)是答案空间(不清楚的可以去看入门篇),<x><y>是占位符,将右边的格式输入到T5后,T5会预测占位符<x><y>位置上的token,进而得到prompt。
图9: 数据转换
图10: prompt generation的流程
6 Prompt Scoring【8】
**通过人工构建prompt的方式生成候选集,然后让语言模型对候选集里的prompt打分,选择最合适的prompt。前面提到的涉及多个prompt排序都是直接在看下游任务表现的,而这里却是用语言模型来打分。**
给定知识三元组x=(h,r,t),其中h,t可以理解有关系的头部和尾部,r是关系,我们需要为r搜寻一种最优的prompt。针对每一种关系,会人工构建prompt,然后根据不同的prompt将三元组转化为不同的句子,通过语言模型计算这些句子的似然函数值,只 **保留最终似然函数值最大的那些句子。通过这一步就可以把三元组转化为合适的句子。** 然后再根据这些句子, **利用掩码语言模型来对prompt打分,打分方式如下图** 。其中的logp(t|h,r)就是将涉及t的token给mask掉,然后预测对应mask的位置,计算不同prompt对应分数,从而能选取一个最合适的prompt。
图11:prompt打分函数
7 总结
离散型的人工构建prompt的方式层出不穷,可以通过种子prompt去扩充,可以通过生成方式去获取,在构建得到prompt候选集后,可以在直接在下游任务上评估,也可以通过语言模型去打分,最终可以只选择最合适的一种prompt,也可以集成多个prompt。总而言之,这里面的组合千变万化,在具体任务上需要多加考虑。
参考文献
- (2020, ) How Can We Know What Language Models Know?
- (2021,) BARTSCORE: Evaluating Generated Text as Text Generation
https://arxiv.org/pdf/2106.11520.pdf
- (2021, ) BERTese: Learning to Speak to BERT
https://aclanthology.org/2021.eacl-main.316.pdf
- (2019, ) Universal Adversarial Triggers for Attacking and Analyzing NLP
https://aclanthology.org/D19-1221.pdf
- (2020, ) AutoPrompt: Eliciting knowledge from language models with automatically generated prompts.
https://arxiv.org/pdf/2010.15980v1.pdf
- (2021, ) Making pre-trained language models better few-shot learners
https://arxiv.org/pdf/2012.15723v2.pdf
- (2022, ) PADA: Example-based Prompt Learning for on-the-fly Adaptation to Unseen Domains
https://arxiv.org/pdf/2102.12206.pdf
- (2019, ) Commonsense Knowledge Mining from Pretrained Models