Embedding(嵌入)技术的核心目标是将高维、稀疏的数据(如文本、图像、图结构)映射为低维、稠密的向量空间,从而捕捉数据间的语义关系。根据应用场景的不同,主要分为自然语言处理 (NLP)、图神经网络 (GNN) 和 多模态学习 三大领域。
自然语言处理过程中,文本的向量化,是其中重要的一环。NLP 领域的 Embedding 发展经历了从静态到动态、从单词到句子的演变。
静态词向量:Word2Vec / GloVe
原理: 基于统计学或神经网络模型,通过预测上下文或共现矩阵来学习词向量。
适用: 文本分类、信息检索。
特点: 训练速度快,但无法区分同一词在不同语境下的含义(如 “Apple” 是水果还是公司)。动态上下文:ELMo / BERT
原理: 利用 RNN 或 Transformer 捕捉双向上下文,生成动态的词向量。
适用: 问答系统、复杂语义理解。
特点: 同一个词在不同句子中会有不同的向量表示,精度极高。句子/段落:Sentence-BERT (SBERT)
原理: 基于 BERT 的 Siamese/Triplet 结构,直接对齐句子对的向量空间。
适用: 语义相似度搜索、聚类。
特点: 相比原生 BERT,推理速度提升数百倍。
| 技术 | 核心机制 | 优势 | 劣势 |
|---|---|---|---|
| Word2Vec | 局部窗口预测 | 训练极快,适合大规模语料 | 缺乏上下文感知,无法处理歧义 |
| GloVe | 全局矩阵分解 | 结合了全局统计信息和局部窗口 | 计算复杂度较高 |
| BERT | 双向 Transformer | 深度理解语义,效果 SOTA | 训练慢,推理时需同时输入两个句子,效率低 |
| SBERT | Siamese 网络 | 推理极速 (5秒 vs BERT 65小时) | 需要额外微调,参数量大 |
示例代码:1
2
3
4
5
6
7
8
9import gensim
# 1. 获取静态词向量 (Word2Vec)
model_word2vec = gensim.models.Word2Vec.load("word2vec.model")
vec = model_word2vec.wv['apple']
# 2. 获取句子嵌入 (Sentence-BERT)
from sentence_transformers import SentenceTransformer
model_sbert = SentenceTransformer('paraphrase-MiniLM-L6-v2')
sentences = ["Hello world", "Hi there"]
embeddings = model_sbert.encode(sentences) # 输出形状: [2, 768]
BERT
BERT(Bidirectional Encoder Representations from Transformers)是 Google 在 2018 年提出的革命性预训练模型。即双向Transformer的Encoder,因为decoder是不能获要预测的信息的。模型的主要创新点都在pre-train方法上,它只使用了transformer的encoder部分,它的整体框架是由多层transformer的encoder堆叠而成的。每一层的encoder则是由一层muti-head-attention和一层feed-forword组成,大的模型有24层,每层16个attention,小的模型12层,每层12个attention。每个attention的主要作用是通过目标词与句子中的所有词汇的相关度,对目标词重新编码。所以每个attention的计算包括三个步骤:计算词之间的相关度,对相关度归一化,通过相关度和所有词的编码进行加权求和获取目标词的编码。
在通过attention计算词之间的相关度时,首先通过三个权重矩阵对输入的序列向量(512*768)做线性变换,分别生成query、key和value三个新的序列向量,用每个词的query向量分别和序列中的所有词的key向量做乘积,得到词与词之间的相关度,然后这个相关度再通过softmax进行归一化,归一化后的权重与value加权求和,得到每个词新的编码。
BERT模型输入
在BERT中,输入的向量是由三种不同的embedding求和而成,分别是:
wordpiece embedding:单词本身的向量表示。WordPiece是指将单词划分成一组有限的公共子词单元,能在单词的有效性和字符的灵活性之间取得一个折中的平衡。
- position embedding:将单词的位置信息编码成特征向量。因为我们的网络结构没有RNN 或者LSTM,因此我们无法得到序列的位置信息,所以需要构建一个position embedding。构建position embedding有两种方法:BERT是初始化一个position embedding,然后通过训练将其学出来;而Transformer是通过制定规则来构建一个position embedding
- segment embedding:用于区分两个句子的向量表示。这个在问答等非对称句子中是用区别的。
BERT模型的输入就是wordpiece token embedding + segment embedding + position embedding,如图所示:

