借着ChatGPT的东风,我们来梳理下prompt范式的相关模型。本系列会以A Systematic Survey of Prompting Methods in Natural Language Processing这篇综述为基础,分门别类的整理下这几年比较有代表性的prompt模型。或许你还以其他形式看到过prompt概念,例如Demonstration,Instruction,In-Context learning,few-shot learning等等
开篇我们简单介绍下Prompt范式,并以其中的冻结参数Tunning-Free Prompt为线索串联GPT2,GPT3,LAMA和AutoPrompt这四种冻结参数的基础模型
- 综述1.Pre-train, Prompt, and Predict: A Systematic Survey of Prompting Methods in Natural Language Processing(五星好评)
- 综述2. Paradigm Shift in Natural Language Processing(四星推荐)
- 综述3. Pre-Trained Models: Past, Present and Future
Prompt即提示学习,是继预训练+微调范式后众望所归的第四范式。在预训练+微调的范式中我们调整预训练模型来匹配下游任务数据,本质是对预训练学到的众多信息进行重新排列和筛选。而Prompt是通过引入“提示信息”,让模型回忆起预训练中学过的语言知识,也就是调整下游数据来适配预训练模型,进而把所有NLP任务都统一成LM任务。
举几个例子,以下[x]为prompt提示词,[z]为模型预测
看着非常玄妙!但其实部分原理就来自于于超大的预训练数据中包含的丰富文本知识。例如English2French的翻译任务,在预训练文本中会自然出现一些英法的对应文本如下。而提示词的加入可以理解为尝试还原模型在以下场景中的上下文(Attention)
那和预训练+微调的范式相比,Prompt有什么优势?
Prompt模型的设计主要包含以下几个模块,
我们先按照Training Strategy的不同,来梳理下各个方向的基础模型,再进阶的前沿模型,哈哈所以得花点时间才能轮到ChatGPT。第一章介绍Tunning-Free Prompt,在下游任务使用中LM和Prompt都是冻结的,不需要针对下游任务进行微调,可以用于Zero-shot和few-shot场景,主要介绍下GPT2,GPT3,LAMA和AutoPrompt。
- GPT2:Language Models are Unsupervised Multitask Learners,2019.2
- 任务:NLG
- Prompt: Discrete + Hand crafted Prompt
- 核心:Language Model本身就是无监督的多任务学习
在前BERT时代,通用文本表征-GenSen就探索过通过多任务得到在不同下游任务中泛化能力更好的文本表征,而后BERT时代,MQPN,MTDNN等模型也探索过如何通过多任务学习得到更加通用的大模型。
GPT2更往前迈了一步,它认为如果语言模型足够优秀,则在拟合\(P(output|input)\)的过程中,对\(p(output|input,task)\)也会进行学习,因为NLP任务信息本身就会在丰富的预训练预料中出现,例如上面我们举的翻译的case。和GPT相比,GPT2的创新就是在“LM是无监督多任务”这个观点上,所以GPT2的评测是基于无finetune的zero-shot场景进行的,旨在证明足够优秀的语言模型是可以不经过微调直接用在不同的下游场景中的。
那如何让模型针对不同的任务给出预测呢?作者通过在原始Input上加入任务相关提示词的方式,这不prompt就来了!举个栗子
几年前看GPT2的论文,只觉得模型更大了(评估是用的1542M的版本是Bert-large的5倍),样本更多了,zero-shot的能力挺新奇但是效果差点意思。如今从Prompt的角度重读,GPT2更像是在探索模型zero-shot能力的时候不小心推开了prompt的大门,从最直观的视角构建了Prompt提示词,也就是类似的任务在常规文本中是以什么形式(关键词)出现的,就以该形式构建文本输入即可~
除此之外GPT2对模型的微调以及构造了更大质量更高的数据集这里就不细说了~
- GPT3: Language Models are Few-Shot Learners, 2020.5
- Making pre-trained language models better few-shot learners
- 任务:无所不能
- Prompt: Discrete + Hand crafted Prompt + Prompt Augmentation
- 核心:大力出奇迹!175B大模型在few-shot,zero-shot的模型表现甚至可以比肩微调
GPT3是GPT2的延续,一方面旨在进一步提高模型的zero-shot能力,方法简单粗暴加参数就完事了!175Billion的参数首次证明了规模的量变会带来质变![Ref8]详细论证了大模型会带来一些奇迹般的能力,包括更强的复杂推理,知识推理,和样本外泛化能力!
另一方面GPT3在few-shot场景做了很多尝试,提出了自带神秘光环的in-context learning,可以被归类为multi-prompt中的prompt augmentation方案~
GPT3的模型结构延续GPT系列,但测试了不同模型参数量级的8个模型在不同下游任务上的效果,从125M到175B,模型效果在zero/one/few-shot的设定下都有稳步提升。在TriviaQA等任务上175B的GPT3甚至超越微调模型拿到了SOTA,算是预训练模型超越微调模型的第一次。但在NLI(判断两个句子是相似,对立,中性),WiC(判断一个单词是否在两个句子中含义相同)两个任务上GPT3的表现非常差,看起来似乎对涉及两个句子间逻辑推断的任务并不擅长。或许因为类似两个文本的逻辑推断在预训练文本中未出现过?
针对GPT3变态的模型大小,咱不聊技术垄断,OpenAI好有钱blabla我更好奇的是增长的参数究竟是如何提升模型能力?是更多的参数可以记忆更多的知识?还是更大的向量空间可以让模型学到更加线性可分的空间表征,使得下游任务对信息的解码更加简单,所以在few-shot场景有更好的表现?还没看到较严谨的论证,有知道的盆友求答疑解惑
论文在GPT2已有的zero-shot的基础上,提出了In-Context learning的概念,也称类比学习,上下文学习或者语境学习。有one-shot和few-shot两种方案,对应不同的增强Prompt的构建方式。随着模型参数量级的提升,few-shot,one-shot带来的效果提升更加显著。以英翻法任务为例
GPT3对其他NLP任务的prompt构建方案详见论文附录G~
对于Prompt Augmentation带来的效果提升,个人感觉in-context这个词的使用恰如其分,就是带答案的样本输入其实做了和任务描述相似的事情,也就是让待预测的输入处于和预训练文本中任务相关语料相似的上下文。带答案的样本比任务描述本身更接近自然的上下文语境。
不过prompt增强的构建还有许多细节待研究,例如抽取哪些样本更好,不同样本模型预测结果是否稳健,样本答案的构建方式,样本的顺序是否有影响等等。针对素材生成的场景没啥所谓,但是对抽取,分类,QA等任务,如果不同的prompt会得到显著不同的结果,就让人很头疼了~
[Ref6]的论文更深入的探究了in-context具体提供了哪些信息,作者定位到以下4类信息
GPT3正式推开了in-context learning的大门,模型参数也断层式的增长进入了Billon级别,后面的Flan,PaLM,LaMDA皆是这个大小。不过就效果而言GPT3在部分任务上依旧会被小模型T5吊打,以至于模型规模增长到底是否是正确的技术方向一度被质疑,直到之后的Chain of Thought出现才被逆转,这个放在后面章节再说~
- LAMA: Language Models as Knowledge Bases? 2019.9
- Github: https://github.com/facebookresearch/LAMA
- 任务:NLU(实事抽取)
- prompt: cloze + Hand Craft Prompt
- 核心:不经过微调的Bert在知识抽取和开放与问答上效果惊人的好,可以比肩有监督的KG基准
LAMA是在GPT2和GPT3之间提出的一个探测(probe)任务,旨在研究预训练模型存储的知识信息,这里只考虑实体关系三元组(Subject, Relation, Object)。
LAMA设计的Probe方案就是人工设计的完形填空(cloze)类型的prompt模板。例如把出生地实体识别,转化成小明出生于[MASK]的完形填空任务,如果模型预测MASK正确,就认为模型掌握了这一知识。
来具体说下LAMA针对不同关系构建的Prompt模板。论文使用以下4个评测数据
Wikipedia抽取的事实,包括5种关系,论文只保留了出生地,死亡地,出生日期3种关系,因为剩余两种的预测结果为多token,而LAMA的答案模板限制只预测1个token。每种关系作者手工构建了Prompt填空模板,举个栗子
wikidata三元组,比Google-RE范围更广,作者选取了41种关系,每种关系采样了1000条事实。每种关系作者手工构建了Prompt模板,部分Prompt如下
多语言词之间的常识关系,作者只考虑object为英文单字的16种关系,部分prompt如下
QA数据集,论文选取了305条上下文无关,且回答为单字的问题。prompt模板通过人工把问题改造成MLM语句得到,举个例子
因为LAMA只检测实体三元组关系,所以除Squad外的prompt模板可以抽象为'[X] relation [Y]'的完形填空形式, 但是prompt构建本身还是依赖人工,完整的LAMA数据集详见github~
这类Hand Crafted Prompt的构建主要有2个问题,一个是全靠人工,另一个在论文中也有提到就是不同的prompt对结果有较大影响,那如何找到最优的构建方案是个需要解决的问题
在Answer模板上LAMA限定了答案只能是token,这和它选择的预训练模型是BERT有关,所以Answer的解析没啥好说的就判断预测token是否正确即可。
其他探测任务相关的细节这里就不展开,感兴趣的盆友可以去看论文~
- paper: AutoPrompt Eliciting Knowledge from Language Models,2020.10
- github: https://github.com/ucinlp/autoprompt
- 任务:NLU(NLI,实事抽取,关系抽取)
- prompt: Discrete + Gradient Search Prompt
AutoPrompt是在LAMA上的改进,针对LAMA需要人工构造Prompt的问题,提出了一种基于梯度自动生成提示词的方案。论文针对分类任务,作者设计了通用的prompt模板如下,在原始文本输入的基础上,拼接多个触发词[T],最后一个MASK token为模型预测[P]。
下面分别针对Prompt和Answer Engineering来说下细节
LAMA的一个核心问题就是人工构造Prompt的成本和效果的不确定性,AutoPrompt借鉴了文本对抗AdvTrigger的梯度搜索方案,给定样本和模型可以自动搜索任务相关触发词。
AdvTrigger旨在找到和输入以及模型无关的通用Trigger,把这个Trigger拼接在输入文本的开头或者结尾可以使得模型得到特定的结果,可以是增加模型的误判率,使得模型输出有种族歧视的文本,或者让模型输出相同的错误结果等等。以下是AdvTrigger中给出的例子(注意以下案例只显示模型结果)
AutoPrompt使用了相同的Trigger搜索方式,首先把触发词用[MASK]初始化,然后逐步迭代来最大化以下似然函数,即加入触发词后MASK预测为正确标签的概率最大化
每一步迭代通过用以下一阶泰勒展开来近似把触发词改成j后似然函数的变化(梯度*词向量),得到最大化似然函数的topK个触发词。然后把触发词拼接输入,重新计算上述似然函数。以上两步迭代多次,得到最终的TopK触发词,这里K作为超参可以有{3,6}个
所以AutoPrompt虽然省去了人工构建prompt,但是需要下游标注任务样本来搜索触发词,一定程度上不算是tunning-free范式,更像是Fixed-LM Prompt-Tunning,除非搜索得到的触发词能直接迁移到相同任务其他领域数据中,不过这部分论文中并未评测。
AutoPrompt除了评估事实抽取任务,还加入了对分类任务的评估所以需要对Answer部分进行额外处理把模型预测的token映射到分类标签。这里主要是多token到单label的映射,例如哪些单词代表情感正向,哪些是负向。依旧是基于下游人物样本的有监督方案,top-k标签词的选择需要两步
第一步是label表征,作者使用了模型对[MASK]的模型输出作为x,真实标签作为Y,训练了一个logit classifer,这时模型权重(hidden_size * label_size )其实就是标签的空间表征
第二步是token打分,作者把[MASK]替换为其他候选token,\(p(y|h_{token})\)概率值越高,意味着token的输出向量和标签向量相似度越高,因此选择概率值最高的K个token来作为标签的答案词。
最后我们看下AutoPrompt搜索得到的触发词和答案长啥样,可以说是完全出乎意料,毫无逻辑可言,触发词和答案候选词都很离谱哈哈哈
至于效果AutoPrompt超越LAMA嘛,本身AutoPrompt就是使用下游任务样本搜索的Prompt和label,不好才奇怪不是~~~
更多论文详见DecryptPrompt
我正在尝试测试是否存在表单。我是Rails新手。我的new.html.erb_spec.rb文件的内容是:require'spec_helper'describe"messages/new.html.erb"doit"shouldrendertheform"dorender'/messages/new.html.erb'reponse.shouldhave_form_putting_to(@message)with_submit_buttonendendView本身,new.html.erb,有代码:当我运行rspec时,它失败了:1)messages/new.html.erbshou
我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-
我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t
我有一个对象has_many应呈现为xml的子对象。这不是问题。我的问题是我创建了一个Hash包含此数据,就像解析器需要它一样。但是rails自动将整个文件包含在.........我需要摆脱type="array"和我该如何处理?我没有在文档中找到任何内容。 最佳答案 我遇到了同样的问题;这是我的XML:我在用这个:entries.to_xml将散列数据转换为XML,但这会将条目的数据包装到中所以我修改了:entries.to_xml(root:"Contacts")但这仍然将转换后的XML包装在“联系人”中,将我的XML代码修改为
为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar
我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
在MRIRuby中我可以这样做:deftransferinternal_server=self.init_serverpid=forkdointernal_server.runend#Maketheserverprocessrunindependently.Process.detach(pid)internal_client=self.init_client#Dootherstuffwithconnectingtointernal_server...internal_client.post('somedata')ensure#KillserverProcess.kill('KILL',
我已经从我的命令行中获得了一切,所以我可以运行rubymyfile并且它可以正常工作。但是当我尝试从sublime中运行它时,我得到了undefinedmethod`require_relative'formain:Object有人知道我的sublime设置中缺少什么吗?我正在使用OSX并安装了rvm。 最佳答案 或者,您可以只使用“require”,它应该可以正常工作。我认为“require_relative”仅适用于ruby1.9+ 关于ruby-主要:Objectwhenrun
我花了三天的时间用头撞墙,试图弄清楚为什么简单的“rake”不能通过我的规范文件。如果您遇到这种情况:任何文件夹路径中都不要有空格!。严重地。事实上,从现在开始,您命名的任何内容都没有空格。这是我的控制台输出:(在/Users/*****/Desktop/LearningRuby/learn_ruby)$rake/Users/*******/Desktop/LearningRuby/learn_ruby/00_hello/hello_spec.rb:116:in`require':cannotloadsuchfile--hello(LoadError) 最佳