ChongruiYang / Econ_Daily_Note

0 stars 0 forks source link

Attention in BERT #7

Open ChongruiYang opened 1 year ago

ChongruiYang commented 1 year ago

这不是BERT和RobertA的注意力机制,只是为了帮助理解:

BigBird是在Transformer模型基础上提出的一种稀疏注意机制。相比于Transformer中的全连接注意力,BigBird的注意力机制是线性的,这使其具有更高的计算效率。

BigBird的稀疏注意力由三个主要部分组成:

  1. 一组全局令牌,对输入序列的所有部分进行注意力。这可以捕捉到输入序列的全局上下文信息。
  2. 所有令牌都会对一组局部相邻的令牌进行注意力。这可以建模输入序列的局部上下文依赖关系。
  3. 所有令牌都会对一组随机选择的令牌进行注意力。这有助于模型学习到更丰富的上下文表达。 相比于ETC模型,BigBird不需要任何关于源数据结构的先验知识。它是一个通用的注意力替代机制,可以直接替换Transformer中的全连接注意力。

具体来说,BigBird的注意力可以表示为: Attention(Q, K, V) = βqZqKV + αqMqKV + γqRqKV

其中:

与Transformer相比,BigBird的主要优点是:

  1. 线性时间复杂度。全连接注意力的时间复杂度是O(n2),BigBird的时间复杂度为O(n)。这大大提高了模型的计算效率。
  2. 不需要任何先验知识。BigBird是一个通用的机制,可以直接替换Transformer的注意力模块,不需要任何关于任务或数据的先验知识。
  3. 性能不下降。BigBird可以达到与Transformer相当的性能,在一些任务上甚至优于Transformer。
  4. 更广的应用前景。由于更高的计算效率,BigBird可应用于更长序列的NLP任务,这些任务Transformer难以处理。

所以,总体来说,BigBird是在Transformer基础上的一种稀疏注意力机制。相比于全连接注意力,它具有线性时间复杂度,不需要任何先验知识,可以在性能不下降的情况下大大提高模型的计算效率。这使其有望在更广范围内应用于NLP。

ChongruiYang commented 1 year ago

在Roberta的预测过程中,被遮蔽的token(mask)及其周围的tokens都被转化成向量表示。然后通过上下文tokens的向量表征来预测mask token。

具体过程如下:

  1. Roberta使用词嵌入层(Embedding Layer)将每个token映射成一个定长向量,比如768维的向量。这些向量带有语义信息,可以表示token的意思。
  2. 接着,Roberta使用编码器(Encoder) - 通常是变压器(Transformer)对这些向量进行编码。编码器捕获 token之间的上下文依赖关系,输出的向量带有语义和位置信息。
  3. 在预测mask token时,Roberta提取mask token的上下文,通常选择该token前后的若干个token。这些tokens的编码向量包含了预测mask token需要的上下文语义信息。
  4. 接下来,这些上下文向量被输入到一个预测头(Prediction Head),通常是一个简单的线性+Softmax层。该层基于上下文向量来计算所有tokens可能出现在mask位置的概率,并输出概率最高的那个token作为预测结果。
  5. 整个过程中,被mask的token的位置使用特殊的mask向量填充,它的值通常是0。这样,模型就无法直接获取mask token的信息,需要依赖上下文进行预测。
  6. 预测完成后,模型会比较预测的token与原始的mask token,并根据结果更新模型参数。这实现了无监督的预训练过程。

所以,关键是编码器(通常是Transformer)从上下文中学习到的语义知识,以及简单的预测头如何有效利用这些知识来预测mask的token。其中,词嵌入为每个token提供了基础的语义表示,编码器进一步建模上下文语义,最后通过预测头转化为具体的token预测。 这个过程充分利用了Transformer在建模上下文依赖关系上的优势,并通过大规模的mask语言模型预训练实现了无监督学习。这也是Roberta比其前身BERT有效的主要原因。

ChongruiYang commented 1 year ago

Transformer的结构是一种多层感知机,多层感知器(Multilayer Perceptron,缩写MLP)是一种前向结构的[人工神经网络],映射一组输入向量到一组输出向量。MLP可以被看作是一个有向图,由多个的节点层所组成,每一层都全连接到下一层。除了输入节点,每个节点都是一个带有非线性激活函数的神经元(或称处理单元)。

ChongruiYang commented 1 year ago

Ref: https://zh.d2l.ai/chapter_attention-mechanisms/attention-cues.html

