0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

从预训练语言模型看MLM预测任务

深度学习自然语言处理 来源:老刘说NLP 作者:老刘说NLP 2022-11-14 14:56 次阅读

Prompt Learning是当前NLP的一个重要话题,已经有许多文章进行论述。

从本质上来说,Prompt Learning 可以理解为一种下游任务的重定义方法,将几乎所有的下游任务均统一为预训练语言模型任务,从而避免了预训练模型和下游任务之间存在的 gap。

如此一来,几乎所有的下游 NLP 任务均可以使用,不需要训练数据,在小样本数据集的基础上也可以取得超越 Fine-Tuning 的效果,使得所有任务在使用方法上变得更加一致,而局限于字面意义上的理解还远远不够,我们可以通过一种简单、明了的方式进行讲述。

为了解决这一问题,本文主要从预训练语言模型看MLM预测任务、引入prompt_template的MLM预测任务、引入verblize类别映射的Prompt-MLM预测、基于zero-shot的prompt情感分类实践以及基于zero-shot的promptNER实体识别实践五个方面,进行代码介绍,供大家一起思考。

一、从预训练语言模型看MLM预测任务

MLM和NSP两个任务是目前BERT等预训练语言模型预训任务,其中MLM要求指定周围词来预测中心词,其模型机构十分简单,如下所示:

importtorch.nnasnn
fromtransformersimportBertModel,BertForMaskedLM
classBert_Model(nn.Module):
def__init__(self,bert_path,config_file):
super(Bert_Model,self).__init__()
self.bert=BertForMaskedLM.from_pretrained(bert_path,config=config_file)#加载预训练模型权重
defforward(self,input_ids,attention_mask,token_type_ids):
outputs=self.bert(input_ids,attention_mask,token_type_ids)#maskedLM输出的是mask的值对应的ids的概率,输出会是词表大小,里面是概率
logit=outputs[0]#池化后的输出[bs,config.hidden_size]
returnlogit

下面一段代码,简单的使用了hugging face中的bert-base-uncased进行空缺词预测,先可以得到预训练模型对指定[MASK]位置上概率最大的词语【词语来自于预训练语言模型的词表】。

例如给定句子"natural language processing is a [MASK] technology.",要求预测出其中的[MASK]的词:

>>>fromtransformersimportpipeline
>>>unmasker=pipeline('fill-mask',model='bert-base-uncased')
>>>unmasker("naturallanguageprocessingisa[MASK]technology.")
[{'score':0.18927036225795746,'token':3274,'token_str':'computer','sequence':'naturallanguageprocessingisacomputertechnology.'},
{'score':0.14354903995990753,'token':4807,'token_str':'communication','sequence':'naturallanguageprocessingisacommunicationtechnology.'},
{'score':0.09429361671209335,'token':2047,'token_str':'new','sequence':'naturallanguageprocessingisanewtechnology.'},
{'score':0.05184786394238472,'token':2653,'token_str':'language','sequence':'naturallanguageprocessingisalanguagetechnology.'},
{'score':0.04084266722202301,'token':15078,'token_str':'computational','sequence':'naturallanguageprocessingisacomputationaltechnology.'}]

从结果中,可以显然的看到,[MASK]按照概率从大到小排序后得到的结果是,computer、communication、new、language以及computational,这直接反馈出了预训练语言模型能够有效刻画出NLP是一种计算机、交流以及语言技术。

二、引入prompt_template的MLM预测任务

因此,既然语言模型中的MLM预测结果能够较好地预测出指定的结果,那么其就必定包含了很重要的上下文知识,即上下文特征,那么,我们是否可以进一步地让它来执行文本分类任务?即使用[MASK]的预测方式来预测相应分类类别的词,然后再将词做下一步与具体类别的预测?

实际上,这种思想就是prompt的思想,将下游任务对齐为预训练语言模型的预训练任务,如NPS和MLM,至于怎么对齐,其中引入两个概念,一个是prompt_template,即提示模版,以告诉模型要生成与任务相关的词语。因此,将任务原文text和prompt_template进行拼接,就可以构造与预训练语言模型相同的预训练任务。

例如,

