【预训练语言模型】BERT原理解析、常见问题和微调实战
一、BERT原理
1、概述
2、BERT模型
- pre-training 阶段,BERT 在无标记的数据上进行无监督学习;
- fine-tuning 阶段,BERT利用预训练的参数初始化模型,并利用下游任务标记好的数据进行有监督学习,并对所有参数进行微调。

2.1、模型架构

2.2、输入

- Token Embeddings 采用的 WordPiece Tokenizer进行分词,词表数量为30000。每个 sequence 会以一个特殊的 classification token [CLS] 开始,同时这也会作为分类任务的输出;句子间会以 special seperator token [SEP] 进行分割。
- Segment Embedding也可以用来分割句子,但主要用来区分句子对。Embedding A 和 Embedding B 分别代表左右句子,如果是普通的句子就直接用 Embedding A。
- Position Embedding 是用来给词元Token定位的,学习出来的embedding向量。这与Transformer不同,Transformer中是预先设定好的值。
WordPiece Tokenizer分词器:采用 BPE 双字节编码,在单词进行拆分,比如 “loved” “loving” ”loves“ 会拆分成 “lov”,“ed”,“ing”,“es”。
2.3、预训练Pre-training
2.3.1、任务一:Masked LM

- 80% 的 [MASK] token 会继续保持 [MASK];—my dog is [MASK]
- 10% 的 [MASK] token 会被随机的一个单词取代;my dog is apple
- 10% 的 [MASK] token 会保持原单词不变(但是还是要预测)my dog is hairy
- 在 encoder 的输出上添加一个前馈神经网络,将其转换为词汇的维度
- softmax 计算词汇表中每个单词的概率
2.3.2、任务二:Next Sentence Prediction

- B有一半的几率是A的下一句,即正例;
- B有一半的几率是随机取一个句子作为负例。
2.4、微调Fine-tuning

- a、b 是 sentence-level 级别的任务,类似句子分类,情感分析等等,输入句子或句子对,在 [CLS] 位置接入 Softmax 输出 Label;
- c是token-level级别的任务,比如 QA 问题,输入问题和段落,在 Paragraph 对应输出的 hidden vector 后接上两个 Softmax 层,分别训练出 Span 的 Start index 和 End index(连续的 Span)作为 Question 的答案;
- d也是token-level级别的任务,比如命名实体识别问题,接上 Softmax 层即可输出具体的分类。
例如:
在分类任务中,例如情感分析等,只需要在 Transformer 的输出之上加一个分类层

在命名实体识别(NER)中,系统需要接收文本序列,标记文本中的各种类型的实体(人员,组织,日期等)。 可以用 BERT 将每个 token 的输出向量送到预测 NER 标签的分类层。



3. 结论
- BERT的Transformer Encoder的Self-Attention结构能较好地建模上下文,而且在经过在语料上预训练后,能获取到输入文本较优质的语义表征。
- BERT的MLP和NSP联合训练,让其能适配下游多任务(Token级别和句子级别)的迁移学习
- [MASK] token在推理时不会出现,因此训练时用过多的[MASK]会影响模型表现(需要让下游任务去适配预训练语言模型,而不是让预训练语言模型主动针对下游任务做优化)
- 每个batch只有15%的token被预测,所以BERT收敛得比left-to-right模型要慢(BERT对语料的利用低。而GPT对语料的利用率更高,它几乎能利用句子的每个token);
- BERT的上下文长度固定为512,输入过长需要阶段(对长文本不友好)
二、BERT答疑
1、三个Embedding怎么来的
self.word_embeddings = Embedding(config.vocab_size, config.hidden_size)
self.position_embeddings = Embedding(config.max_position_embeddings, config.hidden_size)
self.token_type_embeddings = Embedding(config.type_vocab_size, config.hidden_size)

from transformers import AutoTokenizer checkpoint = "bert-base-uncased"
tokenizer = AutoTokenizer.from_pretrained(checkpoint)
tokenized_sentences_1 = tokenizer(raw_datasets["train"]["sentence1"])
tokenized_sentences_2 = tokenizer(raw_datasets["train"]["sentence2"])
nputs = tokenizer("This is the first sentence.", "This is the second one.") inputs
结果:input_ids为token ids, token_type_ids用于区分两个toke序列(对应segment embeddings)
{'input_ids': [101, 2023, 2003, 1996, 2034, 6251, 1012, 102, 2023, 2003, 1996, 2117, 2028, 1012, 102],
'token_type_ids': [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1],
'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
}
反tokenize
tokenizer.convert_ids_to_tokens(inputs["input_ids"])
结果
['[CLS]',
'this',
'is',
'the',
'first',
'sentence',
'.',
'[SEP]',
'this',
'is',
'the',
'second',
'one',
'.',
'[SEP]']
2、不考虑多头的原因,self-attention中词向量不乘QKV参数矩阵,会有什么问题?
3、为什么BERT选择mask掉15%这个比例的词,可以是其他的比例吗?
4、为什么BERT在第一句前会加一个[CLS]标志?