multi-head attention和self-attention都是注意力机制,但在实现上有以下主要区别:

  1. 计算方式:

    • self-attention:对输入的某个向量,计算它与所有其他向量的attention,从而得到context vector。计算方式为: Attention(Q, K, V) = Softmax(QK^T)V
    • multi-head attention:将输入分割成h份,计算h个self-attention,然后拼接所有结果concatenation,得到最终输出。计算方式为: MultiHead(Q, K, V) = Concat(head1, ..., headh)W^O
      headi = Attention(QWi^Q, KWi^K, VWi^V) multi-head attention在计算self-attention时,会先通过可学习的权重矩阵将输入投影到不同的子空间,然后分别在这些子空间上计算self-attention。
  2. 目的:

    • self-attention:计算输入序列中每个位置与所有其他位置的依赖关系,用于获取上下文信息。
    • multi-head attention:通过多重self-attention, jointly attend to information from different representation subspaces at different positions. 其目的是从不同角度理解输入序列,获取更丰富的上下文语义信息。 所以,总体来说,multi-head attention和self-attention的主要区别是: 1) 计算方式不同:multi-head attention是在多个子空间上分别计算self-attention,然后拼接结果;self-attention仅在原始输入空间计算注意力。 2) 目的不同:self-attention在获取上下文信息;而multi-head attention通过多角度理解输入获取更丰富的上下文语义信息。 综上,multi-head attention可以看作是在self-attention的基础上,利用本地化的线性投影获得输入序列的多种表征的拼接,从而实现多角度理解序列数据和获取更丰富的上下文语义信息。这使得它在许多任务中表现优于原始的self-attention机制。
  3. Query,Key and Values Machinisms

Query: 实现了自主提示;Key:非自主提示

查询(自主提示)和键(非自主提示)之间的交互形成了注意力汇聚; 注意力汇聚有选择地聚合了值(感官输入)以生成最终的输出

N-W Kernel Weighting Skills:

Nadaraya (Nadaraya, 1964)和 Watson (Watson, 1964)提出了一个更好的想法, 根据输入的位置对输出 进行加权:

成为一个更加通用的注意力汇聚(attention pooling)公式:

$f(x) = \sum_{i=1}^n \alpha(x, x_i) y_i$

其中 $x$ 是查询,$(x_i, y_i)$ 是键值对。 注意力汇聚是 $y_i$ 的加权平均;

将查询和键之间的关系建模为注意力权重(attention weight), $\alpha(x, x_i) y_i$,这个权重将被分配给每一个对应值。对于任何查询,模型在所有键值对注意力权重都是一个有效的概率分布:它们是非负的,并且总和为1。如果一个键越是接近给定的查询,那么分配给这个键对应值的注意力权重就会越大,也就“获得了更多的注意力”。

这里测试数据的输入相当于查询,而训练数据的输入相当于键。 因为两个输入都是经过排序的,因此由观察可知“查询-键”对越接近, 注意力汇聚的注意力权重就越高。

注意力参数也可以带未知量以在训练中学习。

在带参数的注意力汇聚模型中, 任何一个训练样本的输入都会和除自己以外的所有训练样本的“键-值”对进行计算, 从而得到其对应的预测输出。带参数的权重拟合会相比非参数的权重拟合更加不平滑(这就存在潜在的过拟合现象)。

键值是一个整体,你可以认为一个黑盒子,是我们训练好的网络,query你是要向这个网络来查询一个输入对应的输出,根据任务,我们要通过x_test来查询y_test值。

  1. score_function

    高斯核指数部分可以视为注意力评分函数(attention scoring function), 简称评分函数(scoring function), 然后把这个函数的输出结果输入到softmax函数中进行运算。 通过上述步骤,将得到与键对应的值的概率分布(即注意力权重)。 最后,注意力汇聚的输出就是基于这些注意力权重的值的加权和。

ChongruiYang commented 1 year ago

BERT’s tokenizer: https://cloud.tencent.com/developer/beta/article/1865689

为了保证词表有足够的压缩空间,同时要兼顾词的信息量,需要将词拆分成子词

1)BPE:for chars and high frequency subword: count for a higher frequency subword vocabs.

2)Byte_level:如果遇到了unicode,基本字符集可能会很大。一种处理方法是我们以一个字节为一种“字符”,不管实际字符集用了几个字节来表示一个字符。这样的话,基础字符集的大小就锁定在了256。 /例如,像GPT-2的词汇表大小为50257 = 256 + + 50000 mergers,是句子结尾的特殊标记。