网络结构
BERT的主要结构是transformer(如图1所示),一个BERT预训练模型的基础结构是标准transformer结构的 encoder 部分,一个标准transformer结构如图2所示,其中左边的部分就是BERT中使用的encoder部分。
一个transformer的encoder单元由一个multi-head-Attention + Layer Normalization + feedforword + Layer Normalization 叠加产生,BERT的每一层由一个这样的 encoder 单元构成。在比较大的BERT模型中,有24层encoder,每层中有16个Attention,词向量的维度是1024。在比较小的BERT模型中,有12层encoder,每层有12个Attention,词向量维度是768。在所有情况下,将feed-forward/filter 的大小设置为 4H(H为词向量的维度),即H = 768时为3072,H = 1024时为4096。
这种transformer的结构可以使用上下文来预测mask的token,从而捕捉双向关系。
self-attention Layer
self-attention出现的原因
a、为了解决RNN、LSTM等常用于处理序列化数据的网络结构无法在GPU中并行加速计算的问题
b、由于每个目标词是直接与句子中所有词分别计算相关度(attention)的,所以解决了传统的RNN模型中长距离依赖的问题。通过attention,可以将两个距离较远的词之间的距离拉近为1直接计算词的相关度,而传统的RNN模型中,随着距离的增加,词之间的相关度会被削弱。
模型的输入
就是前面BERT模型的输入,即 X=(batch_size, max_len, embedding),假设batch_size=1,输入的句子长度为512,每个词的向量表示的长度为768,那么整个模型的输入就是一个512*768的tensor。
单个self-attention 的计算过程
每一次的self-attention的计算涉及到三个中间权重矩阵Wq,Wk,Wv,他们分别对输入的X进行线性变换,生成query、key和value这三个新的tensor,整个的计算步骤如 下:
step 1:输入X分别与Wq,Wk,Wv矩阵相乘,得到Q,K,V。
step 2:Q,K_T矩阵相乘,得到X中各个词之间的相关度,并scale(为了防止结果过大,除以他们维度的均方根)。
step 3:将第二步的相关度通过Softmax函数归一化,得到归一化后各个词与其他词的相关度。
step 4:将第三步的相关度矩阵与 V 相乘,即加权求和,得到每个词新的向量编码。
计算图如下所示:
在BERT小模型中,每个head的神经元个数是64,12个head总的神经元的个数即为768,也就是模型介绍时说的H=768。在上图中单个的的Wq,Wk,Wv都是76864的矩阵,那么Q,K,V则都是51264的矩阵,Q,K_T相乘后的相关度矩阵则为512512,归一化后跟V相乘后的z矩阵的大小则为51264,这是一个attention计算出的结果。12个attention则是将12个51264大小的矩阵横向concat,得到一个512768大小的多头输出,这个输出再接一层768的全连接层,最后就是整个muti-head-attention的输出了。
multi-head attention的计算
Multi-Head Self-Attention将多个不同单头的Self-Attention输出Concat成一条,然后再经过一个全连接层降维输出。例如,一个self-attention计算的输出为output_0 = (batch_size, max_len, w_length),那么n个attention进行concat之后,输出就为output_sum = (batch_size, max_len,n * w_length),这个concat的结果再连一层全连接层即为整个multi-head attention的输出。如下图所示,右边的部分即为一个multi-head attention的计算过程,其中的h指的是attention的个数,即上面例子中的n。
Layer Normalization
Self-Attention的输出会经过Layer Normalization,为什么选择Layer Normalization而不是Batch Normalization?
此时,我们应该先对我们的数据形状有个直观的认识,当一个batch的数据输入模型的时候,形状是长方体如图所示,大小为(batch_size, max_len, embedding),其中batch_size为batch的批数,max_len为每一批数据的序列最大长度,embedding则为每一个单词或者字的embedding维度大小。而Batch Normalization是在batch间选择同一个位置的值做归一化,相当于是对batch里相同位置的字或者单词embedding做归一化,Layer Normalization是在一个Batch里面的每一行做normalization,相当于是对每句话的embedding做归一化。显然,LN更加符合我们处理文本的直觉。如下图所示。
模型优化之Batch Normalization
模型优化之Layer Normalization
BERT 每一层的学习
bert从浅层到高层可以分别学习到surface,短语级别的,句法级别的,和语义级别的信息;长程依赖需要更多层进行建模;
What does BERT learn about the structure of language?
译本:BERT的每一层学习到了哪些语义信息
理解BERT每一层都学到了什么
模型预训练
训练任务
masked language model
随机掩盖掉一些单词,然后通过上下文预测该单词。BERT中有15%的wordpiece token会被随机掩盖,这15%的token中80%用[MASK]这个token来代替,10%用随机的一个词来替换,10%保持这个词不变。这种设计使得模型具有捕捉上下文关系的能力,同时能够有利于token-level tasks例如序列标注。Q:为什么选中的15%的wordpiece token不能全部用 [MASK]代替,而要用 10% 的 random token 和 10% 的原 token
[MASK] 是以一种显式的方式告诉模型『这个词我不告诉你,你自己从上下文里猜』,从而防止信息泄露。如果 [MASK] 以外的部分全部都用原 token,模型会学到『如果当前词是 [MASK],就根据其他词的信息推断这个词;如果当前词是一个正常的单词,就直接抄输入』。这样一来,在 finetune 阶段,所有词都是正常单词,模型就照抄所有词,不提取单词间的依赖关系了。
以一定的概率填入 random token,就是让模型时刻堤防着,在任意 token 的位置都需要把当前 token 的信息和上下文推断出的信息相结合。这样一来,在 finetune 阶段的正常句子上,模型也会同时提取这两方面的信息,因为它不知道它所看到的『正常单词』到底有没有被动过手脚的。Q:最后怎么利用[MASK] token做的预测?
最终的损失函数只计算被mask掉的token的,每个句子里 [MASK] 的个数是不定的。实际代码实现是每个句子有一个 maximum number of predictions,取所有 [MASK] 的位置以及一些 PADDING 位置的向量拿出来做预测(总共凑成 maximum number of predictions 这么多个预测,是定长的),然后再用掩码把 PADDING 盖掉,只计算[MASK]部分的损失。next sentence prediction
语料中50%的句子,选择其相应的下一句一起形成上下句,作为正样本;其余50%的句子随机选择一句非下一句一起形成上下句,作为负样本。这种设定,有利于sentence-level tasks,例如问答。注意:作者特意说了语料的选取很关键,要选用document-level的而不是sentence-level的,这样可以具备抽象连续长序列特征的能力。
模型训练设置
pre-train阶段
(1)256个句子作为一个batch,每个句子最多512个token。
(2)迭代100万步。
(3)总共训练样本超过33亿。
(4)迭代40个epochs。
(5)用adam学习率, 1 = 0.9, 2 = 0.999。
(6)学习率头一万步保持固定值,之后线性衰减。
(7)L2衰减,衰减参数为0.01。
(8)drop out设置为0.1。
(9)激活函数用GELU代替RELU。
(10)Bert base版本用了16个TPU,Bert large版本用了64个TPU,训练时间4天完成。
论文定义了两个版本,一个是base版本,一个是large版本。
- Large版本( L=24, H=1024, A=16, Total Parameters=340M)。
- base版本 ( L=12, H=768 , A=12, Total Parameters=110M)。
L代表网络层数,H代表隐藏层数,A代表self attention head的数量。
因为序列长度太大(512)会影响训练速度,所以90%的steps都用seq_len=128训练,余下的10%步数训练512长度的输入。
fine-tune 阶段
微调阶段根据不同任务使用不同网络模型。在微调阶段,大部分模型的超参数跟预训练时差不多,除了batchsize,学习率,epochs。
微调参数建议:
- Batch size: 16, 32
- Learning rate (Adam): 5e-5, 3e-5, 2e-5
- Number of epochs: 3, 4
模型特点
- 使用transformer作为算法的主要框架,transformer能更彻底的捕捉语句中的双向关系;
- 使用了mask language model 和next sentence prediction的多任务训练目标,是一个自监督的过程,不需要数据的标注;
- 使用tpu这种强大的机器训练了大规模的预料,是NLP的很多任务达到了全新的高度。
BERT本质上是在海量语料的基础上,通过自监督学习的方法为单词学习一个好的特征表示。该模型的优点是可以根据具体的人物进行微调,或者直接使用预训练的模型作为特征提取器。
参考资料
[1] Bengio Y, Ducharme R, Vincent P, et al. A neural probabilistic language model[J]. Journal of machine learning research, 2003, 3(Feb): 1137-1155.
[2] Devlin J, Chang M-W, Lee K, et al. Bert: Pre-training of deep bidirectional transformers for language understanding[J]. arXiv preprint arXiv:1810.04805, 2018.
[3] Vaswani A, Shazeer N, Parmar N, et al. Attention is all you need[C]. Advances in neural information processing systems, 2017: 5998-6008.
BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding
NLP必读:十分钟读懂谷歌BERT模型
BERT的原理与应用
论文解读:BERT模型及fine-tuning