>>>fromtransformersimportpipeline
>>>unmasker=pipeline('fill-mask',model='bert-base-uncased')
>>>text="Ireallylikethefilmalot."
>>>prompt_template="Becauseitwas[MASK]."
>>>pred1=unmasker(text+prompt_template)
>>>pred1
[
{'score':0.14730973541736603,'token':2307,'token_str':'great','sequence':'ireallylikethefilmalot.becauseitwasgreat.'},
{'score':0.10884211212396622,'token':6429,'token_str':'amazing','sequence':'ireallylikethefilmalot.becauseitwasamazing.'},
{'score':0.09781625121831894,'token':2204,'token_str':'good','sequence':'ireallylikethefilmalot.becauseitwasgood.'},
{'score':0.04627735912799835,'token':4569,'token_str':'fun','sequence':'ireallylikethefilmalot.becauseitwasfun.'},
{'score':0.043138038367033005,'token':10392,'token_str':'fantastic','sequence':'ireallylikethefilmalot.becauseitwasfantastic.'}]

>>>text="thismoviemakesmeverydisgusting."
>>>prompt_template="Becauseitwas[MASK]."
>>>pred2=unmasker(text+prompt_template)
>>>pred2
[
{'score':0.05464331805706024,'token':9643,'token_str':'awful','sequence':'thismoviemakesmeverydisgusting.becauseitwasawful.'},
{'score':0.050322480499744415,'token':2204,'token_str':'good','sequence':'thismoviemakesmeverydisgusting.becauseitwasgood.'},
{'score':0.04008950665593147,'token':9202,'token_str':'horrible','sequence':'thismoviemakesmeverydisgusting.becauseitwashorrible.'},
{'score':0.03569378703832626,'token':3308,'token_str':'wrong','sequence':'thismoviemakesmeverydisgusting.becauseitwaswrong.'},
{'score':0.033358603715896606,'token':2613,'token_str':'real','sequence':'thismoviemakesmeverydisgusting.becauseitwasreal.'}]

上面,我们使用了表达正面和负面的两个句子,模型得到最高的均是与类型相关的词语,这也验证了这种方法的可行性。

三、引入verblize类别映射的Prompt-MLM预测

与构造prompt-template之外,另一个重要的点是verblize,做词语到类型的映射,因为MLM模型预测的词语很不确定,需要将词语与具体的类别进行对齐,比如将"great", "amazing", "good", "fun", "fantastic", "better"等词对齐到"positive"上,当模型预测结果出现这些词时,就可以将整个预测的类别设定为positive;

同理,将"awful", "horrible", "bad", "wrong", "ugly"等词映射为“negative”时,即可以将整个预测的类别设定为negative;

>>>verblize_dict={"pos":["great","amazing","good","fun","fantastic","better"],"neg":["awful","horrible","bad","wrong","ugly"]
...}
>>>hash_dict=dict()
>>>fork,vinverblize_dict.items():
...forv_inv:
...hash_dict[v_]=k
>>>hash_dict
{'great':'pos','amazing':'pos','good':'pos','fun':'pos','fantastic':'pos','better':'pos','awful':'neg','horrible':'neg','bad':'neg','wrong':'neg','ugly':'neg'}

因此,我们可以将这类方法直接加入到上面的预测结果当中进行修正,得到以下结果,

>>>[{"label":hash_dict[i["token_str"]],"score":i["score"]}foriinpred1]
[{'label':'pos','score':0.14730973541736603},{'label':'pos','score':0.10884211212396622},{'label':'pos','score':0.09781625121831894},{'label':'pos','score':0.04627735912799835},{'label':'pos','score':0.043138038367033005}]

>>>[{"label":hash_dict.get(i["token_str"],i["token_str"]),"score":i["score"]}foriinpred2]
[{'label':'neg','score':0.05464331805706024},{'label':'pos','score':0.050322480499744415},{'label':'neg','score':0.04008950665593147},{'label':'neg','score':0.03569378703832626},{'label':'real','score':0.033358603715896606}]

通过取top1,可直接得到类别分类结果,当然也可以综合多个预测结果,可以获top10中各个类别的比重,以得到最终结果:

{
"text":"Ireallylikethefilmalot.","label":"pos"
"text":"thismoviemakesmeverydisgusting.","label":"neg"
}

至此,我们可以大致就可以大致了解在zero-shot场景下,prompt的核心所在。而我们可以进一步的想到,如果我们有标注数据,又如何进行继续训练,如何更好的设计prompt-template以及做好这个词语映射词表,这也是prompt-learning的后续研究问题。

因此,我们可以进一步地形成一个完整的基于训练数据的prompt分类模型,其代码实现样例具体如下,从中我们可以大致在看出具体的算法思想,我们命名为prompt.py

fromtransformersimportAutoModelForMaskedLM,AutoTokenizer
importtorch

