词嵌入 Embedding: 从 Word2vec 到 Bert

Bert 的第一步是文字向量化。文字向量化从 Word2Vec 开始,逐渐走向成熟。

 

Word2vec

参考资料

  • 官方网址:https://code.google.com/archive/p/word2vec/
  • 论文
『Distributed Representations of Sentences and Documents』
      贡献:在前人基础上提出更精简的语言模型(language model)框架并用于生成词向量,这个框架就是 Word2vec
『Efficient estimation of word representations in vector space』
      贡献:专门讲训练 Word2vec 中的两个trick:hierarchical softmax 和 negative sampling
优点:Word2vec 开山之作,两篇论文均值得一读
 Xin Rong 的论文:『word2vec Parameter Learning Explained』:
!重点推荐!

 

Hierarchical softmax

参数优化目标函数为:

 [Y. Goldberg, etc.] 或  [X. Rong]

其中  表示输入词序列的第1个词, 表示词序列下标, 表示词  的语境(上下文 context)。

 

Hierachical softmax 借鉴了 Haffman encoding 的思想,压缩了待训练参数数量, 由路径变量乘积确定,每个路径变量使用 Sigmoid function 概率。Sigmoid function 具有如下很好的性质:

在 Hierachical softmax 中,一个输出词  的概率计算公式为:

image.png   (5)

其中  定义为:

词嵌入 Embedding: 从 Word2vec 到 Bert_第1张图片

公式(5)之所以能够使用 [[x]] 函数定义,正是因为 Sigmoid function 具有性质(3)。

 

Negative sampling and subsampling

为了防止学习到极端点,而不是是适当的优化点,保持样本的平衡非常重要。 的统计数据从语料  中产生,都是正样本,极端解也可以得到最大化的 loss 函数。Negative sampling 为了解决上述问题,人为按照词频分布产生 ,作为负样本。

 

Subsampling 人为剔除极低频词和降低极高频次的抽样频率,据此可以产生更加有意义的上下文。

 

ELMo

Embedding from Language Model, ELMo 从大量语料中,无监督训练,从整句中得到词的语义向量表示,这个向量称为语言模型嵌入向量,即  LM 向量。在特定的 NLP 任务中,比如 SQuAD 问答任务,可以冻结 LM 训练网络参数,把 LM 向量与任务特定词向量串联,可以得到语境敏感的词向量嵌入表示,实验表面 ELMo 能够改进现有的 NLP 任务性能。

 

ELMo 架构上包括了以下技术:1. Highway layer; 2. Projection layer;

Highway layer

Highway layer 解决了深度神经网络训练面临的问题,主要有:1. 梯度消失;2. 非线性堆叠导致激活和梯度传播效果差;

 

Highway layer 由变换门和携带门组成,公式表示如下:

通常可以取,直觉理解是最初输出 y 由两部分归一混合而成,一部分经过了递归或深度神经网络变换即,另外一部分是原始输入 .

 

Project layer

映射层解决维度变换问题,从高维降为低维。

 

BERT

 

BERT 结构上包含了以下几个结构:1)字符编码;2)位置编码;3)变换器编码;4)池化。

 

字符编码使用随机初始化向量,把 wordpieces 编码转化为初始嵌入向量。

 

位置编码在 embedding_postprocessor() 中实现,其中包括了 token_type_embedding 和 position_embedding,都是直接加在字符初始编码上。

 

Bert 基于变换器 transformer 架构,Bert 使用的是多层双向变换器。

Transformer

BERT 使用的变换器架构在 Ashish Vaswani, etc. Attention is all your need 一文中进行了详细阐述。传统变换器的编码和解码部分使用了复杂的递归和卷积,Vaswani 等发布的变换器只使用了注意力模型,完全摈弃了递归和卷积模型,因而更简单,训练效率更高。

 

变形器包括编码器( encoder )和解码器( decorder )两部分,各自都由相同的6层组成。编码器每层包括两个子层,第一个子层是注意力层,第二个子层是全连接层,每个子层最后都加入了残差连接和归一化层;解码器每层包括三个子层,前两个是注意力层,第三个是全连接层,第一个注意力层使用掩码和位置偏移,确保只使用已有前序词预测后续词。

 

