注意力机制与Transformer

注意力机制

序列算法

序列算法核心在于建立样本与样本之间的关联,并借助这一种关联提炼出对序列数据的理解

常见的算法:

  • ARIMA家族算法群:使用加权的方式
    X t = c + ϕ 1 X t − 1 + ϕ 2 X t − 2 + ⋯ + ϕ p X t − p + ϵ t X_t = c + \phi_1 X_{t-1} + \phi_2 X_{t-2} + \dots + \phi_p X_{t-p} + \epsilon_t Xt=c+ϕ1Xt1+ϕ2Xt2++ϕpXtp+ϵt
  • 循环网络家族
    • RNN:本质上还是加权,但是是动态衰减的加权
      h t = σ ( W h h h t − 1 + W x h x t + b h ) h_t = \sigma(W_{hh} h_{t-1} + W_{xh} x_t + b_h) ht=σ(Whhht1+Wxhxt+bh)
    • LSTM:将短期记忆和长期记忆进行数据分流
      输入门 i t = σ ( W i i x t + W h i h t − 1 + b i ) 遗忘门 f t = σ ( W i f x t + W h f h t − 1 + b f ) 输出门 o t = σ ( W i o x t + W h o h t − 1 + b o ) 候选状态 C ~ t = tanh ⁡ ( W i c x t + W h c h t − 1 + b c ) 时间步 t 的状态 C t = f t ⋅ C t − 1 + i t ⋅ C ~ t 时间步 t 的隐藏状态 h t = o t ⋅ tanh ⁡ ( C t ) 时间步 t 的输出 y t = W h y h t + b y \begin{align*} 输入门 i_t &= \sigma(W_{ii} x_t + W_{hi} h_{t-1} + b_i) \\ 遗忘门 f_t &= \sigma(W_{if} x_t + W_{hf} h_{t-1} + b_f) \\ 输出门 o_t &= \sigma(W_{io} x_t + W_{ho} h_{t-1} + b_o) \\ 候选状态 \tilde{C}_t &= \tanh(W_{ic} x_t + W_{hc} h_{t-1} + b_c) \\ 时间步 t 的状态 C_t &= f_t \cdot C_{t-1} + i_t \cdot \tilde{C}_t \\ 时间步 t 的隐藏状态 h_t &= o_t \cdot \tanh(C_t) \\ 时间步 t 的输出 y_t &= W_{hy} h_t + b_y \end{align*} 输入门it遗忘门ft输出门ot候选状态C~t时间步t的状态Ct时间步t的隐藏状态ht时间步t的输出yt=σ(Wiixt+Whiht1+bi)=σ(Wifxt+Whfht1+bf)=σ(Wioxt+Whoht1+bo)=tanh(Wicxt+Whcht1+bc)=ftCt1+itC~t=ottanh(Ct)=Whyht+by
  • 卷积网络家族:卷积的核心仍为对应元素相乘相加

Transformer是序列算法的最优解
Attention is All You Need

注意力机制的本质

计算每个样本之于一个序列的重要程度,为这些样本赋予能代表其重要性的权重。

  • 经典注意力机制Attention:序列A中的样本之于序列B的重要程度,常用于Seq2Seq任务中(如机器翻译)。
  • 自注意力机制Self-Attention:序列内部样本之于序列自身。

为什么要Attention

不同样本对于句子的理解的重要程度是不一样的。Attention可以引导模型去关注重要的部分,提升模型性能。

如何定义Attention

样本与样本之间的相关性。如果一个样本与很多样本都高度相关,则一般来讲它的重要性较高。

怎么计算Attention

实际上就是向量之间的相关性:向量点积。而向量点积实际上也是加权求和。在语言中,A相较于B的重要程度与B相较于A的重要程度是不同的。比如"Tom"对"He"很重要,因为"Tom"解释了"He"。但是"He"对于"Tom"来讲并不是那么重要。单纯用向量点积无法体现这种关系。如果存在A、B两个样本,则需要计算AA、AB、BA、BB —>矩阵乘法X * X.T。核心词被认为在进行发问(Question),非核心词在进行应答(Key)。而为了从多方面进行语义理解,则添加语义解读矩阵W,用于生成Q、K,即为WQ、WK。

注意力分数

Attention ( Q , K , V ) = softmax ( Q K T d k ) V \text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)V Attention(Q,K,V)=softmax(dk QKT)V

  • d k \sqrt{d_k} dk 是特征的维度(input_dimensions)用于scaling标准化。因为计算加权求和时,特征维度越多,加的就越多,从而点积矩阵的结果会更大,这样不公平。但是一般 d k d_k dk会比较大,直接除以 d k d_k dk会导致注意力分数都比较小,从而使用 d k \sqrt{d_k} dk
  • softmax完成转化为[0,1],并且满足概率分布特征(满足全概率公式,这是由softmax的数学表达决定的)。
  • V代表着对原始语句的语义解读,V由X和WV乘积生成。
  • Transformer的注意力机制相较于LSTM多出了n倍的记忆(n为得到的注意力矩阵行数)。即存在多种解读,从而大幅优化模型性能。
