论文BERT(3): 2018.10 Pre-training of Deep Bidirectional Transformers for Language Understanding;架构

3 架构BERT

在本节中,我们将介绍BERT及其详细实现。我们的框架包含两个步骤:预训练和微调。在预训练阶段,模型会在不同的预训练任务上针对未标记数据进行训练。在微调阶段,BERT模型首先使用预训练参数进行初始化,然后使用来自下游任务的有标记数据对所有参数进行微调。每个下游任务都有独立的微调模型,尽管它们都是使用相同的预训练参数进行初始化的。图1中的问答示例将作为本节的一个持续示例。

BERT的一个显著特点是其在不同任务上拥有统一的架构。预训练架构和最终下游架构之间的差异极小。

BERT的模型架构是一个多层双向Transformer编码器,基于Vaswani等人(2017)描述的原始实现,并在tensor2tensor库中发布。由于Transformer的使用已经变得非常普遍,且我们的实现与原始实现几乎相同,因此我们将省略对模型架构的详尽背景描述,并建议读者参考Vaswani等人(2017)的论文以及诸如“The Annotated Transformer”之类的优秀指南。

在这项工作中,我们用L表示层数(即Transformer块),用H表示隐藏层大小,用A表示自注意力头的数量。3我们主要报告了两个模型尺寸的结果:BERT BASE(L=12,H=768,A=12,总参数=1.1亿)和BERT LARGE(L=24,H=1024,A=16,总参数=3.4亿)。

BERT BASE的模型大小被选择与OpenAI GPT相同,以便进行比较。然而,至关重要的是,BERT的Transformer使用双向自注意力机制,而GPT的Transformer使用约束自注意力机制,其中每个标记只能关注其左侧的上下文。

输入输出标识

为了使BERT能够处理各种下游任务,我们的输入表示能够明确地表示单个句子和一对句子(例如,问题h和答案i)作为一个令牌序列。在这项工作中,“句子”可以是任意连续的文本片段,而不一定是实际的语言句子。“序列”指的是输入到BERT的令牌序列,这可能是一个单独的句子或两个组合在一起的句子。

我们使用WordPiece嵌入(Wu等人,2016年),包含3万个令牌的词汇表。每个序列的第一个令牌始终是一个特殊的分类令牌([CLS])。与此令牌对应的最终隐藏状态被用作分类任务的聚合序列表示。句子对会被打包成一个单独的序列。我们通过两种方式区分这些句子。首先,我们使用一个特殊的令牌([SEP])将它们分开。其次,我们为每个令牌添加一个学习过的嵌入,以指示它属于句子A还是句子B。如图1所示,我们将输入嵌入表示为E,特殊[CLS]令牌的最终隐藏向量表示为C ∈ R^H,第i个输入令牌的最终隐藏向量表示为T_i ∈ R^H。

对于给定的令牌,其输入表示是通过将相应的令牌嵌入、段嵌入和位置嵌入相加而构建的。这种构建的可视化可以在图2中看到。

3.1 BERT的预训练

与Peters等人(2018a)和Radford等人(2018)不同,我们没有使用传统的从左到右或从右到左的语言模型来预训练BERT。相反,我们使用两个无监督任务来预训练BERT,这些任务将在本节中描述。这一步在图1的左半部分中展示。

任务#1:掩码语言模型(Masked LM)

直觉上,人们有理由相信,一个深度双向模型严格来说要比从左到右的模型或者从左到右和从右到左模型的浅层拼接更强大。不幸的是,标准的条件语言模型只能从左到右或从右到左进行训练,因为双向条件会让每个单词间接地“看到”自己,模型可以在多层上下文中轻易地预测目标单词。

为了训练一个深度双向表示,我们只需随机地遮盖输入令牌的一定比例,然后预测这些被遮盖的令牌。我们将这个过程称为“掩码语言模型”(MLM),尽管在文献中它通常被称为Cloze任务(Taylor,1953)。在这种情况下,与标准语言模型一样,对应于掩码令牌的最终隐藏向量被送入一个输出softmax层,用于对词汇表中的词进行预测。在我们所有的实验中,我们随机遮盖每个序列中15%的WordPiece令牌。与去噪自编码器(Vincent等人,2008年)不同,我们只预测被遮盖的单词,而不是重构整个输入。

虽然这使我们能够获得一个双向预训练模型,但缺点是我们在预训练和微调之间产生了不匹配,因为在微调过程中不会出现[MASK]令牌。为了缓解这个问题,我们并不总是用实际的[MASK]令牌替换“被遮盖”的单词。训练数据生成器随机选择15%的令牌位置进行预测。如果选择了第i个令牌,我们会按照以下方式替换第i个令牌:(1)80%的时间用[MASK]令牌替换(2)10%的时间用随机令牌替换(3)10%的时间保持第i个令牌不变。然后,T_i将用于预测原始令牌,并计算交叉熵损失。我们在附录C.2中比较了这种过程的变种。

任务#2:下一句预测(NSP)

