赞
踩
在原始的bert模型中,有两个训练任务,masked prediction(M)和next sentence prediction(NSP),所以针对这两个任务,在基本的BertModel主体后面接有两个branch,分别负责一个任务。最后算两个支路的损失之和。
先说BertModel这个基础的主体机构,在上面的链接文章中已经说得比较详细了,就是分为embedding,encoder,pooler这三部分,输出是encoder和pooler两个输出。(这里具体说一下,pooler就是一个全连接层和激活层,对encoder输出的feature的第一个词向量,即[CLS]对应的输出,进行一个全连接的计算,输出还是768维。而encoder输出就是全部的词向量)。
在BertModel的基础上,NSP分支就是一个全连接,称为seq_relationship(在权重命名中体现),将pooler输出的向量变成2维(是/否下一句话)。M分支是称为predictions,它包括transform,decoder两部分,transform是768->768的全连接,decoder是768->21128的反embedding层,实现嵌入到稀疏编码的转换。
最后,我们做损失时,对于NSP分支,就是二分类损失,对于M分支,就是对应mask位置的独热码的交叉熵损失。总的损失就是两者之和。(之前不理解两个预训练任务是怎么做的,这里说明是同时做的,多任务学习)
然后,关于我们使用pytorch的transformers调用bert模型api时,很多调用方式,比如AutoModel,BertModel等,这里的话,两者是等效的,AutoModel最后也是找到bertmodel调用。还有就是,我们需要注意有几种结构调用,比如
BertModel.from_pretrained(),
BertForNextSentencePrediction.from_pretrained(),
BertModelForMaskedLM.from_pretrained(),
BertModelForSequenceClassification.from_pretrained(),
我们先说第一个,第一个调用的是我们上面说的BertModel主体,不含两个branch。
第二个和第三个就是调用的整个Model的每个分支,即NSP和M分支。
最后一个跟第二个很像,都是做一个分类任务,但是不一样的地方在于,最后一个模型做的是通用的分类,比如情感,主题等,而第二个是原生bert模型里的那个分支,预训练为上下句预测任务,所以两者在权重加载时会有区别。
我们加载的预训练模型都是bertmodel带两个分支的(2022.10更正)。
对于加载预训练模型,有如下两种方式,一种是直接在.from_pretrained()中放模型的名字。另一种是放预先下载好的模型权重的路径,但是在此之前要预先加载模型的config文件,这个在下载权重时会有。然后,对于上面的前三个调用模式,可以直接加载预训练权重,只不过有些是用不到的,但是对于最后一个,最后的分类全连接权重是不能直接从权重中获得的,是随机初始化。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。