多头注意力机制 Multi-Head Attention

:一组 W Q W^Q WQ W K W^K WK W V W^V WV。对于多头的输出,由于不能再增加数据维度(前面还有batch_size),采用简单的拼接方式。

Transformer

架构

Input/Output Embedding、编码解码器、残差机制等。

可有多个编码层,只有最后一层编码层的结果传入解码层,而解码器每一层都会收到编码层传来的结果

使用Mask机制防止数据泄露/偷看。解码器注意力机制生成Q,编码器生成K、V。即让标签进行提问,让编码后的信息进行回答。

Embedding层

文字 --> 顺序编码 --> 高维向量。Embedding层有权重,即可训练

Attention机制会导致位置信息的缺失

  • RNN、LSTM等是按照时间步进行处理的,而Transformer是按照矩阵并行进行处理的,天然缺乏位置信息。
  • 注意,在注意力机制的数学表达中,核心为点积运算,而点积运算并没有位置相关的概念,它只知道一个元素与另一个元素进行加权求和,而没有位置信息

位置编码:创建与词义Embedding维度相同的向量,记录位置,与其相加,从而得到与位置相关的编码。

而如何创建这个位置向量呢?Transformer使用了正余弦位置编码
PE ( p o s , 2 i ) = sin ⁡ ( p o s 1000 0 2 i / d model ) \text{PE}(pos, 2i) = \sin\left(\frac{pos}{10000^{2i/d_{\text{model}}}}\right) PE(pos,2i)=sin(100002i/dmodelpos)
PE ( p o s , 2 i + 1 ) = cos ⁡ ( p o s 1000 0 2 i / d model ) \text{PE}(pos, 2i+1) = \cos\left(\frac{pos}{10000^{2i/d_{\text{model}}}}\right) PE(pos,2i+1)=cos(100002i/dmodelpos)

  • pos 是词在序列中的位置。
  • i 是维度索引。
  • d m o d e l d_{model} dmodel是模型的维度。
  1. 需要限制位置编码大小:如果使用简单的位置编码,比如第i个样本的位置编码为[i,i,i,i…],这样会造成在长文时,位置编码的数值远远大于语义编码的值,导致信息的覆盖和丢失
  2. 得到多种信息:如果简单的使用sin、cos,这样确实限制了位置编码的大小,但是得到的信息不够多样,从而想到通过频率来生成 d m o d e l d_{model} dmodel个sin、cos函数。实际上变成了sin(pos * frequency)。
  3. 局部与全局特征捕捉: 1 1000 0 2 i / d model \frac{1}{10000^{2i/d_{\text{model}}}} 100002i/dmodel1实际上就是frequency。而这样的频率公式会导致对于较小索引的特征的frequency会较大,从而sin、cos函数的变化会比较大。特征较大索引与之相反。从信息论上讲,这样可以理解为全局和局部的信息都被捕获了。

额外的点:

  • 正弦函数的周期性带来泛化性。
  • 不参加额外的训练参数。
  • 带来相对位置信息(正弦函数的周期性使得在位置编码的变化也具有周期性,从而蕴含了相对位置信息)。

Encoder层

在某些任务中可以仅使用Encoder层而不使用Decoder层,例如:

  • 情感分析
  • 文本分类
  • 命名实体识别
  • 关系抽取
  • 文本生成的预训练
1.残差机制

残差机制不会改变输入维度,但是多头注意力机制会使得特征维度*N。解决方案:

  1. 将输入复制。
  2. 分割传入多头注意力机制,确保最终得到的拼接后的结果与原始输入一致。

第一种适用于特征较少的情形,现有transformer大部分使用第二种方案。

2.归一化
  • 减少内部协方差偏移。
  • 加快训练速度。
  • 减少对初始值的依赖。
  • 允许更深层网络的训练。

Transformer使用了Layer Normalization而没有使用Batch Normalization:

  • Batch Normalization : 在batch内对每个样本的每一个特征进行归一化。
  • Layer Normalization : 在layer内对每个样本的所有特征进行归一化。

NLP任务存在特殊性,从而使用了LN而非像CV一样使用了BN:

  1. 由于存在padding,可能每个batch的voc_size不够大被填充为0,这样对于其他batch会存在影响。
  2. batch_size存在限制,一般不会太大(算力不够,或者说更多用到了voc_size上),较小的batch_size会存在波动。
  3. 某些NLP任务中需要按照序列进行处理,而非不能批处理。