许多重要的下游任务,如问答(QA)和自然语言推理(NLI),都基于理解两个句子之间的关系,这种关系并未被语言模型直接捕获。为了训练一个能够理解句子间关系的模型,我们预先训练了一个二值化的下一句预测任务,该任务可以轻易地从任何单语语料库中生成。具体来说,在选择每个预训练示例中的句子A和B时,50%的时间里,B是紧随A出现的实际下一句(标记为IsNext),而另外50%的时间里,B是语料库中的一个随机句子(标记为NotNext)。正如我们在图1中展示的,C用于下一句预测(NSP)。尽管这个任务很简单,但我们在5.1节中证明,针对此任务的预训练对QA和NLI都非常有益。

NSP任务与Jernite等人(2017年)以及Logeswaran和Lee(2018年)中使用的表示学习目标密切相关。然而,在以前的工作中,只有句子嵌入被转移到下游任务中,而BERT则是将所有参数转移到下游任务模型参数的初始化中。

预训练数据

预训练过程在很大程度上遵循了现有文献中关于语言模型预训练的内容。对于预训练语料库,我们使用了BooksCorpus(8亿单词)(Zhu等人,2015年)和英文维基百科(25亿单词)。对于维基百科,我们只提取文本段落,忽略列表、表格和标题。为了提取长的连续序列,使用文档级别的语料库至关重要,而不是像十亿词基准(Billion Word Benchmark)(Chelba等人,2013年)那样打乱句子级别的语料库。

3.2 BERT微调

微调过程很直接,因为Transformer中的自注意力机制允许BERT通过替换适当的输入和输出来建模许多下游任务——无论这些任务是涉及单个文本还是文本对。对于涉及文本对的应用,一种常见的模式是在应用双向交叉注意力之前独立地对文本对进行编码,如Parikh等人(2016年)和Seo等人(2017年)所做的那样。然而,BERT使用自注意力机制来统一这两个阶段,因为使用自注意力对拼接的文本对进行编码实际上包括了两个句子之间的双向交叉注意力。

对于每个任务,我们只需将特定于任务的输入和输出插入BERT中,并对所有参数进行端到端的微调。在输入方面,预训练中的句子A和句子B类似于(1)释义中的句子对,(2)蕴含中的假设-前提对,(3)问答中的问题-段落对,以及(4)文本分类或序列标注中的退化文本-∅对。在输出方面,令牌表示被送入一个输出层,用于令牌级别的任务,如序列标注或问答;而[CLS]表示被送入一个输出层,用于分类任务,如蕴含或情感分析。

与预训练相比,微调相对便宜。从完全相同的预训练模型开始,论文中的所有结果都可以在单个Cloud TPU上在最多1小时内复制,或在GPU上在几小时内复制。我们在第4节的相应子节中描述了特定于任务的细节。更多细节可以在附录A.5中找到。

Ankie的评论:

在本节中,我们将介绍BERT及其详细实现。我们的框架包含两个步骤:预训练和微调。

在预训练阶段,模型会在不同的预训练任务上针对未标记数据进行训练。

在微调阶段,BERT模型首先使用预训练参数进行初始化,然后使用来自下游任务的有标记数据对所有参数进行微调。每个下游任务都有独立的微调模型,尽管它们都是使用相同的预训练参数进行初始化的。微调就是为了应试,跑分。所以后来的GPT放弃了微调,追求通用。

论文BERT(1): 2018.10 Pre-training of Deep Bidirectional Transformers for Language Understanding;摘要,引言-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/ank1983/article/details/137836156

  • 26
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
这个错误通常是由于使用了错误的tokenizer类导致的。在使用HuggingFaceEmbeddings时,你需要使用与模型相对应的tokenizer。如果使用了不兼容的tokenizer,就会出现这个错误。 在BERT模型的情况下,可以使用`BertTokenizer`或`BertTokenizerFast`。但是值得注意的是,这两个类的输入格式不同: - `BertTokenizer`的输入是单个句子或句子对,可以使用`encode`方法将句子转换为输入向量。 - `BertTokenizerFast`的输入是一批句子,需要使用`__call__`方法将句子转换为输入向量。 所以,如果你使用`BertTokenizerFast`类,你需要将句子封装成列表或元组,并将其传递给tokenizer。例如: ```python from transformers import BertTokenizerFast, BertModel from sentence_transformers import SentenceTransformer tokenizer = BertTokenizerFast.from_pretrained('bert-base-cased') model = BertModel.from_pretrained('bert-base-cased') sentences = ['This is an example sentence', 'Each sentence is converted'] input_ids = tokenizer(sentences, padding=True, truncation=True, return_tensors='pt') outputs = model(**input_ids) sentence_transformer_model = SentenceTransformer(modules=[model, tokenizer]) embeddings = sentence_transformer_model.encode(sentences) ``` 在这个例子中,我们使用了`BertTokenizerFast`类,并将句子列表传递给tokenizer进行编码。然后使用编码后的输入向量来计算BERT模型的输出。最后,我们使用SentenceTransformer将句子转换为嵌入向量。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ankie(资深技术项目经理)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值