BERT(预训练)
NLP 迁移学习的思路是:用大规模预训练模型(如 Word2vec、语言模型)提供通用语言知识,再加任务特定层做微调。但传统方法有++++时序或方向上的局限++++ ,而 Transformer(尤其是其双向 Self-Attention)为++++更好的预训练模型(BERT 等)++++提供了架构基础。
BERT 的设计动机 : 让 NLP(自然语言处理) 也能像 CV(ResNet等视觉模型) 一样,通过预训练 + 微调的方式高效解决各种下游任务。++++各种任务只换最后一层分类头++++ 。
BERT 的核心架构 = ++++只有 Encoder 的 Transformer++++
BERT 不需要 Decoder,因为它不做"生成下一个词",而是做"理解整个句子"。(双向)
特殊之处:
1.每个样本是一个句子对:BERT 预训练时,输入总是两个句子++++拼在一起++++
2.片段嵌入:BERT 新增了一个++++嵌入层++++ ,用来区分句子 A 和句子 B
3.位置编码可学习:不是固定的正余弦函数而是可学习的参数
- 最终输入表示BERT 的每个词的输入向量 = 三者相加
Input=Token Embedding+Segment Embedding+Position Embedding

训练BERT需要的两个训练任务:
第一个训练任务MLM 预训练BERT:
BERT 的 MLM 通过随机遮住 15% 的词(80% 变 <mask>、10% 变随机词、10% 不变),强迫双向 Encoder 根据左右上下文预测原词,++++从而学到深度的双向语言理解能力++++ 。
为什么不全换成<mask>?
如果预训练时全是 <mask>,但微调,实际使用时输入里没有 <mask>
如果训练时只见过 <mask>,真正用时看到正常句子,BERT 会"懵"
第二个预训练任务:Next Sentence Prediction(NSP )下一个句子预测
判断两个句子是否"相邻"
构造训练样本:

两个任务一起训练BERT,损失函数 = MLM 损失 + NSP 损失,一起反向传播。
BERT的代码实现:

给定两个句子,拼接得到BERT的输入:CLS + 句子A + SEP + 句子B(可选) + SEP

BERT的Encoder实现:
和Transformor的类似,有两个新增的部分

可学习的位置编码

X三层嵌入相加
BERTEncoder = 原始 Transformer Encoder + ++++可学习位置编码++++ + ++++片段嵌入++++ 。核心计算层(EncoderBlock)完全没变,只是输入表示层多了两个嵌入,让模型能区分++++"哪个句子"和"哪个位置"。++++
MLM预训练任务:
预训练时临时接在 BERT Encoder 后面,用来猜被遮住的词,与训练完后丢弃

一个四层的MLP
把 BERT Encoder 输出的某个位置的向量,映射到词表大小的概率分布

取出被Mask的位置然后做预测
BERTEncoder -> MaskLM -> 预测被遮住的词 -> 算损失 -> 更新所有权重
下一句预测NSP

整合整个模型:

BERT编码器+NSP的隐藏层+MLM的预测头+NSP预测头

过Encoder->MLM预测原词->NSP是否相邻
BERT的预训练代码:

定义一个简单的BERT模型
这里定义了BERT模型的loss函数

调用BERT模型

BERT预训练的最终损失是遮蔽语言模型损失和下一句预测损失的和
具体流程和一般的训练一样的套路:

初始化


移动数据到GPU

清零梯度,误差反向传播,梯度下降
BERT微调
BERT输出的特征:
BERT 对每一个词元返回抽取了++++上下文信息++++ 的特征向量
不同的任务使用不同的特性

微调BERT只需要一个额外的基于多层感知机的架构
BERT的几个下游任务:
1.单文本分类

特殊分类标记"<cls>"用于序列分类,而特殊分类标记"<sep>"标记单个文本的结束或分隔成对文本
在单文本分类应用中,特殊分类标记"<cls>"的BERT表示对整个输入文本序列的信息进行编码。
作为输入单个文本的表示,它将被送入到由全连接(稠密)层组成的小多层感知机中,以输出所有离散标签值的分布。
2.文本标注

每个词元都要独立预测一个标签,而不是只预测一个句子标签。
输入文本的每个词元的BERT表示被送到相同的额外全连接层中,以输出词元的标签,例如词性标签。
·3.QA问答

将问题和段落分别作为第一个和第二个文本序列,问题的词元不参与预测
目的:预测段落中答案的开始位置和结束位置
开始位置和结束位置使用两个独立的全连接层,参数不共享
总结:

具体的Fine-tuning微调代码:
加载预训练的BERT

加载预训练的BERT参数

加载词表vocab,创建BERT模型架构,加载预训练权重
*不能混用不同预训练模型的词表
对于SNLI数据集的下游任务自然语言推断,我们定义了一个定制的数据集类SNLIBERTDataset。在每个样本中,前提和假设形成一对文本序列,并被打包成一个++++BERT输入序列++++ ++++(相关代码冗长不细看了)++++
用于自然语言推断的微调BERT只需要一个额外的多层感知机,该多层感知机由两个全连接层组成

output为微调时新增的可训练层
传入encoder,结果过隐藏层output