🌺历史文章列表🌺
- 深度学习------优化算法、激活函数、归一化、正则化
- 深度学习------权重初始化、评估指标、梯度消失和梯度爆炸
- 深度学习------前向传播与反向传播、神经网络(前馈神经网络与反馈神经网络)、常见算法概要汇总
- 万字长文解读深度学习------卷积神经网络CNN
- 万字长文解读深度学习------循环神经网络RNN、LSTM、GRU、Bi-RNN
- 万字长文解读深度学习------Transformer
- 万字长文解读深度学习------GPT、BERT、T5
- 万字长文解读深度学习------ViT、ViLT、DiT
- 万字长文解读深度学习------CLIP、BLIP
- 万字长文解读深度学习------AE、VAE
- 万字长文解读深度学习------GAN
- 万字长文解读深度学习------训练、优化、部署细节
文章目录
- 初识Transformer
- [1. 编码器-解码器架构](#1. 编码器-解码器架构)
- [2. 自注意力机制(Self-Attention Mechanism)](#2. 自注意力机制(Self-Attention Mechanism))
- [3. 位置编码(Positional Encoding)](#3. 位置编码(Positional Encoding))
- [4. 前馈神经网络(Feed-Forward Neural Network, FFN)](#4. 前馈神经网络(Feed-Forward Neural Network, FFN))
- [5. 残差连接和层归一化(Residual Connections and Layer Normalization)](#5. 残差连接和层归一化(Residual Connections and Layer Normalization))
- [6. Transformer 的应用](#6. Transformer 的应用)
- [7. Transformer 的优势](#7. Transformer 的优势)
- 编码解码的过程
- 训练、推理过程的不同
- [Transformer 推理的步骤](#Transformer 推理的步骤)
- [1. 输入准备](#1. 输入准备)
- [2. 编码器处理](#2. 编码器处理)
- [3. 解码器初始化](#3. 解码器初始化)
- [4. 逐步生成输出](#4. 逐步生成输出)
- [5. 终止条件](#5. 终止条件)
- [6. 输出序列](#6. 输出序列)
- Self-Attention的计算过程
- [1. 输入嵌入(输入序列向量化+位置编码)。](#1. 输入嵌入(输入序列向量化+位置编码)。)
- [2. 计算 Query、Key 和 Value。](#2. 计算 Query、Key 和 Value。)
- [3. 计算点积注意力得分。](#3. 计算点积注意力得分。)
- [4. 对点积进行缩放。](#4. 对点积进行缩放。)
- [5. (可选)对未来时间步进行掩码。](#5. (可选)对未来时间步进行掩码。)
- [6. 使用 softmax 计算注意力权重。](#6. 使用 softmax 计算注意力权重。)
- [7. 将注意力权重与 Value 进行加权求和。](#7. 将注意力权重与 Value 进行加权求和。)
- [8. (可选)使用多头注意力机制。](#8. (可选)使用多头注意力机制。)
- [9. 残差连接与层归一化。](#9. 残差连接与层归一化。)
- 位置编码
- [Q K V 维度](#Q K V 维度)
- [1. Query (Q)、Key (K)、Value (V) 的作用:](#1. Query (Q)、Key (K)、Value (V) 的作用:)
- [2. 常见的维度关系](#2. 常见的维度关系)
- [2.1 Q 和 K 的维度通常相同](#2.1 Q 和 K 的维度通常相同)
- [2.2 V 的维度可以与Q和K的维度不同](#2.2 V 的维度可以与Q和K的维度不同)
- [3. 总结](#3. 总结)
- 计算公式中的权重矩阵初始化
- 为什么要进行缩放?
- [Scaled 的作用](#Scaled 的作用)
- 遮蔽(Mask)
- 如何做到多头?
- 自注意力的时间复杂度
- 编码器-解码器注意力机制
- 前馈神经网络的双层结构
- [1. 前馈神经网络的结构](#1. 前馈神经网络的结构)
- [2. 为什么需要两个权重矩阵和两个偏置项?](#2. 为什么需要两个权重矩阵和两个偏置项?)
- [3. 作用和重要性](#3. 作用和重要性)
- [4. 总结](#4. 总结)
- 残差网络
- 层归一化
- Transformer的并行化(Decoder可以做并行化嘛?)
- 解决梯度消失和梯度爆炸方案
- Softmax在transformer中的什么作用
- Transformer模型中,Dropout的位置
- [Transformer 输入总结](#Transformer 输入总结)
- ROPE位置编码方法
- [ROPE 的特点总结](#ROPE 的特点总结)
初识Transformer
Transformer 是一种革命性的神经网络架构,最早由 Vaswani 等人在 2017 年提出,它彻底改变了自然语言处理(NLP)的领域 。与传统的递归神经网络(RNN)和长短期记忆网络(LSTM)不同,Transformer不依赖于序列的时间步 ,而是通过注意力机制 并行处理整个输入序列。它在诸如机器翻译、文本生成和语言模型等任务中表现出色。下面详细介绍 Transformer 的原理、结构和应用。
1. 编码器-解码器架构
Transformer 的架构由两个部分组成:
- 编码器(Encoder) :将输入序列 -> (映射) -> 连续的表示空间。
- 解码器(Decoder) :根据编码器的输出 ->生成目标序列。
编码器和解码器均由多个相同的层堆叠 而成。每层都有两个主要组件:
- 多头自注意力机制(Multi-Head Self-Attention Mechanism)
- 前馈神经网络(Feed-Forward Neural Network)。
解码器的额外结构
解码器除了与编码器相同的结构外,还多了一个编码器-解码器注意力机制 ,它在生成每个目标时依赖于编码器的输出。
2. 自注意力机制(Self-Attention Mechanism)
Transformer 的核心是自注意力机制,它能够捕捉输入序列中的全局依赖关系 ,并且不需要像 RNN 那样逐步计算 。
解码器中的注意力机制的2点特殊
- 编码器-解码器注意力机制 :解码器中,不仅包含自注意力机制,还包括一个与编码器输出交互 的注意力机制,它允许解码器在生成每个词时参考编码器的上下文信息。
- 未来遮蔽 :确保在生成第 t 个词时 ,只能看到之前生成的词,而看不到未来的词。
3. 位置编码(Positional Encoding)
因为 Transformer 不依赖输入序列的顺序信息 ,它需要显式地将位置信息引入模型中 。为此,Transformer 使用位置编码(Positional Encoding)来为每个输入向量添加位置信息。
位置编码通过正弦和余弦函数生成 ,并按照序列的索引位置注入到每个词向量中:
其中 ( p o s pos pos ) 是词在序列中的位置,( i i i ) 是词向量的维度索引,( d d d ) 是词向量的总维度。
4. 前馈神经网络(Feed-Forward Neural Network, FFN)
在每个编码器和解码器层中,除了自注意力机制外,还包括一个前馈神经网络。每个时间步上的前馈网络是独立应用 的,它的公式如下:
5. 残差连接和层归一化(Residual Connections and Layer Normalization)
Transformer 的每个子层 (如自注意力机制或前馈神经网络)后 面都有一个残差连接(Residual Connection)和层归一化(Layer Normalization),确保在网络训练的过程中信息可以直接传递,缓解深层网络中的梯度消失问题 。
残差连接的形式为:
6. Transformer 的应用
Transformer 由于其并行计算的优势,以及在处理长距离依赖关系上的优越表现,在许多任务中取得了卓越的成果:
- 机器翻译:例如谷歌翻译。
- 文本生成:例如 OpenAI 的 GPT 系列模型。
- 文本摘要:自动生成文档摘要。
- 语言建模:如 BERT、GPT 及其变体,用于各种 NLP 任务。
- 图像处理&多模态:ViT、ViLT。
7. Transformer 的优势
- 并行处理 :不依赖时间步顺序,可以并行处理整个序列,因此训练速度更快,特别适合大规模数据集。
- 长距离依赖处理能力强 :注意力机制,能够轻松处理序列中远距离的依赖关系,而不像 RNN 或 LSTM 那样受限于序列的长度。
- 广泛的应用:Transformer 已成为 NLP 的标准架构,并被扩展到其他领域,如图像处理(Vision Transformer, ViT)和语音处理等。
编码解码的过程
编码过程(Encoder)
主要任务是将输入序列转换为一种捕捉全局上下文信息的表示 。这一过程确保输入序列中的每个元素 (如文本中的单词或句子中的其他单位)都能够有效地"理解"整个输入序列中的其他元素,从而为后续任务(如机器翻译、文本生成等)提供丰富的上下文信息。
输入数据的准备(输入数据向量化+位置编码)
其中 x e m b e d d i n g x_{embedding} xembedding是输入数据向量化; P E p o s i t i o n PE_{position} PEposition是位置编码,具体实现如下:
自注意力机制(循环计算多次------多头)
前馈神经网络
在每个编码器层的注意力机制之后,接着使用一个前馈神经网络,它对每个位置上的向量独立进行非线性变换:
这是一个两层的全连接网络,使用 ReLU 作为激活函数。
残差连接和归一化
每一层的注意力机制和前馈神经网络的输出都会经过残差连接 (Residual Connection) 与输入相加,并通过层归一化 (Layer Normalization):
这样可以缓解梯度消失问题 ,加速训练。
编码器通常由多层(例如 6 层)堆叠组成。最终,编码器的输出是一个包含全局上下文信息的序列表示,作为解码器的输入。
解码过程(Decoder)
解码过程是自回归 的,目的是根据编码器生成的上下文信息,以及已经生成的部分目标序列,逐步生成完整的输出序列(例如,翻译后的句子)。解码器的每一层与编码器类似,但有几个额外的步骤。
自回归模型:Transformer 的解码器是自回归的,这意味着解码器会根据已经生成的输出 (即部分目标序列)来生成下一个时间步的输出。
输入嵌入和位置编码
解码器首先将已经生成的目标序列进行嵌入 ,并加入位置编码,确保模型感知目标序列的顺序。
计算自注意力时加入遮蔽机制(Masked Self-Attention Mechanism)
在解码过程中,使用遮蔽自注意力机制 。通过对未来词进行掩蔽,确保在生成某个位置上的词时,解码器只能看到之前生成的词,而不能看到未来的词。
这个步骤确保 生成过程是按顺序进行的。
增加编码器-解码器注意力机制(Encoder-Decoder Attention)
在每一层中,解码器还使用编码器-解码器注意力机制。这个机制使解码器在生成每个目标词时参考编码器提供的上下文信息,帮助生成更合适的输出。
编码器-解码器注意力与自注意力的区别在于:
- 作用不同 :
- 自注意力机制(Self-Attention Mechanism) :作用于单一序列 (即源序列或目标序列),用于捕捉序列内部元素之间的上下文信息。
- 编码器-解码器注意力机制(Encoder-Decoder Attention Mechanism) :作用于两个序列之间 (源序列和目标序列),用于将编码器的输出信息传递到 解码器中。解码器的每个位置会基于编码器输出的特征来生成当前步的输出,从而实现对源序列和目标序列的关联建模。
- 输入不同 :
- 自注意力(Self-Attention) :
- 查询 ( Q )、键 ( K )、值 ( V ) 都来自同一个输入序列
- 编码器-解码器注意力(Encoder-Decoder Attention) :
- 查询 ( Q ) 来自解码器;
- 键 ( K ) 和值 ( V ) 来自编码器的输出序列。
- 自注意力(Self-Attention) :
前馈神经网络
类似于编码器的每一层,解码器每层的输出也会通过一个前馈神经网络进行非线性变换。
残差连接和层归一化
与编码器相同,解码器也使用残差连接和层归一化来稳定训练过程。
输出生成
最后一层解码器的输出经过一个线性层和 softmax 函数,用来生成目标词的概率分布。在每个时间步,解码器根据概率分布选择下一个词,逐步生成整个目标序列。
整体编码解码流程总结
- 编码过程 :编码器通过多头自注意力机制和前馈神经网络 ,将输入序列中的每个位置的单词转化为一个上下文相关的表示 。经过多层堆叠的编码器 ,生成输入序列的全局表示,供解码器使用。
- 解码过程 :解码器首先通过遮蔽自注意力机制生成目标序列中的下一个词 ,然后使用编码器-解码器注意力机制 获取编码器输出的信息,结合目标序列的已有部分,生成新的词 。解码器通过循环逐步生成整个目标序列。
这个过程确保模型能够捕捉输入序列的全局信息,并在生成目标序列时做到合理且流畅的生成。
训练、推理过程的不同
步骤 | 训练流程 | 推理流程 |
---|---|---|
输入准备 | 有完整的源序列和目标序列作为输入 | 只有源序列作为输入 (目标序列是空) |
解码器输入 | 使用目标序列的前 ( m-1 ) 个词作为解码器输入(强制教学) | 自回归生成,每步使用解码器生成的词作为下一步输入 |
生成机制 | 每步根据目标序列计算输出,并与真实词对比计算损失 | 逐步生成输出,依赖之前生成的词作为输入 |
损失计算 | 计算每个时间步与真实词之间的损失 | 无损失计算,只预测输出 |
反向传播 | 使用反向传播计算梯度,并更新模型参数 | 不涉及反向传播,只进行前向传播和输出预测 |
Transformer 推理的步骤
1. 输入准备
- 输入序列
- 词嵌入(Embedding)
- 位置编码
2. 编码器处理
- 6个循环编码器层 :
- 多头自注意力机制
- 残差和归一化层
- 前馈神经网络
- 残差和归一化层
3. 解码器初始化
- 解码器输入 :推理过程通常从一个特殊的起始符号 (如
<sos>
,表示序列开始)开始。
4. 逐步生成输出
采用自回归生成 ,直到生成终止符(如 <eos>
,表示序列结束)。
每一步生成的流程如下:
- 6个循环解码器层:
- 掩码(masking)
- 自注意力机制(Masked Self-Attention)
- 编码器-解码器注意力机制
- 前馈神经网络
- 输出预测
- 更新解码器输入
5. 终止条件
- 生成终止符
- 达到最大长度
6. 输出序列
Self-Attention的计算过程
Self-Attention 的计算过程可以分为以下几个关键步骤:
1. 输入嵌入(输入序列向量化+位置编码)。
2. 计算 Query、Key 和 Value。
3. 计算点积注意力得分。
4. 对点积进行缩放。
5. (可选)对未来时间步进行掩码。
6. 使用 softmax 计算注意力权重。
7. 将注意力权重与 Value 进行加权求和。
8. (可选)使用多头注意力机制。
9. 残差连接与层归一化。
这些步骤构成了 Self-Attention 机制的核心计算流程,确保模型可以有效地捕捉输入序列中各个位置之间的依赖关系。
下面将按照顺序详细讲解这些步骤中可能的考点
位置编码
在Transformer模型中,位置编码(Positional Encoding)是用于引入位置信息的关键组件。由于Transformer没有像递归神经网络(RNN)那样的顺序处理机制,它不能天然地获取输入序列的顺序信息,因此需要通过位置编码显式地为输入数据引入位置信息。
1. 位置编码的目的
自注意力机制是并行执行的,因此模型本身不会隐式地知道输入序列的顺序(即词的位置)。为了让模型理解序列的顺序,在【输入嵌入(word embedding)】上添加了位置编码,使得嵌入向量同时包含语义信息和位置信息 。这可以让模型感知每个词的位置,从而能够处理具有顺序关系的任务,如机器翻译或文本生成。
2. 位置编码的公式
位置编码通过正弦和余弦函数 生成,每个位置的编码向量都不同,从而保留了词在序列中的位置信息。位置编码的公式如下:
偶数维度
奇数维度
其中,10000 是一个基数,用于控制位置编码的周期性和范围。选择10000作为基数 (scale factor)的原因主要与平衡模型的数值范围和稳定性 有关。选择 10000 作为基数能够确保模型在短距离信息和长距离信息之间取得平衡,既能感知局部词与词的关系,又能捕捉到全局顺序信息。
这里,10000 控制着不同维度中的频率。小的维度具有较大的频率(变化较快),而大的维度具有较小的频率(变化较慢)。这样,模型可以通过这些不同的频率来编码序列中的位置信息。 如果基数过大或过小,会影响位置编码的数值范围,进而影响模型的表现。
- 如果基数太大:正弦和余弦函数的输入值会非常小,导致输出接近线性变化,这样位置编码无法充分反映序列的位置信息。
- 如果基数太小:正弦和余弦函数的输入值会非常大,导致它们快速进入周期性的震荡状态,失去了平滑变化的特性,进而难以捕捉序列中相对较长的依赖关系。
10000 是一个经验性选择,确保正弦和余弦函数的值在常见的序列长度范围内(如20到100个词)能够有效地变化,既能捕捉到短距离的依赖关系,也能捕捉到较长距离的依赖。
3. 位置编码的特点
-
周期性 :由于正弦和余弦函数的周期性,位置编码具有周期性的特点。这意味着编码可以很好地捕捉 到序列中位置之间的相对关系,而不仅仅是绝对位置。对于较小的维度,编码的周期较短,可以捕捉到细粒度的局部位置信息;对于较大的维度,周期较长,捕捉到全局信息。
-
唯一性 :每个位置都有独特的编码。通过将正弦和余弦函数应用于偶数和奇数维度,位置编码在不同维度上具有不同的变化模式,这保证了每个位置的编码是唯一的。
-
无参数学习 :位置编码的值是通过公式计算得出的,而不是通过训练学习的 。这与嵌入向量不同,嵌入向量是通过反向传播优化得到的参数。
总结
- 位置编码 通过正弦和余弦函数为输入序列中的每个词引入位置信息,使Transformer模型能够理解输入序列中的顺序关系。
- 位置编码的生成方式使其在不同维度上具有不同的频率变化,从而能够捕捉到序列中的局部和全局关系。
- 正弦函数和余弦函数分别用于偶数和奇数维度,通过这种方式,位置编码可以为每个位置提供独特的向量表示,并且这种表示是平滑、连续的。
Q K V 维度
在 注意力机制 中,Q (Query)、K (Key)、和 V(Value) 的维度不一定需要完全相同,但有一些具体的约束条件和常见的设置。下面对它们的维度关系进行详细说明。
1. Query (Q)、Key (K)、Value (V) 的作用:
- Query :用于查询注意力得分 ,代表需要关注什么。
- Key :与 Query 进行匹配 ,决定应该关注哪些内容。
- Value :代表具体要提取和返回的内容,在确定了哪些部分重要之后,用于输出相关信息。
2. 常见的维度关系
在计算注意力时,Q 、K 、和 V 的维度可以不同,以下是常见的设置及约束:
2.1 Q 和 K 的维度通常相同
Q 和 K 的维度通常是相同的。原因是:
- 在点积注意力(dot-product attention)中,注意力分数是通过 Q 和 K 的点积计算得到的。因此,它们的最后一维(即嵌入维度)需要相同,以保证点积运算的合法性。
如果 ( Q ) 的维度是 ( d q d_q dq ),而 ( K ) 的维度是 ( d k d_k dk ),那么在进行 ( Q ⋅ K T Q \cdot K^T Q⋅KT ) 的点积运算时,通常要求 ( d q = d k d_q = d_k dq=dk ),以便能够得到一个合适的注意力得分矩阵。
2.2 V 的维度可以与Q和K的维度不同
V 的维度通常与输出的维度 ( d m o d e l d_{model} dmodel) 相关,可以与 Q 和 K 的维度不同。
3. 总结
- Q 和 K 的维度必须相同,以便能够进行点积计算,产生注意力得分。
- V 的维度可以与 Q 和 K 不同,因为 Value 只是加权求和的内容,维度可以根据任务需求设置。
常见的做法是将 Q 、K 和 V 的维度设为相同,尤其是在多头注意力机制中,这是为了简化计算。
计算公式中的权重矩阵初始化
权重矩阵( W Q W_Q WQ ), ( W K W_K WK ), ( W V W_V WV )、线性变换权重( W O W_O WO )
- Xavier初始化(也称Glorot初始化)是**Transformer中注意力层权重矩阵初始化的常用选择,**适用于大多数线性层和多头注意力机制中的权重初始化。
- He初始化 是前馈网络 的权重初始化的常用选择具有ReLU或其变体激活函数的网络中更为有效,适用于提高模型的稳定性。
- 偏置项:一般初始化为 0。
权重矩阵的训练与学习
在Transformer中,这些权重矩阵,即 ( W Q W_Q WQ ), ( W K W_K WK ), ( W V W_V WV ), ( W O W_O WO )都是模型的可训练参数。训练过程如下:
- 初始化:在训练开始时,这些权重矩阵使用Xavier初始化,随机初始化为小值。
- 前向传播:输入序列通过这些线性变换生成查询、键和值,然后经过注意力计算,得到输出。
- 计算损失:根据模型的输出和目标值,计算损失函数,如交叉熵损失(在分类任务中)。
- 反向传播:通过反向传播算法,损失函数的梯度从输出层逐层传递回这些线性变换的权重矩阵。
- 更新权重:使用优化算法(如Adam或SGD),根据梯度更新权重矩阵的值,从而逐步调整它们,使模型在后续的训练中能够更好地拟合数据。
激活函数相关知识点参考:深度学习------权重初始化、评估指标、梯度消失和梯度爆炸
为什么要进行缩放?
Scaled Dot-Product Attention ,"scaled" 指的是对点积的结果进行缩放处理 。
在 Transformer 的注意力机制中,Attention 的核心操作是计算"查询(Query)"和"键(Key)"的点积,来衡量输入序列中不同位置的信息相互关联的程度。公式如下:
原因
这个缩放步骤是为了避免点积值过大,导致后续的 softmax函数输出分布非常尖锐,产生梯度爆炸问题
这个操作可以将点积值缩小,使得它们处于更合理的范围内,从而保证 softmax 函数的输入不会过大或过小。从而使 Transformer 模型的注意力机制能够更有效地学习长距离依赖关系
在没有缩放的情况下,点积 ( Q K T QK^T QKT ) 的值随着维度 ( d k d_k dk ) 增大而变大。当维度较大时,点积的结果可能会非常大,导致在应用 softmax 函数时,输出分布非常尖锐(即某些注意力权重接近于 1,而其他权重接近于 0)。这会导致梯度爆炸的问题,影响模型的训练效果。
Scaled 的作用
-
数学解释 :键的维度 ( d k d_k dk ) 增大时,点积 ( Q K T QK^T QKT ) 的期望值和方差也会增大。通过除以 ( d k \sqrt{d_k} dk ),可以将点积的方差标准化为 1,保持稳定的数值范围。
-
实际效果 :缩放后的点积值较小,softmax 输出会更加平滑,能够更合理地分配注意力权重,从而改善训练的稳定性和模型的表现。
遮蔽(Mask)
填充遮蔽(Padding Masking)与未来遮蔽(Future Masking)介绍
Transformer 模型中的遮蔽机制是确保模型在处理不定长序列 或自回归生成任务 时能够正确工作的重要技术。
其中,填充遮蔽 和未来遮蔽是两种关键的遮蔽方法,它们的目的是避免模型在不适当的位置关注无意义的填充值或未来的词。下面我们将详细介绍这两种遮蔽机制的作用、工作原理、公式表示、具体作用举例和总结。
1. 填充遮蔽(Padding Masking)与未来遮蔽(Future Masking)的作用
填充遮蔽的作用
主要作用是处理变长输入序列。为了使得批量处理中的所有句子具有相同的长度 ,较短的句子会使用 padding 填充,并且确保序列中用来填充(如[PAD]
标记)的部分不会在注意力机制中被模型关注。
在自然语言处理中 ,由于输入的序列长度可能不同,较短的序列通常需要填充到固定长度 。这些填充的部分是无意义的,占位符而已。因此,填充遮蔽用于忽略这些填充值,防止它们影响模型的训练和推理过程。
为什么需要填充(padding)?
- 循环神经网络(RNN, LSTM, GRU)
- 批处理的高效性 :在处理批次数据 时,也需要将序列填充到固定长度 ,以便所有序列能够一起进行计算。将序列填充到相同长度后,数据就能构建成相同维度的张量 ,便于在批处理时并行运算。
- 硬件加速的需求 :依赖GPU或TPU等硬件加速器,变长序列如果不进行填充,会导致批处理中的张量形状不一致,从而无法高效利用并行计算的优势。
卷积神经网络(CNN)在处理文本或序列任务时、语音识别模型、时间序列预测模型都需要进行padding。
- Transformer在其他领域的变长输入
- 批处理的需求:Transformer在处理变长输入时,无论是文本、图像还是视频任务,都需要确保输入的长度一致,以便模型能够进行批处理和高效计算。
未来遮蔽的作用
- 未来遮蔽 ,也称为自回归遮蔽 ,用于生成任务中的解码器部分 。它的作用是防止模型在生成过程中"看到"当前词之后的未来词,确保每个时间步的输出只能依赖于当前时间步及之前的词。
- 未来遮蔽在生成任务(如文本生成、机器翻译等)中尤为重要。
2. 填充遮蔽与未来遮蔽的工作原理
填充遮蔽的工作原理
- 填充遮蔽通过生成一个遮蔽矩阵/向量,标记哪些位置是填充值(例如,
[PAD]
标记通常用0
填充) 。然后,在计算注意力得分时,将这些位置的注意力分数设置为极小值(通常为负无穷),从而确保填充值不会影响模型的注意力计算。
例如,假设有一个序列长度为 5 的输入句子,填充部分用[PAD]
标记表示,填充遮蔽向量会如下所示:
Mask = [1,1,1,0,0]
- 这里的
1
表示实际输入,0
表示填充值([PAD]
),对应的注意力得分在计算时会被设置为极小值(如负无穷),从而在softmax中不再产生影响。
未来遮蔽的工作原理
- 未来遮蔽通过生成一个上三角矩阵 ,确保每个时间步只能关注当前时间步及之前的词,避免"偷看"未来的词。例如,序列长度为 5 时的未来遮蔽矩阵为:
- 这个上三角矩阵确保模型在时间步 ( i ) 只能看到之前的词,而不能看到未来的词。被设置为负无穷的部分表示未来词被屏蔽,从而在softmax计算后,未来词的注意力分数会为零。
3. 公式表示
填充遮蔽的公式表示
在填充遮蔽 中,掩码矩阵 ( M pad M_{\text{pad}} Mpad ) 会被添加到注意力分数上。注意力机制的公式为:
未来遮蔽的公式表示
在未来遮蔽 中,同样需要将未来遮蔽矩阵 ( M future M_{\text{future}} Mfuture ) 添加到注意力得分上:
Q&A
为什么填充遮蔽的填充矩阵不使用未来遮蔽的负无穷表示填充值?
填充遮蔽需要参与到注意力计算点积( Q ⋅ K T Q \cdot K^T Q⋅KT )中(对原始句子进行填充,之后进行点积计算),所以需要考虑下面的部分:
- 效率 :使用布尔或 0/1 掩码可以更灵活地计算,并减少负无穷值在早期引入带来的数值问题。
- 数值稳定性 :在某些硬件和计算精度下,直接处理负无穷值可能会导致数值不稳定。通过布尔值等手段间接表示负无穷,有助于提高稳定性。
- 代码兼容性和可维护性 :布尔掩码或 0/1 掩码的表示更简单,适用于不同的框架和优化需求。
为什么未来遮蔽使用负无穷?不使用填充遮蔽的0/1?
未来遮蔽不需要参与到注意力计算点积( Q ⋅ K T Q \cdot K^T Q⋅KT )中 ,只作用于负无穷值是在计算注意力得分之后,softmax之前的注意力得分矩阵 。
1. 计算位置固定和小矩阵
- 未来遮蔽的掩码矩阵大小较小 :
- 在模型的解码器自注意力层使用。
- 矩阵的大小等于序列长度,比较小。
2. 未来遮蔽的矩阵形状固定
未来遮蔽是一个静态生成的上三角矩阵,形状是固定的(例如 (5 \times 5)),且负无穷只应用于未来词的位置。
相比之下,填充遮蔽需要动态生成掩码矩阵,以适应变长序列的不同填充位置,填充位置可能在序列的任意位置,这样的灵活性要求更高。因此,在填充遮蔽中,直接使用负无穷可能会导致效率问题,而未来遮蔽则不需要这种灵活性,矩阵是固定形状且规则的。
3. 负无穷在softmax之前的处理
负无穷值只作用于负无穷值是在计算注意力得分之后,softmax之前的注意力得分矩阵且其负无穷的引入非常明确和局部化,这使得计算较为高效。
总结
- 未来遮蔽 直接使用负无穷值的原因是其计算位置固定 、矩阵较小 且形状规则,负无穷只影响局部注意力得分计算之后,不涉及复杂的动态生成和反向传播问题。
- 填充遮蔽 其掩码矩阵需要动态生成 ,形状不固定,并且影响编码器和解码器的多个层次的计算,因此在实现中通常先使用布尔或 0/1 掩码,并在最后一步处理负无穷,避免早期引入极端数值而导致的数值稳定性问题。
如何做到多头?
目的 :让每个注意力头可以在不同的子空间中独立地学习和关注序列中的不同特征和关系 。
在多头自注意力机制中,每个头的输入是一样的 ,即每个头接收到的初始输入向量是相同的。但是每个头的权重矩阵都是不同的 。在多头自注意力机制中,每个头都有自己的独立的权重矩阵来生成查询(Query) 、键(Key)和值(Value),都会使用随机初始化(通常使用Xavier初始化)。
为什么Xavier初始化能确保不同头的权重不同?
Xavier初始化的随机性是使得每个头的权重矩阵初始化不同的关键:
- 虽然Xavier初始化方法是相同的,但随机数生成器为每个权重矩阵生成不同的初始值。每个矩阵的数值是通过从特定范围(由Xavier初始化确定的)内随机抽样得到的,而不是固定值。
- 由于每个头的权重矩阵是独立的可训练参数 ,这些矩阵会被单独初始化,即每个头的权重矩阵会独立生成自己的初始值,而不共享具体的数值。
自注意力的时间复杂度
总的时间复杂度是O( n 2 d n^2 d n2d),来自计算自注意力机制。
QK矩阵乘法 的复杂度是矩阵行列数乘以中间的维度d,即 n×n×d。
O( n 2 d n^2 d n2d)的解释:
在许多自然语言处理任务中,序列长度 (n)(如一个句子或段落的单词数量)通常会比较大,而嵌入维度 (d) 的大小相对较小 。因此,序列长度 (n) 经常远大于 嵌入维度 (d) 。
所以,总的时间复杂度是O( n 2 d n^2 d n2d)
常见的设置如下:
- 序列长度 (n):对于自然语言处理任务,句子或文本的长度可以是几十到几百个词。例如,在机器翻译、文本摘要生成等任务中,句子长度可能是 20 到 100+。
- 嵌入维度 (d):嵌入维度通常是一个较小的固定值,比如 256、512、768 等,依赖于任务的具体要求。嵌入维度表示每个词的特征空间大小,但它并不需要过大,因为过大的嵌入维度可能会导致过拟合和计算负担。
编码器-解码器注意力机制
编码器-解码器注意力机制 (Encoder-Decoder Attention Mechanism)是Transformer模型中连接编码器(Encoder)和解码器(Decoder)的一种关键机制。该机制允许解码器在生成每个目标词时参考编码器提供的上下文信息,帮助生成更合适的输出。
与自注意力的不同
输入的不同
- 自注意力(Self-Attention) :查询 ( Q )、键 ( K )、值 ( V ) 都来自同一个输入序列。
- 编码器-解码器注意力(Encoder-Decoder Attention) :
- 查询 ( Q ) 来自解码器【Q 来自解码器当前层的输入 或 上一层的输出】;
- 键 ( K ) 和值 ( V ) 来自编码器的输出序列。
(当前层的输入==上一层的输出, 每次的输出比之前多一个词,之后当作下层的输入)。
作用的不同
- 自注意力 :捕捉序列内部元素之间的依赖关系,帮助模型理解序列中的局部或全局信息。
- 编码器-解码器注意力 :在输入序列和输出序列之间建立联系,帮助解码器根据编码器的输出生成更合适的目标词。
编码器-解码器多头注意力机制
编码器-解码器注意力机制通常采用多头注意力机制(Multi-Head Attention),即并行计算多个不同的注意力头,每个头有自己的 ( Q )、( K )、( V ) 权重矩阵。多头注意力允许解码器从多个角度关注编码器输出的不同部分,从而捕捉不同层次的特征。
编码器-解码器注意力机制的作用
- 上下文获取 :解码器在生成目标序列时,可以动态地从
编码器
的不同位置获取上下文信息 。这意味着生成每个词时,解码器可以灵活地关注源序列
中与当前生成词最相关的位置,而不必依赖于一个固定的上下文向量。 - 长距离依赖捕捉 :编码器-解码器注意力机制能够捕捉到源序列中的长距离依赖关系。
- 处理不对齐问题 :在很多自然语言处理任务中,源序列和目标序列 的长度可能不同,并且它们之间的对齐关系也不一定是一一对应的。通过编码器-解码器注意力机制,解码器可以选择性地关注编码器输出的某些部分,解决了对齐问题。
在 Transformer 中,编码器-解码器注意力机制 允许解码器在每一步生成目标词时,根据目标序列中已经生成的部分,动态地关注输入序列中的不同位置。这种机制可以根据上下文灵活选择输入信息,解决不对齐问题。
- 编码器部分 :编码器处理输入序列(如源语言句子),并将其表示为上下文表示。每个输入词会被转换为一个上下文向量,这些上下文向量包含了输入序列中不同位置的信息。
- 解码器部分 :解码器在生成目标序列的每一步时,利用编码器-解码器注意力机制来决定应该关注输入序列中的哪些部分。在每个时间步,解码器通过查询(Query)解码器中的状态向量,并与编码器输出的键(Key)向量进行注意力计算,从而生成注意力分数(即每个输入词的重要性)。然后,将这些注意力分数加权应用于输入的值(Value)向量,得到加权和作为解码器生成当前输出的依据。
这一机制使得模型在生成目标序列的每一步时都可以动态地从输入序列中"抽取"相关信息,而不需要固定的对齐方式。
前馈神经网络的双层结构
前馈神经网络的结构由两层全连接神经网络(Fully Connected Layer)组成
1. 前馈神经网络的结构
在Transformer的编码器和解码器中,每个层的前馈神经网络是独立于序列位置 的,即对于每个输入位置 ( x i x_i xi ),前馈网络应用于该位置而不考虑其他位置 。前馈网络的计算过程如下:
2. 为什么需要两个权重矩阵和两个偏置项?
为了实现更强的表达能力,前馈神经网络有两层全连接层,具体来说:
- 第一层扩展维度 :将输入从原始维度(如词向量的维度)扩展到一个更高的维度 ,这样网络能够表示更多的特征信息 ,并且在高维空间中进行更复杂的计算。【类似SVM核函数】
- ReLU 激活函数 :引入非线性,使模型能够学习复杂的非线性关系。
- 第二层将回原始维度 :将经过非线性处理后的结果映射回原始的维度 ,使得最终的输出可以与输入具有相同的形状,方便后续的操作。
两个偏置项 ( b 1 b_1 b1 ) 和 ( b 2 b_2 b2 ) 是为了进一步增加模型的灵活性和表达能力,它们帮助每一层的输出更加独立地进行调整,避免过度依赖输入的线性变换。
3. 作用和重要性
Transformer 中的前馈神经网络使用两层全连接层,主要带来以下好处:
- 引入非线性 :通过两层结构和激活函数,模型可以捕捉更复杂的非线性特征。
- 提升模型表达能力 :扩展-压缩的结构提高了模型的容量,增强了其学习复杂模式的能力。
- 与多头注意力机制互补 :前馈网络负责局部特征的深入处理,与注意力机制的全局特征捕捉形成互补。
- 独立于序列长度 :前馈网络能够对每个位置的输入向量独立处理,灵活适应不同长度的输入。
4. 总结
- Transformer中的前馈神经网络(FFN)包含两个权重矩阵 ( W 1 W_1 W1 ) 和 ( W 2 W_2 W2 ) 【He初始化】以及相应的偏置项 ( b 1 b_1 b1 ) 和 ( b 2 b_2 b2 )【初始化为0】,这是因为它是一个由两层全连接层组成的网络。
- 第一层通过 ( W 1 W_1 W1 ) 和 ( b 1 b_1 b1 ) 将输入投影到一个更高的维度,经过非线性ReLU激活函数处理;第二层通过 ( W 2 W_2 W2 ) 和 ( b 2 b_2 b2 ) 将结果投影回原始维度。
- 这种结构允许网络在更高维空间中学习复杂的特征,并将结果映射回可操作的低维空间,从而提高网络的表达能力和性能。
残差网络
残差网络(Residual Network, ResNet)目的是解决深层网络在训练过程中出现的 梯度消失 和 退化 问题。
ResNet 的核心思想是引入残差连接(skip connections),让网络学习残差函数,而不是直接学习复杂的映射函数。
为什么需要 ResNet?
理论上更深的网络能够捕捉到更复杂的特征,效果应该更好。然而,在实际中,随着网络深度的增加,梯度消失 和 梯度爆炸 的问题加剧,导致模型难以收敛。即使通过适当的初始化或正则化缓解了梯度问题,退化问题 也会出现------更深的网络反而会比浅层网络表现更差。
为了解决这个问题,ResNet 引入了残差连接,使得网络可以更容易地训练超深层网络。
残差网络的核心思想
残差连接 是 ResNet 的关键,将输入直接绕过若干层传递给输出,使得网络可以学习输入和输出之间的 "残差" ,而不是直接学习输入到输出的映射 。
ResNet 的基本残差块
每个残差块包含两种路径:
- 主路径(main path) :即通过两层(或三层)卷积操作对输入进行处理,生成 F ( x ) F(x) F(x) 。
- 捷径路径(shortcut path) :直接将输入 x x x 传递给输出。
具体的残差块结构如下:
- 输入 ( x x x ) 通过主路径 ,生成 ( F ( x ) F(x) F(x) )。
- ( x x x ) 通过捷径连接 直接加到 ( F ( x ) F(x) F(x) ) 上,得到输出: y = F ( x ) + x y = F(x) + x y=F(x)+x
这种结构使得即便某些层的 ( F ( x ) F(x) F(x) ) 学习不好 ,网络仍然可以通过捷径连接保留输入信息,确保网络深度的增加不会导致性能下降。
ResNet 的优势
- 缓解梯度消失问题 :残差连接使得梯度能够在反向传播过程中通过捷径路径更好地传递,避免深层网络中的梯度消失问题。
- 解决退化问题 :通过引入残差连接,网络可以学习到恒等映射(identity mapping),即使增加网络深度,也不会出现性能下降的问题,甚至可能获得更好的结果。
- 便于优化:残差网络使得更深的网络变得易于训练,在实践中,ResNet 能够轻松达到数百甚至上千层。
总结
残差网络(ResNet) 通过引入残差连接 ,使得深层神经网络能够在不产生梯度消失和退化问题 的情况下进行训练。其基本思想是让网络学习残差函数,使得网络层数增加时不会显著增加优化难度。这个简单而有效的结构使得 ResNet 成为了现代深度学习中常用的网络架构之一,并广泛应用于计算机视觉等领域。
层归一化
Transformer 模型使用 层归一化(Layer Normalization, LN) 而不是 批归一化(Batch Normalization, BN),主要原因涉及到序列处理的需求、自回归生成任务的特性、模型并行化能力以及训练的稳定性。主要原因包括以下几点:
自回归生成任务、处理变长序列、并行化
- 处理变长序列 :层归一化可以对每个样本的特征维度独立进行归一化,适合不同长度的序列,而批归一化依赖于整个批次的统计量,在变长序列中不适用。
- 自回归生成任务 :在逐步生成目标序列时,层归一化能在每个时间步稳定工作,而批归一化则因依赖于批次数据无法适应。
- 并行化需求 :层归一化的独立性使其非常适合并行计算,避免了批归一化在并行时的同步开销,提升了模型的训练效率。
- 稳定性与效率 :层归一化在处理小批量数据或变长序列时训练更加稳定 ,避免了批归一化引入的训练不稳定问题。
因此,层归一化 更加适合 Transformer 模型中处理复杂的序列任务,确保模型在不同场景下的稳定性和训练效率。
归一化相关知识点参考:深度学习------优化算法、激活函数、归一化、正则化
Transformer的并行化(Decoder可以做并行化嘛?)
层级内的并行化
每一层内部 (如自注意力、前馈神经网络、编码器-解码器注意力机制)的计算是并行的,可以同时处理所有的词,这大大提升了计算效率。
单层编码器的并行化情况
训练阶段和推理阶段的在所有层级都可以完全并行化处理输入序列,极大地提高了处理速度。
单层解码器的并行化情况
- 训练阶段 :解码器可以并行化 ,因为使用了教师强制,整个目标序列是已知的,因此可以同时计算多个时间步的自注意力和编码器-解码器注意力。
- 推理阶段 :解码器需要逐步串行生成目标序列 ,每个时间步依赖前一个时间步的输出,因此自注意力机制不能完全并行化。不过,编码器-解码器注意力部分可以并行进行,因为编码器的输出是已知的。
总之,Transformer 的并行化能力极大地提高了模型在大规模数据上的计算效率,而解码器在推理阶段由于逐步生成词汇的特性,限制了其完全并行化的能力。
层级之间的串行
- 编码器和解码器的所有层级之间是顺序执行的,因为每一层的输出是下一层的输入。
解决梯度消失和梯度爆炸方案
在 Transformer 模型中,梯度消失和梯度爆炸问题的解决方案涵盖了模型的多个层面,确保模型能够在深度学习训练中保持稳定的梯度传播。以下是主要的技术方法及其作用:
- 残差连接:通过为每层引入直接连接,确保梯度能够有效传播,缓解深层网络中的梯度消失问题。
- 层归一化:在每层的输入上进行归一化处理,避免输入分布波动过大,同时解决梯度消失和梯度爆炸问题。
- 缩放点积注意力:通过对点积结果进行缩放,防止点积值过大,避免在 softmax 计算时引发梯度爆炸。
- 权重初始化:通过 Xavier 或 He 初始化等策略,确保初始梯度处于合理范围,避免梯度在训练初期消失或爆炸。
- 学习率调度器 :Transformer 在训练过程采用 warmup(学习率从一个非常小的值开始,并逐渐增大) 和 decay(学习率达到一个峰值,之后开始逐渐降低) 策略,通过动态调整学习率,目的是在模型训练的不同阶段动态调整学习率。
- Warmup 阶段:在训练的初期,学习率从一个非常小的值开始,并逐渐增大,称为 "warmup" 。这一阶段的目的是防止模型在训练开始时的梯度过大或过小,导致梯度消失或梯度爆炸问题。通过缓慢增加学习率,可以帮助模型稳定地找到合适的训练方向。
- 学习率衰减(Decay)阶段:经过 warmup 后,学习率达到一个峰值,之后开始逐渐降低。这是为了避免在训练的中后期由于学习率过大而导致参数更新剧烈,从而引发梯度爆炸。学习率逐步减小,可以让模型在接近最优解时,进行更细致的优化,从而避免训练不稳定。
- 梯度裁剪:在每次参数更新之前,当梯度过大时,限制梯度的范数,确保训练过程中不会出现梯度爆炸。
- 正则化技术:在前向传播过程中,通过 L2 正则化限制权重增长和 Dropout 防止过拟合,间接防止梯度爆炸。
这些技术共同作用,使得 Transformer 能够在大规模训练和深层结构中有效应对梯度消失和梯度爆炸问题,从而确保其在自然语言处理、机器翻译等任务中的出色表现。
Softmax在transformer中的什么作用
- 归一化注意力权重:通过应用softmax函数,注意力权重被归一化,使其和为1,从而形成有效的概率分布。这确保了模型在计算注意力时,能对每个位置的关注程度进行衡量。
- 输出阶段生成概率分布:将最后的线性层输出转换为概率分布,以便进行词预测或分类任务。
Transformer模型中,Dropout的位置
- 在Transformer模型中,Dropout通常被应用于以下位置:
- 在自注意力层和前馈网络之间。
- 在前馈网络内部,即在两个全连接层之间。
- 在残差连接和层归一化之后。
使用Dropout时,通常会在训练过程中启用它,而在模型评估或推理阶段则禁用,以确保所有的神经元都能参与到最终的预测中。通过这种方式,Dropout有助于Transformer模型在多种不同的任务上实现更好的性能。
Transformer 输入总结
Transformer 的输入主要包括以下几个关键部分:
- 源序列:原始的输入序列(如句子),经过嵌入层映射为词向量。
- 目标序列:解码器的输入序列(训练时已知,推理时逐步生成)。
- 词嵌入(Word Embedding):将源序列和目标序列的词转化为固定维度的向量表示。可学习的嵌入(Learned Embeddings):通过嵌入层将词映射为向量,词嵌入矩阵是通过模型训练逐渐学习的。预训练的嵌入(Pre-trained Embeddings):可以使用如 Word2Vec、GloVe 等预训练词向量来初始化嵌入矩阵,帮助模型快速获取语义信息
- 位置编码(Positional Encoding):为词嵌入添加位置信息,确保模型感知序列中的顺序。
- 遮蔽机制(Masking) :
- 填充遮蔽:忽略输入中的填充值。
- 未来遮蔽:确保解码器在生成目标序列时,只能看到当前和过去的词,不能看到未来的词。
- 特殊标记 :如
<START>
、<END>
、<PAD>
等,用于标记序列的起始、结束或填充。
这些输入内容共同作用,保证 Transformer 模型能够正确处理序列数据并生成高质量的输出。
ROPE位置编码方法
ROPE(Rotary Position Embedding) 是一种新的位置编码方法,最早应用于一些改进的 Transformer 模型(如 GPT-NeoX 和 GPT-J),用于替代传统的绝对位置编码 (如 Transformer 中的正弦-余弦位置编码)。它通过引入旋转不变性(rotary invariance),使模型能够更好地捕捉相对位置信息。
ROPE 的特点总结
- 相对位置编码:ROPE 不仅编码词的绝对位置,还能够捕捉词之间的相对位置信息。
- 旋转不变性:通过对查询(Q)和键(K)向量的旋转操作隐式注入位置信息,不需要额外的位置编码向量。
- 提高长序列处理能力:相比于传统的正弦-余弦位置编码,ROPE 在处理长序列时更加有效,能够捕捉远距离的依赖关系。
- 计算高效:无需显式地为每个词计算位置编码,直接对向量进行旋转操作,节省了计算资源。
- 可扩展性:ROPE 对于处理变长序列具有很好的扩展性,能够在训练时未见过的序列长度上表现良好。
这些特点使得 ROPE 在改进 Transformer 模型(如 GPT-J、GPT-NeoX)中被广泛应用,尤其在需要处理长序列的任务中表现出色。