当前位置: 首页 > article >正文

BERT的结构与输出详解

前言

BERT(Bidirectional Encoder Representations from Transformers)是由Google发布的预训练语言模型,旨在通过双向编码器深度理解文本中的上下文信息。BERT的出现显著提升了自然语言处理(NLP)任务的表现,其结构基于Transformer模型的编码器部分。本文将详细介绍BERT的结构和输出,包括它的输入格式、层次结构及输出的含义。

一、BERT的整体结构

BERT的核心基于Transformer的Encoder部分,具有以下特点:

  • 多层Transformer编码器:BERT由多层堆叠的Transformer编码器组成,每一层编码器都有自注意力机制和前馈神经网络。
  • 双向注意力机制:与传统的单向语言模型不同,BERT使用双向的注意力机制,能够同时关注词语的前后文,从而更好地理解句子中的语义关系。
  • 预训练+微调:BERT模型通过大规模语料预训练(主要包括MLM和NSP任务),然后在特定任务上进行微调,能适应多种NLP任务。

1. Transformer编码器的核心组件

BERT使用了标准的Transformer编码器架构。每个编码器层包含以下几个模块:

  • 自注意力机制(Self-Attention):自注意力机制通过计算句子中每个词与其他词之间的相关性,捕捉全局上下文信息。BERT的自注意力机制是双向的,允许模型同时关注左侧和右侧的上下文。
  • 前馈神经网络(Feed-forward Neural Network, FFN):每个编码器层中都包含一个前馈神经网络,它的作用是将经过自注意力机制处理的词向量进行非线性变换,提高模型的表达能力。
  • 残差连接和LayerNorm:每个编码器层内部有残差连接与LayerNorm(层归一化),保证梯度稳定,避免梯度消失或爆炸问题。

BERT通常有两种主要的模型配置:

  • BERT-Base:12层编码器,每层有768个隐藏单元,12个自注意力头,总参数量约为110M。
  • BERT-Large:24层编码器,每层有1024个隐藏单元,16个自注意力头,总参数量约为340M。

2. BERT的输入格式

BERT模型的输入非常讲究格式化。其输入由三部分组成:

  • [CLS]标记:输入序列的第一个位置始终是特殊的[CLS]标记,用于表示整个序列的句子级别的特征。
  • Token序列:BERT将输入的句子进行WordPiece分词,将分词后的结果转化为对应的词嵌入向量。句子A和句子B之间会有特殊的[SEP]标记分隔,以便模型区分两段不同的文本。
  • Segment Embedding:为了区分句子A和句子B,BERT为每个词添加一个段向量(Segment Embedding),用于表示当前词属于句子A还是句子B。
  • 位置嵌入(Position Embedding):Transformer没有卷积网络的结构,所以需要通过显式的位置编码来捕捉词语的顺序信息。BERT为每个位置提供了位置嵌入,帮助模型理解词在句子中的位置。

BERT的输入示例:

假设我们有两个句子:

Sentence A: How are you?
Sentence B: I am fine.

BERT的输入可以表示如下:

[CLS] How are you? [SEP] I am fine. [SEP]

其中:

  • [CLS]:第一个位置始终是[CLS]标记,用于生成句子级别的表示。
  • [SEP]:用于分隔不同的句子。
  • Segment Embedding:标识How are you?属于句子A,I am fine.属于句子B。

二、BERT的输出

BERT的输出主要有两种形式:序列级别的输出词级别的输出。具体来说,BERT的输出是每一层编码器的输出,每一层都会输出一个向量表示。

1. [CLS]标记的输出(句子级别表示)

[CLS]标记的输出代表了整个句子的全局语义信息。在很多任务中,比如句子分类任务(例如情感分类、文本分类等),我们只使用BERT的[CLS]输出。它经过进一步的全连接层和softmax层后,可以用于判别句子的类别。

import torch
from transformers import BertTokenizer, BertModel

# 加载BERT模型和分词器
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
model = BertModel.from_pretrained('bert-base-uncased')

# 输入文本
input_text = "[CLS] How are you? [SEP] I am fine. [SEP]"
inputs = tokenizer(input_text, return_tensors='pt')

# 获取BERT的输出
outputs = model(**inputs)

# 获取 [CLS] 标记的输出 (第一层)
cls_output = outputs.last_hidden_state[:, 0, :]
print(cls_output.shape)  # 输出:torch.Size([1, 768])

在该例子中,cls_output[CLS]标记对应的向量表示,维度为768(对于BERT-base)。

2. 词级别的输出(Token级别表示)

BERT的每个词都会输出一个对应的向量。对于命名实体识别标注任务等需要逐词处理的任务,BERT的每个词级别的输出都非常重要。

我们可以通过获取last_hidden_state来提取每个词的向量表示:

# 获取每个词的向量表示 (词级别的输出)
token_outputs = outputs.last_hidden_state
print(token_outputs.shape)  # 输出:torch.Size([1, 序列长度, 768])

这里,token_outputs包含了输入序列中每个词对应的输出向量,向量维度为768(对于BERT-base)。

3. 中间层的输出

BERT的每一层编码器都会输出一组向量。在一些任务中,使用BERT的中间层输出可以提高性能,比如通过提取多层的输出来进行融合。

通过outputs.hidden_states属性可以访问到每层的输出:

# 启用输出所有层的隐藏状态
outputs = model(**inputs, output_hidden_states=True)

# 获取第5层的输出
fifth_layer_output = outputs.hidden_states[5]
print(fifth_layer_output.shape)  # 输出:torch.Size([1, 序列长度, 768])

三、总结

BERT模型结构基于Transformer的编码器,具有深层的双向自注意力机制。其输入由特殊的格式化组成,包括[CLS][SEP]标记,以及位置和段落嵌入。BERT的输出可以分为两类:句子级别输出(通过[CLS]标记表示)和词级别输出(针对每个词的向量表示)。这些输出可以用于多种下游任务,如分类、命名实体识别、问答等。


http://www.kler.cn/a/369465.html

相关文章:

  • 300元蓝牙耳机性价比高的有哪些?学生平价蓝牙耳机推荐
  • Netty的简介与实战
  • Java设计模式—观察者模式详解
  • QT建立工程时出现了:Reading Project
  • 2024年好用不踩雷的8款图纸加密软件推荐!CAD图纸加密软件!
  • 数据结构:“小猫钓鱼游戏”
  • 中酱集团:黑松露酱油,天然配方定义健康生活
  • Qt 文本文件读写与保存
  • 关于我、重生到500年前凭借C语言改变世界科技vlog.11——深入理解指针(1)
  • 拖拽盖章处理
  • Virtuoso使用layout绘制版图、使用Calibre验证DRC和LVS
  • 丝氨酸/苏氨酸激酶(STKs):前列腺癌治疗的新兴靶点
  • 探索 JavaScript 事件机制(四):React 合成事件系统
  • Java虚拟机的历程(jvm01)
  • Unity编辑器界面及其基础功能介绍
  • 005:航空力学基础、无人机操纵、飞机性能
  • 谷粒商城の秒杀服务
  • 深度学习超参数调优指南
  • Typst 平替Latex的新一代工具
  • vue3+ts实时播放视频,视频分屏
  • 【学术会议论文投稿】JavaScript在数据可视化领域的探索与实践
  • 若依框架前后端结构
  • 前端构建工具vite的优势
  • Java虚拟机JVM的简要工作原理
  • 从零学习大模型(三)-----GPT3(下)
  • 轻松拿捏!windows系统上安装Mamba