BERT 使用了 Attention is all your need 的编码层。注意力层对比递归和卷积层,计算复杂度大大降低,下表给出了各种不同层的计算复杂性对比,值得进一步分析。

 

Table 1

词嵌入 Embedding: 从 Word2vec 到 Bert_第2张图片

Table 1 中符号说明:n 表示序列长度,d 表示向量维度,即使用多长的向量建模 sentense,k 表示卷积层的核尺寸,r 表示受限自注意力层,限制邻居范围。

 

Attention

抽象的注意力层包括三种 tensor 输入,分布为查询 Q,键 K,值 V,Q 与 K 的点积作为 V 的权重,公式如下:

直觉理解,Q 与 K 的相似程度,缩放、归一化后,作为输出值 V 的权重系数。

 

Multi-head Attention

多头注意力模型,把序列分为 number of heads 多个分段,并行计算每个分段的注意力层,然后在串联在一起。实际编程中,使用矩阵 reshape 和 transpose 就可以了,真正的并行计算可以基于更底层的矩阵并行计算优化能力,而不用在编码过程中显式地并行化。

 

Pooler

BERT 的池化操作默认选择序列的第一个字符输出作为最终输出。

 

池化层来概念来自于卷积神经网络。卷积神经网络包含两个核心组建,一个是卷积,另一个就是池化。池化层以激进的方式减少数据量,一般没有需要训练的参数。典型的池化层就是 max pooling。 池化层之所以在减少数据量方面是激进的,原因在于池化区域不重叠,如果池化区域大小为 M,那么数据量至少下降 M 倍。

 

下图形象的描述了最大池化层操作,即选择一个区域中最大的值输出。

词嵌入 Embedding: 从 Word2vec 到 Bert_第3张图片

参考:https://medium.com/technologymadeeasy/the-best-explanation-of-convolutional-neural-networks-on-the-internet-fbb8b1ad5df8

 

Fine tune

BERT 的巨大优势在于能够作为其他 NLP 任务起点,初始化词嵌入。比如,对于分类任务,把句子的第一个字符 [CLS] 的 BERT 输出 h 代表整个句子语义嵌入,加上一个 softmax 层,可以用来计算分类分值。

 

使用 BERT 进行 fine tune 需要考虑一下几个方面:

  1. 规整输入数据,预处理任务输入,使之符合 BERT 输入,两个文本序列,每个最大长度为 512;
  2. BERT 输出选择,从 BERT 的结构入手,选择合适的输出;
    1. BERT 结构包括:embedding lookup; position and token type embedding; transformer encoder; pooler;
    2. fine tune 任务可以采用 BERT 结构中任意一层的输出作为任务输出;
    3. 实验表明最后一层,一般而言,对整个句子的表达能力是最好的;
  1. 选择合适的优化器和学习速率;
    1. 可以有效解决以下问题:
      1. 过拟合问题;
      2. 迁移遗忘问题 catastrophic forgetting
    1. 实验表面学习速率可以影响 forgetting 程度,学习太快,容易遗忘 pretrain 学到的知识;

 

Fine tune 之前针对领域词汇再进行 pretrain 有助于提升任务性能;

 

BERT 代码中自带了几个例子,很好的演示了如何使用 Fine tune. 以 run_classifier.py 为例,create_model 函数就是基于 BERT checkpoint 得到特定分类问题的训练模型。该函数做了以下操作:

  1. BERT 输出选择:选择池化层输出作为任务输入起点;
  2. LOSS 定义:定义了任务特定的损失函数计算方法;

 

输入数据包括四个 featues,分别是:input_ids, input_mask, segment_ids, label_ids. 其中 segment_ids 对应于 bert model 中的 token_type_ids, 默认配置 token_type_size=2,即输入两个序列,每个字符分别属于其中一个序列,标记为 type0 或 type1. 

 

位置编码实现暂时没有理解!代码中只有一个 tf.get_variable() 构造了一个 tensor,值都初始化为正态分布随机值,没有乘上 [0,1,2,...] 之类的值,也没有使用 feature 输入位置编号。Transformer 论文 中介绍 position embedding 使用了 sin/cos 函数,但是 Bert 中直接使用可训练参数,让模型自己学习。(参考:https://zhuanlan.zhihu.com/p/69106080)

 

 

 

你可能感兴趣的:(NLP,NLP,Bert,解读)