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

    文章

    575

    浏览量

    11370
  • nlp
    nlp
    +关注

    关注

    1

    文章

    491

    浏览量

    23364

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

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

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    《多模态大模型 前沿算法与实战应用 第一季》精品课程简介

    为512维向量。 语言模态 :BERT、GPT等训练模型将文本转换为上下文相关的词嵌入。例如\"苹果\"在\"水果\"语境和\"科技公司\"
    发表于 05-01 17:46

    零基础手写大模型资料2026

    方式使模型能区分\"猫追狗\"和\"狗追猫\"的语义差异。 三、训练优化:原始代码到实用模型 1. 损失函数与优化器选择 分类任务常用交叉
    发表于 05-01 17:44

    AI Ceph 分布式存储教程资料大模型学习资料2026

    内存层构建分布式缓存池。通过感知训练任务的读取模式,系统能够预测下一步需要的数据块,并提前将其底层存储介质加载至缓存层,实现计算与 I/O 的流水线并行。此外,为了解决 Python 数据加载框架(如
    发表于 05-01 17:35

    HM博学谷狂野AI大模型第四期

    ,抽象的数学概念将转化为具象的张量流动逻辑。开发者将不再被复杂的网络结构图所迷惑,而是能够清晰地看到数据在模型内部的流动轨迹,为后续的模型优化与定制打下坚实的算法地基。 二、 训练引擎解构:
    发表于 05-01 17:30

    人工智能多模态与视觉大模型开发实战 - 2026必会

    ,学员们将亲自动手操作,数据收集与预处理开始,逐步深入到模型训练与优化。 数据收集是视觉大模型开发的第一步,需要收集大量与目标任务相关的高
    发表于 04-15 16:06

    训练到推理:大模型算力需求的新拐点已至

    在大模型产业发展的早期阶段,行业焦点主要集中在大模型训练所需的算力投入。一个万亿参数大模型训练可能需要数千张GPU芯片连续运行数月,成本高
    的头像 发表于 02-05 16:07 1111次阅读
    <b class='flag-5'>从</b><b class='flag-5'>训练</b>到推理:大<b class='flag-5'>模型</b>算力需求的新拐点已至

    什么是大模型,智能体...?大模型100问,快速全面了解!

    ,LLM)是大模型中最主要的一类,专门用于处理和生成人类语言。大语言模型通过“阅读”海量的文本数据(如书籍、网页、文章等)进行
    的头像 发表于 02-02 16:36 1195次阅读
    什么是大<b class='flag-5'>模型</b>,智能体...?大<b class='flag-5'>模型</b>100问,快速全面了解!

    数据到模型:如何预测细节距键合的剪切力?

    预估其剪切力?行业内的研究数据为我们揭示了可能性。今天,科准测控小编将带您了解如何基于实验数据建立并应用预测模型,实现从“测量”到“预估”的关键跨越。 一、平方定律到经验公式 直观上,我们可能会假设
    发表于 01-08 09:45

    RA8P1部署ai模型指南:训练模型到部署 | 本周六

    在嵌入式边缘AI中,如何把“训练好的模型”稳定地“跑在板子上”,决定了项目能否落地。我们带你基于RA8P1平台,跑通数据准备、模型训练、量
    的头像 发表于 11-20 18:06 2561次阅读
    RA8P1部署ai<b class='flag-5'>模型</b>指南:<b class='flag-5'>从</b><b class='flag-5'>训练</b><b class='flag-5'>模型</b>到部署 | 本周六

    如何将训练好的神经网络模型部署到蜂鸟e203开发板上

    运行模型推理: interpreter->Invoke();6. 输出张量中读取预测结果: // 假设输出为float类型float* output_data
    发表于 10-22 08:04

    在Ubuntu20.04系统中训练神经网络模型的一些经验

    模型。 我们使用MNIST数据集,训练一个卷积神经网络(CNN)模型,用于手写数字识别。一旦模型训练并保存,就可以用于对新图像进行推理和
    发表于 10-22 07:03

    基于大规模人类操作数据训练的VLA模型H-RDT

    近年来,机器人操作领域的VLA模型普遍基于跨本体机器人数据集训练,这类方法存在两大局限:不同机器人本体和动作空间的差异导致统一训练困难;现有大规模机器人演示数据稀缺且质量参差不齐。得
    的头像 发表于 08-21 09:56 1290次阅读
    基于大规模人类操作数据<b class='flag-5'>预</b><b class='flag-5'>训练</b>的VLA<b class='flag-5'>模型</b>H-RDT

    Text2SQL准确率暴涨22.6%!3大维度全拆

    摘要 技术背景:Text2SQL 是将自然语言查询转为 SQL 的任务,经历了基于规则、神经网络、训练语言
    的头像 发表于 08-14 11:17 879次阅读
    Text2SQL准确率暴涨22.6%!3大维度全拆

    利用自压缩实现大型语言模型高效缩减

    随着语言模型规模日益庞大,设备端推理变得越来越缓慢且耗能巨大。一个直接且效果出人意料的解决方案是剪除那些对任务贡献甚微的完整通道(channel)。我们早期的研究提出了一种训练阶段的方
    的头像 发表于 07-28 09:36 719次阅读
    利用自压缩实现大型<b class='flag-5'>语言</b><b class='flag-5'>模型</b>高效缩减

    CPU密集型任务开发指导

    以及后台长时间的模型预测任务分别进行举例。 使用TaskPool进行图像直方图处理 实现图像处理的业务逻辑。 数据分段,通过任务组发起关联任务
    发表于 06-19 06:05