BERT在第一句前会加一个CLS]标志,最后一层该位对应向量可以作为整句话的语义表示,从而用于下游的分类任务等。与文本中已有的其它词相比,这个无明显语义信息的符号会更“公平”地融合文本中各个词的语义信息,从而更好的表示整句话的语义
5、Self-Attention 的时间复杂度是怎么计算的?
6、Transformer在哪里做了权重共享,为什么可以做权重共享?
7、BERT非线性的来源在哪里?
8. BERT参数量
- BERT-BASE-Uncase (L=12, H=768, A=12, Total Parameters=110M)
- BERT-LARGE-Uncase (L=24, H=1024, A=16, Total Parameters=340M)
三、BERT调包和微调
- 1. 所有的句子必须被填充或截断成一个固定的长度。
- 2. 最大的句子长度是512个tokens。

- 将句子分割成token。
- 添加特殊的[CLS]和[SEP]标记。
- 将这些标记映射到它们的ID上。
- 把所有的句子都垫上或截断成相同的长度。
- 创建注意力Masl,明确区分真实 token 和[PAD]token。
- BertModel
- BertForPreTraining
- BertForMaskedLM
- BertForNextSentencePrediction(下句预测)
- BertForSequenceClassification - 我们将使用的那个。
- BertForTokenClassification
- BertForQuestionAnswering
import torch
from transformers import AdamW, AutoTokenizer, AutoModelForSequenceClassification # Same as before
checkpoint = "bert-base-uncased"
tokenizer = AutoTokenizer.from_pretrained(checkpoint)
model = AutoModelForSequenceClassification.from_pretrained(checkpoint)
sequences = [
"I've been waiting for a HuggingFace course my whole life.",
"This course is amazing!",
]
batch = tokenizer(sequences, padding=True, truncation=True, return_tensors="pt") # This is new
batch["labels"] = torch.tensor([1, 1]) optimizer = AdamW(model.parameters())
loss = model(**batch).loss
loss.backward()
optimizer.step()
代码源自huggingface Transformer库教程
参考
- 用huggingface.transformers在文本分类任务(单任务和多任务场景下)上微调预训练模型https://blog.csdn.net/PolarisRisingWar/article/details/127365675
- 处理数据 - Hugging Face NLP Course
- 比赛:Datawhale零基础入门NLP赛事 - Task5 基于深度学习的文本分类https://tianchi.aliyun.com/notebook/118258
【预训练语言模型】BERT原理解析、常见问题和微调实战的更多相关文章
- 学习AI之NLP后对预训练语言模型——心得体会总结
一.学习NLP背景介绍: 从2019年4月份开始跟着华为云ModelArts实战营同学们一起进行了6期关于图像深度学习的学习,初步了解了关于图像标注.图像分类.物体检测,图像都目标物体检测等 ...
- 预训练语言模型的前世今生 - 从Word Embedding到BERT
预训练语言模型的前世今生 - 从Word Embedding到BERT 本篇文章共 24619 个词,一个字一个字手码的不容易,转载请标明出处:预训练语言模型的前世今生 - 从Word Embeddi ...
- 预训练语言模型整理(ELMo/GPT/BERT...)
目录 简介 预训练任务简介 自回归语言模型 自编码语言模型 预训练模型的简介与对比 ELMo 细节 ELMo的下游使用 GPT/GPT2 GPT 细节 微调 GPT2 优缺点 BERT BERT的预训 ...
- NLP中的预训练语言模型(五)—— ELECTRA
这是一篇还在双盲审的论文,不过看了之后感觉作者真的是很有创新能力,ELECTRA可以看作是开辟了一条新的预训练的道路,模型不但提高了计算效率,加快模型的收敛速度,而且在参数很小也表现的非常好. 论文: ...
- 知识增强的预训练语言模型系列之ERNIE:如何为预训练语言模型注入知识
NLP论文解读 |杨健 论文标题: ERNIE:Enhanced Language Representation with Informative Entities 收录会议:ACL 论文链接: ht ...
- 知识增广的预训练语言模型K-BERT:将知识图谱作为训练语料
原创作者 | 杨健 论文标题: K-BERT: Enabling Language Representation with Knowledge Graph 收录会议: AAAI 论文链接: https ...
- 知识增强的预训练语言模型系列之KEPLER:如何针对上下文和知识图谱联合训练
原创作者 | 杨健 论文标题: KEPLER: A unified model for knowledge embedding and pre-trained language representat ...
- 【译】深度双向Transformer预训练【BERT第一作者分享】
目录 NLP中的预训练 语境表示 语境表示相关研究 存在的问题 BERT的解决方案 任务一:Masked LM 任务二:预测下一句 BERT 输入表示 模型结构--Transformer编码器 Tra ...
- NLP中的预训练语言模型(三)—— XL-Net和Transformer-XL
本篇带来XL-Net和它的基础结构Transformer-XL.在讲解XL-Net之前需要先了解Transformer-XL,Transformer-XL不属于预训练模型范畴,而是Transforme ...
- NLP中的预训练语言模型(二)—— Facebook的SpanBERT和RoBERTa
本篇带来Facebook的提出的两个预训练模型——SpanBERT和RoBERTa. 一,SpanBERT 论文:SpanBERT: Improving Pre-training by Represe ...
随机推荐
- IT技术:开篇 - IT技术系列文章
笔者已经工作了十多年,在这十多年里,笔者在博客上也对自己所学的技术方面的事情记录成了博文.这些博文有些是笔者自己所学所记,有些是将网上的博文进行的转载.在经历了这么多的技术学习之后,笔者将自己的经验记 ...
- 小型命令解析器|minShell|多进程|重定向|进程控制【超详细的代码注释和解释】
前言 那么这里博主先安利一下一些干货满满的专栏啦! 手撕数据结构https://blog.csdn.net/yu_cblog/category_11490888.html?spm=1001.2014. ...
- 应用--WebApplication
应用--Program中的WebApplication 在6.0,微软团队对于NetCore做了很大的改变,其中有一个改变就是推出了新的托管模型--最小托管模型,使用该模型可以创建最小的web应用.( ...
- 【阅读笔记】对比度增强-《Efficientcontrast enhancement using adaptive gamma correction with weighting distribution 》 date: 2023-12-08 10:08:00
2013年发表在TIP上的对比度增强算法AGCWD(Efficient contrast enhancement using adaptive gamma correction with weight ...
- 小知识:在Exadata平台上使用ExaWatcher收集信息
在非Exadata平台上,我们通常会使用DBA已经很熟悉的OSW,如果有不熟悉的朋友可以参考我之前的随笔初步了解OSW: OSW 快速安装部署 OSW Analyzer分析oswbb日志发生异常 而在 ...
- 《ASP.ENT Core 与 RESTful API 开发实战》(第3章)-- 读书笔记(上)
第 3 章 ASP.NET Core 核心特性 3.1 启动与宿主 ASP.NET Core 应用程序启动时,它首先会配置并运行其宿主,宿主主要用来启动.初始化应用程序,并管理其生命周期 ASP.NE ...
- P5943 [POI2002] 最大的园地 题解
题目传送门 前置知识 单调栈 简化题意 在一个 \(n \times n\) 的正方形内找到最大的由 \(0\) 组成的子矩形的面积. 解法 令 \(f_{i,j}(1 \le i,j \le n)\ ...
- NC53079 Forsaken喜欢数论
题目链接 题目 题目描述 Forsaken有一个有趣的数论函数.对于任意一个数 \(x\) , \(f(x)\) 会返回 \(x\) 的最小质因子.如果这个数没有最小质因子,那么就返回0. 现 ...
- 基于keras的胶囊网络(CapsNet)
1 简介 胶囊网络(CapsNet)由 Hinton 于2017年10月在<Dynamic Routing Between Capsules>中提出,目的在于解决 CNN 只能提取特征,而 ...
- Go语言并发编程(4):sync包介绍和使用(下)-Once,Pool,Cond
sync包下:Once,Pool,Cond 一.sync.Once 执行一次 Once 简介 sync.Once 是 Go 提供的让函数只执行一次的一种实现. 如果 once.Do(f) 被调用多次, ...