classPrompting(object):

def__init__(self,**kwargs):
model_path=kwargs['model']
tokenizer_path=kwargs['model']
if"tokenizer"inkwargs.keys():
tokenizer_path=kwargs['tokenizer']
self.model=AutoModelForMaskedLM.from_pretrained(model_path)
self.tokenizer=AutoTokenizer.from_pretrained(model_path)

defprompt_pred(self,text):
"""
输入带有[MASK]的序列,输出LM模型Vocab中的词语列表及其概率
"""
indexed_tokens=self.tokenizer(text,return_tensors="pt").input_ids
tokenized_text=self.tokenizer.convert_ids_to_tokens(indexed_tokens[0])
mask_pos=tokenized_text.index(self.tokenizer.mask_token)
self.model.eval()
withtorch.no_grad():
outputs=self.model(indexed_tokens)
predictions=outputs[0]
values,indices=torch.sort(predictions[0,mask_pos],descending=True)
result=list(zip(self.tokenizer.convert_ids_to_tokens(indices),values))
self.scores_dict={a:bfora,binresult}
returnresult

defcompute_tokens_prob(self,text,token_list1,token_list2):
"""
给定两个词表,token_list1表示表示正面情感positive的词,如good,great,token_list2表示表示负面情感positive的词,如good,great,bad,terrible.
在计算概率时候,统计每个类别词所占的比例,score1/(score1+score2)并归一化,作为最终类别概率。
"""
_=self.prompt_pred(text)
score1=[self.scores_dict[token1]iftoken1inself.scores_dict.keys()else0
fortoken1intoken_list1]
score1=sum(score1)
score2=[self.scores_dict[token2]iftoken2inself.scores_dict.keys()else0
fortoken2intoken_list2]
score2=sum(score2)
softmax_rt=torch.nn.functional.softmax(torch.Tensor([score1,score2]),dim=0)
returnsoftmax_rt

deffine_tune(self,sentences,labels,prompt="Sinceitwas[MASK].",goodToken="good",badToken="bad"):
"""
对已有标注数据进行Fine tune训练。
"""
good=tokenizer.convert_tokens_to_ids(goodToken)
bad=tokenizer.convert_tokens_to_ids(badToken)
fromtransformersimportAdamW
optimizer=AdamW(self.model.parameters(),lr=1e-3)
forsen,labelinzip(sentences,labels):
tokenized_text=self.tokenizer.tokenize(sen+prompt)
indexed_tokens=self.tokenizer.convert_tokens_to_ids(tokenized_text)
tokens_tensor=torch.tensor([indexed_tokens])
mask_pos=tokenized_text.index(self.tokenizer.mask_token)
outputs=self.model(tokens_tensor)
predictions=outputs[0]
pred=predictions[0,mask_pos][[good,bad]]
prob=torch.nn.functional.softmax(pred,dim=0)
lossFunc=torch.nn.CrossEntropyLoss()
loss=lossFunc(prob.unsqueeze(0),torch.tensor([label]))
loss.backward()
optimizer.step()

四、基于zero-shot的prompt情感分类实践

下面我们直接以imdb中的例子进行zero-shot的prompt分类实践,大家可以看看其中的大致逻辑:

1、加入

>>fromtransformersimportAutoModelForMaskedLM,AutoTokenizer
>>importtorch
>>model_path="bert-base-uncased"
>>tokenizer=AutoTokenizer.from_pretrained(model_path)
>>frompromptimportPrompting
>>prompting=Prompting(model=model_path)

2、使用prompt_pred直接进行情感预测

>>prompt="Becauseitwas[MASK]."
>>text="Ireallylikethefilmalot."
>>prompting.prompt_pred(text+prompt)[:10]
[('great',tensor(9.5558)),
('amazing',tensor(9.2532)),
('good',tensor(9.1464)),
('fun',tensor(8.3979)),
('fantastic',tensor(8.3277)),
('wonderful',tensor(8.2719)),
('beautiful',tensor(8.1584)),
('awesome',tensor(8.1071)),
('incredible',tensor(8.0140)),
('funny',tensor(7.8785))]
>>text="Ididnotlikethefilm."
>>prompting.prompt_pred(text+prompt)[:10]
[('bad',tensor(8.6784)),
('funny',tensor(8.1660)),
('good',tensor(7.9858)),
('awful',tensor(7.7454)),
('scary',tensor(7.3526)),
('boring',tensor(7.1553)),
('wrong',tensor(7.1402)),
('terrible',tensor(7.1296)),
('horrible',tensor(6.9923)),
('ridiculous',tensor(6.7731))]