3.前馈神经网络

对数据进行非线性变换、产生输出(也就是说可以只用Encoder)。

自注意力机制的核心部分(QKV)是一个线性结构,Softmax提供了部分非线性。

Transformer中为:全连接–>RELU–>全连接。

Decoder

一般在涉及到Sequence To Sequence的任务时,会倾向于使用完整的transformer架构(包含encoder和decoder)。在此类任务中输出强依赖于输入信息,语义需要保持高度相同:

  • 机器翻译
  • 文本摘要
  • 图像字母生成
  • 文本转语音
  • 问答系统

而在生成式任务时,会倾向于只使用decoder。在此类任务中,期望LLM对输入进行理解,并给出恰当的回应

  • 大语言模型(但不是所有LLM都是decoder-only架构)
  • 文本生成:根据部分输入获得完整的文本
  • 代码补全
  • 对话生成
  • 问答系统
1.输入

真实标签在滞后一个单位进入decoder层参与数据运算,这种与其他模型训练都不同的,允许真实标签参与数据运算的模式称之为强制学习teacher forcing

对于(batch_size,seq_len,input_dimensions):

  • encoder的seq_len可能不同于decoder的seq_len
  • 滞后:向未来移动。

在transformer中,在y开头加一个标记SOS(start of sequence),使得原有的序列滞后一个时间步。

EOS(end of sequence)需要添加到计算损失函数的y中,但在输入解码器的y中并不强制要求添加。

在实现时会将sos设置为0,将eos设置为1,而序列本身从2开始编码。

teacher forcing

  • 利用序列A的所有 + 序列B的前半段 来预测序列的后半段
  • 在预测第i个词时,可以直接知晓前i-1个正确的词,而不管前面的预测的结果。避免了错误累计
  • 没有泄露真实标签,但是又为下一次词的预测提供的最大程度的准确信息。
  • 并且由于预测之间是没有联系的,那么是可以并行训练的!!太伟大了。

自回归过程

  • 在测试和推理的时候,由于没有真实的标签矩阵,那么就将上一个预测的输出作为decoder需要的输入
2.带mask的自注意力层

避免数据泄露。Q不能对未来的K发问

通过掩码矩阵,将未来的注意力得分设置为负无穷,这样在softmax之后会变成0:
M = [ 0 − ∞ − ∞ ⋯ − ∞ 0 0 − ∞ ⋯ − ∞ 0 0 0 ⋯ − ∞ ⋮ ⋮ ⋮ ⋱ ⋮ 0 0 0 ⋯ 0 ] \mathbf{M} = \begin{bmatrix} 0 & -\infty & -\infty & \cdots & -\infty \\ 0 & 0 & -\infty & \cdots & -\infty \\ 0 & 0 & 0 & \cdots & -\infty \\ \vdots & \vdots & \vdots & \ddots & \vdots \\ 0 & 0 & 0 & \cdots & 0 \\ \end{bmatrix} M= 0000000000
通过 Q K T + M QK^T+M QKT+M 即可。

这样最终得到的注意力分数矩阵C会完全符合在teacher forcing时要求的矩阵。

前瞻掩码

  • 不同于在计算注意力时通过掩码矩阵来完成掩码,前瞻掩码在输入数据时就进行预处理 (y+M) 从而实现和 Q K T + M QK^T+M QKT+M 完全相同的效果。
  • 在实际实现中可以直接使用triu和tril函数。

padding填充掩码

  • 在计算注意力分数不对的填充词进行计算,从而掩盖填充所造成的影响。
  • 需要手动进行实现,并且维度应该为(batch_size,num_heads,seq_len,seq_len)。
3.编码器-解码器注意力层

此层的输入是多头自注意力机制的输出:

  • decoder的mask attention机制的输出作为Q。
  • encoder的输出作为K,V。

force-learning需要将每行Q与全部的K、V相乘(而非对应的列),所以需要对其context进行矫正。

Decoder Only

不存在编码器-解码器注意力层:

  • 训练采用force-teaching,不会累计错误。
  • 推理采用auto-regressive,会累计错误。
  • outputs之外,可以存在inputs的输入,但是需要是与outputs输入无关的背景信息/条件。
  • GPT中,将inputs作为system信息,而用户的输入作为outputs信息输入。
  • 为了实现在开始时使用一部分的单词而非首个单词进行预测,可以通过移动前瞻掩码矩阵对角线来完成。

你可能感兴趣的:(人工智能,transformer,深度学习,人工智能)