3)WordPiece

从名字好理解,它是一种子词粒度的tokenize算法subword tokenization algorithm,很多著名的Transformers模型,比如BERT/DistilBERT/Electra都使用了它。

它的原理非常接近BPE,不同之处在于,它在做合并的时候,并不是每次找最高频的组合,而是找能够最大化训练集数据似然的merge,即它每次合并的两个字符串A和B,应该具有最大的 P(AB)/P(A)P(B)值。合并AB之后,所有原来切成A+B两个tokens的就只保留AB一个token,整个训练集上最大似然变化量与 P(AB)/P(A)P(B)成正比。

简而言之,合并"最紧密的"可能出现的词组对,这个紧密的定义需要确定

4)Unigram Cut

WordPiece不同,Unigram的算法思想是从一个巨大的词汇表出发,再逐渐删除trim down其中的词汇,直到size满足预定义。

初始的词汇表可以采用所有预分词器分出来的词,再加上所有高频的子串。

每次从词汇表中删除词汇的原则是使预定义的损失最小。训练时,计算loss的公式为熵的计算公式

5)SentencePiece

顾名思义,它是把一个句子看作一个整体,再拆成片段,而没有保留天然的词语的概念。一般地,它把空格space也当作一种特殊字符来处理,再用BPE或者Unigram算法来构造词汇表。

比如,XLNetTokenizer就采用了_来代替空格,解码的时候会再用空格替换回来。

无论是在非基于词的BERT还是非基于词的RobertA里面,都采用的是WordPiece的分割方法来构造vocab size

ChongruiYang commented 1 year ago

1)归一化

归一化是指对数据维度进行归一化,使它们具有大致相同的规模。有两种常见的方法可以实现这种规范化。一种是将每个维度除以其标准差,一旦它以零为中心:( X /= np.std(X, axis = 0))。这种预处理的另一种形式是对每个维度进行归一化,使得维度上的最小值和最大值分别为 -1 和 1。如果您有理由相信不同的输入特征具有不同的尺度(或单位),那么应用这种预处理才有意义,但它们对学习算法的重要性应该大致相同。

PCA 和 Whitening是另一种形式的预处理。在这个过程中,数据首先如上所述被居中。然后,我们可以计算协方差矩阵,告诉我们数据中的相关结构:

PCA:特征向量列按其特征值排序。我们可以通过仅使用前几个特征向量并丢弃数据没有方差的维度来使用它来降低数据的维度。这有时也称为主成分分析 (PCA)降维。根据方差的解释比来选取

Whitening:The whitening operation takes the data in the eigenbasis and divides every dimension by the eigenvalue to normalize the scale. The geometric interpretation of this transformation is that if the input data is a multivariable gaussian, then the whitened data will be a gaussian with zero mean and identity covariance matrix. 分解的特征分量除于特征值,对每个行进行比例归一化,如果原始数据是多变量高斯分布,那么生成的数据将是零均值多变量的高斯分布

ref: https://cs231n.github.io/neural-networks-2/#init

可以看看whitening后数据分布的结果

2) 权重初始化 In the process of training a neural network, we initialize the weights which are then updated as the training proceeds. For a certain random initialization, the outputs from one or more of the intermediate layers can be abnormally large. This leads to instability in the training process, which means the network will not learn anything useful during training. 会出现梯度异常的情况

推荐的预处理是将数据居中以使其均值为零,并沿每个特征将其比例归一化为 [-1, 1],通过从标准差为的高斯分布中绘制权重来初始化权重,其中n是神经元的输入数。例如在 numpy 中:w = np.random.randn(n) * sqrt(2.0/n).

3)爆炸式激活和梯度爆炸

跑多个epoch是为了避免当前的网络权重适应了数据的分布,对训练数据的批次进行规模化调整;爆炸式激活(exploding activation)会造成这个地方的梯度异常大,在回传的同时导致前面的梯度消失。同时也会减慢训练速度。

爆炸式激活带来的梯度消失问题:

4)避免过拟合:

5)Normalization (Batch VS Layer)

就是加速,稳定训练过程,不因为某个batch产生针对

Batch:不适合用于序列模型,第一对于batch_size大小有要求,二是对于sequence_length长短不一的情况,对于一个batch内的特征分量可能有影响(不要在[PAD]上乱加权值,不好解释)。对batch里每个样本的同一分量做,纵向norm

Layer:适用于序列模型,横向normlization