2、加入neg/pos词语vervlize进行情感预测

>>text="notworthwatching"
>>prompting.compute_tokens_prob(text+prompt,token_list1=["great","amazin","good"],token_list2=["bad","awfull","terrible"])
tensor([0.1496,0.8504])

>>text="Istronglyrecommendthatmoview"
>>prompting.compute_tokens_prob(text+prompt,token_list1=["great","amazin","good"],token_list2=["bad","awfull","terrible"])
tensor([0.9321,0.0679])

>>text="Istronglyrecommendthatmoview"
>>prompting.compute_tokens_prob(text+prompt,token_list1=["good"],token_list2=["bad"])
tensor([0.9223,0.0777])

五、基于zero-shot的promptNER实体识别实践

进一步的,我们可以想到,既然分类任务可以进行分类任务,那么是否可以进一步用这种方法来做实体识别任务呢?

实际上是可行的,暴力的方式,通过获取候选span,然后询问其中实体所属的类型集合。

1、设定prompt-template

同样的,我们可以设定template,以一个人物为例,John是一个非常常见的名字,模型可以直接知道它是一个人,而不需要上下文

Sentence.Johnisatypeof[MASK]

2、使用prompt_pred直接进行预测我们直接进行处理,可以看看效果:

>>prompting.prompt_pred("JohnwenttoParistovisittheUniversity.Johnisatypeof[MASK].")[:5]
[('man',tensor(8.1382)),
('john',tensor(7.1325)),
('guy',tensor(6.9672)),
('writer',tensor(6.4336)),
('philosopher',tensor(6.3823))]
>>prompting.prompt_pred("SavaşwenttoParistovisittheuniversity.Savaşisatypeof[MASK].")[:5]
[('philosopher',tensor(7.6558)),
('poet',tensor(7.5621)),
('saint',tensor(7.0104)),
('man',tensor(6.8890)),
('pigeon',tensor(6.6780))]

2、加入类别词语vervlize进行情感预测
进一步的,我们加入类别词,进行预测,因为我们需要做的识别是人物person识别,因此我们可以将person类别相关的词作为token_list1,如["person","man"],其他类型的,作为其他词语,如token_list2为["location","city","place"]),而在其他类别时,也可以通过构造wordlist字典完成预测。

>>>prompting.compute_tokens_prob("Itisatypeof[MASK].",
token_list1=["person","man"],token_list2=["location","city","place"])
tensor([0.7603,0.2397])

>>>prompting.compute_tokens_prob("SavaşwenttoParistovisittheparliament.Savaşisatypeof[MASK].",
token_list1=["person","man"],token_list2=["location","city","place"])//确定概率为0.76,将大于0.76的作为判定为person的概率
tensor([9.9987e-01,1.2744e-04])

从上面的结果中,我们可以看到,利用分类方式来实现zero shot实体识别,是直接有效的,“Savaş”判定为person的概率为0.99,

prompting.compute_tokens_prob("SavaşwenttoLaristovisittheparliament.Larisisatypeof[MASK].",
token_list1=["person","man"],token_list2=["location","city","place"])
tensor([0.3263,0.6737])

而在这个例子中,将“Laris”这一地点判定为person的概率仅仅为0.3263,也证明其有效性。

总结

本文主要从预训练语言模型看MLM预测任务、引入prompt_template的MLM预测任务、引入verblize类别映射的Prompt-MLM预测、基于zero-shot的prompt情感分类实践以及基于zero-shot的promptNER实体识别实践五个方面,进行了代码介绍。

关于prompt-learning,我们可以看到,其核心就在于将下游任务统一建模为了预训练语言模型的训练任务,从而能够最大地挖掘出预训模型的潜力,而其中的prompt-template以及对应词的构造,这个十分有趣,大家可以多关注。

审核编辑 :李倩


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 语言模型
    +关注

    关注

    0

    文章

    466

    浏览量

    10171
  • nlp
    nlp
    +关注

    关注

    1

    文章

    466

    浏览量

    21888

原文标题:Prompt总结 | 从MLM预训任务到Prompt Learning原理解析与Zero-shot分类、NER简单实践

文章出处:【微信号:zenRRan,微信公众号:深度学习自然语言处理】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    【大规模语言模型理论到实践】- 阅读体验

    再次感谢电子发烧友提供的书籍试读机会。今天来分享下我在学习大模型训练中 注意力机制 的心得体会。 虽然注意力机制可以显著提高模型处理长序列数据的能力,但这也带来了计算成本的增加。在大型模型
    发表于 06-07 14:44

    语言模型:原理与工程时间+小白初识大语言模型

    语言模型进行训练,此处训练为自然语言处理领域的
    发表于 05-12 23:57

    【大语言模型:原理与工程实践】大语言模型的应用

    操作。所谓零样本提示(Zero-Shot Prompt),指的是在提示词中不包含与指令任务相似的任何示例。 当大语言模型训练完成后,它便具备了分析情绪和识别命名实体等常见
    发表于 05-07 17:21

    【大语言模型:原理与工程实践】大语言模型的评测

    语言模型的评测是确保模型性能和应用适应性的关键环节。基座模型到微调模型,再到行业
    发表于 05-07 17:12

    【大语言模型:原理与工程实践】大语言模型训练

    语言模型的核心特点在于其庞大的参数量,这赋予了模型强大的学习容量,使其无需依赖微调即可适应各种下游任务,而更倾向于培养通用的处理能力。然而,随着学习容量的增加,对
    发表于 05-07 17:10

    【大语言模型:原理与工程实践】大语言模型的基础技术

    特定任务模型进行微调。这种方法的成功不仅是自然语言处理发展的一个转折点,还为许多现实世界的应用场带来了前所未有的性能提升。广为人知的GPT到BERT,
    发表于 05-05 12:17

    【大语言模型:原理与工程实践】核心技术综述

    的复杂模式和长距离依赖关系。 训练策略: 训练是LLMs训练过程的第一阶段,模型在大量的
    发表于 05-05 10:56

    【大语言模型:原理与工程实践】揭开大语言模型的面纱

    获得良好效果。 语言模型作为自然语言处理的核心,不断进化以捕捉人类语言的精髓。起初,这些模型依赖于统计方法,如n-gram
    发表于 05-04 23:55

    【大语言模型:原理与工程实践】探索《大语言模型原理与工程实践》

    处理中训练架构Transformer,以及这些技术在现实世界中的如何应用。通过具体案例的分析,作者展示了大语言模型在解决实际问题中的强大能力,同时也指出了当前技术面临的挑战和局限性。
    发表于 04-30 15:35

    名单公布!【书籍评测活动NO.30】大规模语言模型理论到实践

    等多种形式和任务。这个阶段是语言模型向对话模型转变的关键,其核心难点在于如何构建训练数据,包括
    发表于 03-11 15:16

    如何基于深度学习模型训练实现工件切割点位置预测

    Hello大家好,今天给大家分享一下如何基于深度学习模型训练实现工件切割点位置预测,主要是通过对YOLOv8姿态评估模型在自定义的数据集上训练
    的头像 发表于 12-22 11:07 430次阅读
    如何基于深度学习<b class='flag-5'>模型</b><b class='flag-5'>训练</b>实现工件切割点位置<b class='flag-5'>预测</b>

    如何基于深度学习模型训练实现圆检测与圆心位置预测

    Hello大家好,今天给大家分享一下如何基于深度学习模型训练实现圆检测与圆心位置预测,主要是通过对YOLOv8姿态评估模型在自定义的数据集上训练
    的头像 发表于 12-21 10:50 1029次阅读
    如何基于深度学习<b class='flag-5'>模型</b><b class='flag-5'>训练</b>实现圆检测与圆心位置<b class='flag-5'>预测</b>

    LabVIEW进行癌症预测模型研究

    ,然后将得到的特征向量输入到SVM中进行分类。 LabVIEW是一种视觉编程语言,与传统的文本编程语言不同,更适合于进行复杂数据分析和预测模型的开发。 LabVIEW使用数据流
    发表于 12-13 19:04

    语言模型简介:基于大语言模型模型全家桶Amazon Bedrock

    本文基于亚马逊云科技推出的大语言模型与生成式AI的全家桶:Bedrock对大语言模型进行介绍。大语言模型
    的头像 发表于 12-04 15:51 534次阅读

    训练语言模型带来的硬件挑战

    生成式AI和大语言模型(LLM)正在以难以置信的方式吸引全世界的目光,本文简要介绍了大语言模型训练这些
    的头像 发表于 09-01 17:14 1235次阅读
    <b class='flag-5'>训练</b>大<b class='flag-5'>语言</b><b class='flag-5'>模型</b>带来的硬件挑战