一.循环神经网络的缺陷
循环神经网络(RNN)是一类用于处理序列数据的神经网络,特别擅长处理时间序列数据或自然语言处理任务。然而,尽管RNN在处理这类问题上有其优势,但它也存在一些显著的缺点,这些缺点限制了其在某些场景下的应用效果。
- 梯度消失或梯度爆炸问题:在训练深层RNN时,由于梯度在反向传播过程中不断乘以权重矩阵,这可能导致梯度消失(变得非常小)或梯度爆炸(变得非常大),这使得模型难以学习长距离依赖。
- 难以捕捉长距离依赖:尽管理论上RNN能够处理任意长度的序列,但在实践中,RNN通常难以捕捉长序列中的长距离依赖关系,这部分是因为梯度消失或爆炸问题。
- 序列计算的固有顺序性:由于RNN的递归性质,数据必须按顺序处理,这限制了其并行处理能力,导致训练效率较低,特别是对于长序列。
LSTM(长短期记忆网络)是一种特殊的RNN(循环神经网络),设计初衷就是为了解决传统RNN在长序列数据上训练时出现的梯度消失和梯度爆炸问题。然而,尽管LSTM相较于普通的RNN在处理长序列数据时表现得更好,但它仍然有可能在某些情况下出现梯度消失和梯度爆炸的问题。
二、seq2seq
Self-Attention(SA) Mechanism,自注意力机制,用于捕捉序列数据内部依赖关系的关键技术。

Seq2Seq(Sequence-to-Sequence)是NLP中的经典框架,广泛应用于机器翻译、文本摘要等。其结构包括:
- Encoder:编码器,将输入序列编码为一个固定长度的上下文向量。
- Decoder:解码器,基于上下文向量生成输出序列。
1. Encoder(编码器)
编码器的任务是将输入序列编码成一个固定长度的向量表示(即上下文向量)。该部分通常由递归神经网络(RNN)、长短时记忆网络(LSTM)或门控循环单元(GRU)组成,负责逐步读取输入序列。
-
编码器逐个处理输入序列中的元素(如文本中的单词),并将每一步的信息编码进其隐藏状态。
-
最后一步的隐藏状态将作为编码器的输出,即上下文向量,它总结了整个输入序列的信息。
2. Decoder(解码器)
解码器接收从编码器传递过来的上下文向量,并根据该向量生成输出序列。解码器也是由RNN、LSTM或GRU等神经网络结构组成,它使用上下文向量以及之前生成的输出序列来预测接下来的输出元素。
- 解码器逐步生成输出序列,在每个时间步生成一个输出。
- 每个时间步解码器的输入是前一步生成的输出以及隐藏状态。
3. 工作流程
- 编码阶段:编码器逐步处理输入序列,将其转换为隐藏状态,最后将整个输入序列的信息编码为固定长度的上下文向量。
- 解码阶段:解码器接收上下文向量,并逐步生成目标序列。初始输入通常是特殊的开始标记 ,然后解码器在每个时间步生成一个新的输出元素。
- 预测下一个输出:每一个新的输出都是基于上下文向量和先前生成的输出来预测的。
三.transformer
1.介绍
Transformer论文地址:https://proceedings.neurips.cc/paper/2017/file/3f5ee243547dee91fbd053c1c4a845aa-Paper.pdf
-
自注意力机制:Transformer通过自注意力机制能够高效地计算序列内所有元素之间的关系,这使得模型能够捕捉到长距离依赖,无论这些依赖的距离有多远。
-
并行化处理:与RNN不同,Transformer可以同时处理整个序列,这极大地提高了训练效率。
-
无需递归结构:Transformer完全摒弃了递归结构,这意味着不存在梯度消失或爆炸的问题,同时也使得模型能够更容易地学习长距离的依赖关系。
1.1 核心思想
Transformer的核心思想是利用自注意力机制来捕获输入序列中各元素之间的全局依赖关系,无论这些元素之间的实际距离有多远。
-
自注意力机制:允许模型在处理序列的每个元素时,考虑到序列中的所有其他元素,从而捕捉它们之间的关系和依赖,这对于理解上下文和语言的复杂性至关重要。
-
多头注意力:通过并行地使用多个注意力机制(称为“头”),Transformer能够在不同的表示子空间中捕捉到序列的不同特征。
-
位置编码:由于Transformer本身不具备处理序列顺序的能力,通过添加位置编码到输入序列,模型能够利用序列中元素的位置信息。
1.2 优点
-
高效的并行计算:与传统的循环神经网络不同,Transformer可以处理整个序列的所有元素而无需顺序迭代,这使得其特别适合于现代并行计算硬件。
-
长距离依赖捕捉能力:自注意力机制使得Transformer能够有效地处理长距离依赖问题,这在处理长文本或复杂序列关系时尤为重要。
-
灵活性和广泛的适用性:Transformer架构可以被应用于多种序列处理任务,包括但不限于语言理解、文本生成、机器翻译等。
1.3 应用
由于其强大的特性和灵活性,Transformer已经成为了多个领域的基础模型,其应用包括:
- 自然语言处理:如机器翻译、文本摘要、情感分析、问答系统等。
- 语音和音频处理:如语音识别、音乐生成等。
- 图像处理和计算机视觉:通过将图像切割成序列化的片段,Transformer也被应用于图像分类、物体检测等任务。
- 跨模态任务:如图像字幕生成、视觉问答等,Transformer可以处理来自不同模态(如文本和图像)的数据
2.transformer架构

2.1输入部分
Transformer模型的输入模块主要由两部分组成:嵌入层(Embedding Layer)和位置编码(Positional Encoding)。这两部分共同作用,将原始的输入序列转换为模型能够处理的形式,同时保留序列中的单词信息和单词的位置信息。

2.1.1嵌入层(Embedding Layer)
嵌入层的主要任务是将输入序列中的每个单词或标记(token)转换为固定维度的向量。在自然语言处理任务中,这通常涉及将每个单词映射到一个高维空间,其中语义相近的单词在该空间中的距离也较近。嵌入向量通常是通过训练学习得到的,能够捕捉到单词的语义特征。
工作原理
假设我们有一个很小的词汇表,包含了如下四个单词:“King”, “Queen”, “Man”, “Woman”。对应地,我们为每个单词分配一个唯一的索引:King=0, Queen=1, Man=2, Woman=3。在未使用嵌入层之前,可能会使用独热编码(One-Hot Encoding)来表示这些单词,即:
- King = [1, 0, 0, 0]
- Queen = [0, 1, 0, 0]
- Man = [0, 0, 1, 0]
- Woman = [0, 0, 0, 1]
这种表示方法简单直观,但当词汇量很大时,会变得非常低效和稀疏。更严重的是,独热编码无法捕捉单词之间的语义关系。
引入嵌入层后,会初始化一个嵌入矩阵,其大小为词汇量 x 嵌入维度。假设我们选择的嵌入维度为2(实际应用中通常远大于2,例如128、256、512等),那么对于上述的四个单词,我们可能会初始化如下的嵌入矩阵:
[ [ 0.2, 0.8], # King
[-0.5, 0.4], # Queen
[ 0.1, -0.3], # Man
[-0.1, -0.7] ] # Woman
在这个矩阵中,每一行代表一个单词的嵌入向量。例如,“King”的嵌入向量是[0.2, 0.8]。
当输入一个单词时,嵌入层会根据这个单词的索引在嵌入矩阵中查找对应的嵌入向量。比如,如果输入的单词是“King”,索引为0,嵌入层就会输出[0.2, 0.8]作为这个单词的表示。
嵌入向量的意义
嵌入向量在高维空间中捕捉了单词的语义信息。在理想情况下,语义上相近的单词在嵌入空间中的距离也会很近。比如,在经过足够训练后的嵌入矩阵中,“King”和“Queen”、“Man”和“Woman”的嵌入向量在空间中的距离可能比“King”和“Woman”的距离要近,因为前者在语义上更为相似。
嵌入层通常作为神经网络的第一层出现,其嵌入向量会随着模型的训练不断更新和优化,以更好地捕捉和表示单词之间的复杂关系和语义信息。这种密集且富含语义的表示方式,为深度学习模型处理自然语言提供了强大的基础。
2.1.2 位置编码
由于Transformer模型使用的是自注意力机制,没有像循环神经网络(RNN)那样的递归结构,所以它本身并不能理解序列中元素的顺序,因此Transformer模型本身不具有处理序列顺序的能力(这是因为其使用的自注意力机制会同时考虑序列中所有元素的关系,而不关注元素的顺序),这就需要通过位置编码来向模型提供位置信息。位置编码在Transformer模型中是非常关键的,因为它使模型能够利用单词在序列中的位置信息。位置编码通过为序列中每个单词的嵌入向量添加一个与其位置相关的向量来实现。这个位置向量与单词的嵌入向量具有相同的维度,使得两者可以通过加法或其他方式结合起来。
- 位置编码通过为序列中每个单词的嵌入向量添加一个与其位置相关的向量来实现。
- 这个位置向量与单词的嵌入向量具有相同的维度,使得两者可以通过加法或其他方式结合起来。
计算公式
位置编码可以有多种实现方式,Transformer原始论文中提出的位置编码是通过正弦和余弦函数来计算的,这样做的好处是能够让模型学习到相对位置信息,因为这些函数对位置的偏移是可预测的。对于序列中的每个位置pos,和每个维度 i ,位置编码 ( pos , i ) 是这样计算的:
PEpos,2i=sin(pos100002i/dmodel)PEpos,2i+1=cos(pos100002i/dmodel) PE_{pos,2i} = \sin\left(\frac{pos}{10000^{2i/d_{\text{model}}}}\right) \\ PE_{pos,2i+1} = \cos\left(\frac{pos}{10000^{2i/d_{\text{model}}}}\right) PEpos,2i=sin(100002i/dmodelpos)PEpos,2i+1=cos(100002i/dmodelpos)
sentence = “我 喜欢 自然语言 处理”
最大长度为 5 个词(pos = 0, 1, 2, 3, 4)
假设模型的嵌入维度 d_model = 4
因此每个位置会得到一个 4 维的位置编码向量
对于第一个块“我”,pos=0 的位置编码
维度 0 (i=0, sin):PE0,0=sin(0100002×0/4)=sin(0100000)=sin(0)=0
\text{维度 } 0\ (i=0,\ \sin): \quad
PE_{0,0} = \sin\left(\frac{0}{10000^{2 \times 0 / 4}}\right) = \sin\left(\frac{0}{10000^0}\right) = \sin(0) = 0
维度 0 (i=0, sin):PE0,0=sin(100002×0/40)=sin(1000000)=sin(0)=0
维度 1 (i=0, cos):PE0,1=cos(0100002×0/4)=cos(0)=1 \text{维度 } 1\ (i=0,\ \cos): \quad PE_{0,1} = \cos\left(\frac{0}{10000^{2 \times 0 / 4}}\right) = \cos(0) = 1 维度 1 (i=0, cos):PE0,1=cos(100002×0/40)=cos(0)=1
维度 2 (i=1, sin):PE0,2=sin(0100002×1/4)=sin(0100000.5)=sin(0)=0 \text{维度 } 2\ (i=1,\ \sin): \quad PE_{0,2} = \sin\left(\frac{0}{10000^{2 \times 1 / 4}}\right) = \sin\left(\frac{0}{10000^{0.5}}\right) = \sin(0) = 0 维度 2 (i=1, sin):PE0,2=sin(100002×1/40)=sin(100000.50)=sin(0)=0
维度 3 (i=1, cos):PE0,3=cos(0100000.5)=cos(0)=1
\text{维度 } 3\ (i=1,\ \cos): \quad
PE_{0,3} = \cos\left(\frac{0}{10000^{0.5}}\right) = \cos(0) = 1
维度 3 (i=1, cos):PE0,3=cos(100000.50)=cos(0)=1
所以pos=0 的位置,其位置编码为(0,1,0,1)
说明
位置编码的值完全由单词或标记在序列中的位置决定,而且这种决定关系是预先定义好的,不会随训练而改变。换句话说,不管输入序列如何,不管模型训练到什么阶段,序列中第一个位置(位置1)的位置编码总是相同的,因为它是通过固定的函数(正弦和余弦函数)和固定的位置索引(1)计算得到的。
这意味着,与嵌入向量不同,位置编码并不是模型训练过程中学习得到的参数。它们是根据每个位置的索引,通过预定义的数学公式计算得到的,然后加到对应位置的嵌入向量上,以此来提供序列中各位置的相对和绝对位置信息。这样做使得Transformer模型能够理解序列中不同元素的顺序,即使模型的自注意力机制本身并不关注输入元素的顺序。
Q:为什么要除以100002idmodel{10000}\tfrac{2i}{{d}_{model}}10000dmodel2i
- 10000 是一个超参数,用于控制频率的规模。它决定了在高维度时,频率会变得非常大,而在低维度时,频率会保持较小。10000 的选择是基于实验结果的经验值,目的是确保在较低维度时编码变化较慢,而在较高维度时编码变化较快。
- 2i和dmodel{2i}和{{d}_{model}}2i和dmodel表示不同维度对应不同的频率,
i是维度索引,d_model是词向量的维度。通过这个公式,我们使得 每个维度的编码频率不同,从而使得每个位置(词)在不同维度上都能有不同的表示。
频率与位置的关系
- 较低维度的频率(低频):对于位置 pos,在较低维度上,100002idmodel{10000}\tfrac{2i}{{d}_{model}}10000dmodel2i的分母相对较小,导致编码的变化较慢(低频)。这帮助模型捕捉长距离的位置依赖关系。
- 较高维度的频率(高频):随着 i的增加,分母变大(因为 100002idmodel{10000}\tfrac{2i}{{d}_{model}}10000dmodel2i 增大),导致频率变高,从而使得编码的变化更快。这使得模型能够更细致地捕捉短距离的位置关系。
2.2编码器(Encoder)

每个编码器层主要包含以下两个子层:
- 自注意力机制(Self-Attention)子层:允许模型在处理序列的每个位置时,考虑序列中的所有位置,以捕捉不同单词之间的内部关系。自注意力机制可以并行处理所有位置,从而大大提高了计算效率。
- 前馈神经网络(Feed-Forward Neural Network, FFN)子层:是一个简单的全连接神经网络,对自注意力层的输出进行进一步的变换。这个网络对每个位置的输出是独立的,这意味着相同的全连接网络被应用于不同位置的输出。
每个子层周围还有一个残差连接(Residual Connection),随后是层归一化(Layer Normalization)。残差连接帮助避免了在深度模型中常见的梯度消失问题。
2.2.1自注意力机制
核心原理
自注意力的目标是让每个位置的表示能够根据整个序列中其他位置的信息进行加权融合,从而捕获实体之间的相互关系。
自注意力机制通过引入查询向量(Query)、键向量(Key)、值向量(Value) 概念来实现序列中各元素之间的信息交互和依赖建模。
-
Q:Query
表示当前查询者的位置,用来发出问题:“我想知道对我来说谁重要”。
-
K:Key
表示被查询者的身份,是所有位置给出的“介绍信”或“标签”,告诉别人自己是个啥玩意。
-
V:Value
表示被查询者实际信息,也就是一旦你决定“关注我了”,我就把这份信息给你。
实现过程
自注意力机制通过计算输入数据中每个位置与其他位置的相关性,来调整每个位置的信息表示。
输入序列
输入是一个序列,如词向量序列,假设:
X=(x1,x2,…,xn)∈Rn×d
X = (x_1, x_2, \dots, x_n) \in \mathbb{R}^{n \times d}
X=(x1,x2,…,xn)∈Rn×d
是 nnn 个输入,ddd 是输入维度,则自注意力的目的是捕获 nnn 个实体之间的关系。
词语关系
it代表的是animal还是street呢,对我们来说简单,但对机器来说是很难判断的。self-attention就能够让机器把it和animal联系起来。

线性变换
自注意力机制依赖于三个核心概念:查询向量Query、键向量Key、值向量Value。他们对输入 XXX 进行三次线性变换,得到三个矩阵。
查询向量
Q = Query, 是自注意力机制中的“询问者”。每个输入都会生成一个查询向量,表示当前词的需求。
- 作用:用于与键向量计算相似度(通过点积方式),确定当前词与其他词的相关性。
- 生成方式:通过一个权重矩阵将输入数据(如词向量)映射到查询空间。
Q=XWq Q=X W_q Q=XWq
WqW_qWq 是可学习权重矩阵,维度为 d×dkd \times d_kd×dk,dkd_kdk是超参数,表示查询向量的维度。

键向量
**K = **Key,表示其他词的信息,供查询向量匹配。每个输入都会生成一个键向量,表示其能够提供的信息内容。
- 作用:与查询向量计算点积,生成注意力权重。点积越大,表示它们之间的相关性越强。
- 生成方式:通过一个权重矩阵将输入数据(如词向量)映射到键空间。
K=XWk K=X W_k K=XWk
WkW_kWk 是可学习权重矩阵,维度为 d×dkd \times d_kd×dk,dkd_kdk是超参数,表示键向量的维度。
值向量
V = Value, 值向量包含了每个输入实际的信息内容,相关性决定了信息被聚焦的程度。
- 作用:使用值向量基于注意力得分进行加权求和,生成最终的输出表示。
- 生成方式:通过一个权重矩阵将输入数据(如词向量)映射到值空间。
V=XWv V=X W_v V=XWv
WvW_vWv 是可学习权重矩阵,维度为 d×dvd \times d_vd×dv,dvd_vdv是超参数,表示值向量的维度。
注意力得分

使用点积来计算查询向量和键向量之间的相似度,除以缩放因子 dk\sqrt{d_k}dk 来避免数值过大,使得梯度稳定更新。得到注意力得分矩阵:
Attention(Q,K)=QKTdk
\text{Attention}(Q, K) = \frac{QK^T}{\sqrt{d_k}}
Attention(Q,K)=dkQKT
为什么除以d_k?缩放是害怕梯度消失或者爆炸吗?
缩放操作QKTdk \frac{QK^T}{\sqrt{d_k}} dkQKT 的主要目的确实是防止 softmax 的梯度问题,但它不是直接防“梯度消失/爆炸”在反向传播中,而是通过稳定 softmax 的输入分布来间接避免这些问题。
| 输入值(logits) | softmax 输出 | 梯度 |
|---|---|---|
| [1, 2] | [0.27, 0.73] | ✅ 梯度正常 |
| [10, 20] | [0.000, 1.000] | ❌ 梯度几乎为 0 |
当输入差异很大时,softmax 会趋于 one-hot 分布(几乎全给最大值),其他位置接近 0。
这意味着:
大多数位置的梯度 ≈ 0 → 梯度消失
模型无法学习到“细微差别”
注意力机制变得“非黑即白”,不够平滑
归一化
为了将注意力得分转换为概率分布,需按行对得分矩阵进行 softmaxsoftmaxsoftmax 操作,确保每行的和为 1,得到的矩阵表示每个元素对其他元素的注意力权重。是的,包括自己。
Attention Weight=softmax(QKTdk)
\text{Attention Weight} = \text{softmax} \left( \frac{QK^T}{\sqrt{d_k}} \right)
Attention Weight=softmax(dkQKT)
具体到每行的公式如下:
α^1,i=exp(α1,i)∑jexp(α1,j)
\hat{\alpha}_{1,i} = \frac{\exp(\alpha_{1,i})}{\sum_j \exp(\alpha_{1,j})}
α^1,i=∑jexp(α1,j)exp(α1,i)
- α1,i\alpha_{1,i}α1,i :第 111 个词语和第 iii 个词语之间的原始注意力得分。
- α^1,i\hat{\alpha}_{1,i}α^1,i :经过归一化后的注意力得分。
权求和
通过将注意力权重矩阵与值矩阵 VVV 相乘,得到加权的值表示。
Output=Attention Weight×V=softmax(QKTdk)×V
\text{Output} =\text{Attention Weight} \times V = \text{softmax} \left( \frac{QK^T}{\sqrt{d_k}} \right) \times V
Output=Attention Weight×V=softmax(dkQKT)×V
具体计算示意图如下:
![]() |
|---|
| Q和K计算相似度后,经 softmaxsoftmaxsoftmax 得到注意力,再乘V,最后相加得到包含注意力的输出 |
输出
最终得到的输出是一个维度为 n×dvn \times d_vn×dv 的新矩阵,其中每个元素的表示都被加权了。
本质:通过 Query 与所有 Key 计算相似性,得到原始分数;经 softmax 归一化为概率分布(即注意力权重);再用这些权重对对应的 Value 向量进行加权求和,最终生成每个位置富含上下文信息的输出表示。
2.2.2多头注意力机制
Multi-Head Attention,多头注意力机制,是对自注意力机制的扩展。
基本概念
多头注意力机制的核心思想是,将注意力机制中的 Q、K、VQ、K、VQ、K、V 分成多个头,每个头计算出独立的注意力结果,然后将所有头的输出拼接起来,最后通过一个线性变换得到最终的输出。

注:多头注意力机制通常先将词向量映射为Q、K、V,然后再分成多个头。
多头注意力是(自)注意力机制的一个扩展,它允许模型同时从不同的表示子空间中获取信息。在自注意力机制中,每个序列位置的查询(Q)、键(K)和值(V)向量通过一次线性变换获得,然后用于计算注意力分数和最终的输出。而在多头注意力中,这个过程被复制多次,每一份都有独立的权重矩阵(对应不同的“头”),允许模型在多个不同的表示空间中并行地学习信息。
- Z相比较X有了提升,通过Multi-Head Self-Attention,得到的Z’相比较Z又有了进一步提升
- 一般使用的是8头注意力机制
其流程如下:
- 分割头:在多头注意力中,原始的查询、键和值向量首先被分割成多个较小的向量,每个向量对应于一个“头”。这样,对于每个头,我们都有一组较小的Q、K、V向量。
- 独立的注意力计算:每个头独立地执行自注意力计算,包括通过Q和K计算注意力分数、应用softmax、以及使用这些分数加权V。因为每个头都有自己的一套权重矩阵,它们可以关注输入序列的不同部分,捕获不同类型的信息。
- 拼接和最终线性变换:所有头的输出向量随后被拼接起来,并通过另一个线性变换,以生成多头注意力层的最终输出。这一步整合了不同头捕获的各种信息。
代码
- 定义头数:决定将注意力分成几个头。在本例中,我们可以选择将其分成两个头,但这个数值可以根据需求调整。
- 初始化权重矩阵:对每个头,分别初始化Query、Key和Value的权重矩阵。
- 分头计算Query、Key、Value:对每个头,使用对应的权重矩阵和输入矩阵计算Query、Key、Value。
- 分头计算注意力得分和输出:对每个头,独立计算注意力得分,应用softmax,然后计算输出。
- 合并各头的输出:将所有头的输出拼接起来,形成一个更大的矩阵。
- 应用最终线性变换:通常,我们还会有一个额外的权重矩阵用来对拼接后的输出进行变换,以便将其维度还原回原始输入的维度(如果需要的话)。
import torch
import torch.nn.functional as F
# 假设
dim = 512
head_num = 8
d_k = dim // head_num
n = 10 # 序列长度
embedding_out = torch.randn(n, dim) # 输入
# 标准做法:用一个大矩阵,再拆分
W_Q = torch.randn(dim, dim) # (512, 512)
W_K = torch.randn(dim, dim)
W_V = torch.randn(dim, dim)
Q = torch.matmul(embedding_out, W_Q) # (n, 512)
K = torch.matmul(embedding_out, W_K)
V = torch.matmul(embedding_out, W_V)
# 拆分为多头: (n, head_num, d_k)
Q = Q.view(n, head_num, d_k)
K = K.view(n, head_num, d_k)
V = V.view(n, head_num, d_k)
# 转置以便计算: (head_num, n, d_k)
Q = Q.transpose(0, 1)
K = K.transpose(0, 1)
V = V.transpose(0, 1)
# 计算注意力
attn_scores = torch.matmul(Q, K.transpose(-2, -1)) / (d_k ** 0.5) # (8, n, n)
attn_weights = F.softmax(attn_scores, dim=-1)
output_per_head = torch.matmul(attn_weights, V) # (8, n, d_k)
# 合并多头
output = output_per_head.transpose(0, 1).contiguous().view(n, -1) # (n, 512)
print(output.shape) # torch.Size([10, 512])
2.2.3 ADD&Norm
残差连接(Add)
残差连接简单来说就是将子层的输入直接加到其输出上。这种机制可以帮助缓解深层网络中的梯度消失问题,因为它允许梯度直接流过网络的跨层连接。在具体实现上,每个子层(如自注意力层或前馈神经网络层)的输出在进行下一步处理前,都会先与该子层的输入进行逐元素相加。
层归一化(Norm)
归一化是深度学习中常用的技术,用于稳定和加速神经网络的训练。Transformer使用的是层归一化(Layer Normalization),它是在每个子层的输出和输入相加后进行的。层归一化会对每个样本的所有特征进行归一化,确保平均值为0,方差为1。这有助于减少不同层输出分布的差异,从而使训练过程更加稳定。
2.2.4 前馈神经网络
前馈神经网络通常由两个线性变换组成,这两个变换之间有一个非线性激活函数,比如ReLU(Rectified Linear Unit)或GELU(Gaussian Error Linear Unit)。具体来说,FFN可以表示为如下形式:
-
第一层变换:将自注意力层的输出通过一个线性层(全连接层)变换,增加模型的非线性表示能力。
FFN(x)=max(0,xW1+b1)W2+b2 \text{FFN}(x)=max(0, xW_1+b_1)W_2+b_2 FFN(x)=max(0,xW1+b1)W2+b2
其中,W_1和W_2是权重矩阵,b_1和 b_2是偏置项,{max}(0, dot)表示ReLU激活函数。 -
激活函数:在两个线性变换之间,使用ReLU或类似的非线性激活函数增加模型处理复杂非线性关系的能力。
-
第二层变换:经过激活函数处理的数据再次通过一个线性层变换,以生成最终的输出。
第一层会将输入的向量升维,第二层将向量重新降维。这样子就可以学习到更加抽象的特征。
前馈层的主要作用:
- 增加非线性:通过引入非线性激活函数,前馈层使模型能够捕捉和建模输入数据中的复杂非线性关系。
- 扩展模型能力:虽然自注意力机制非常强大,能够捕捉序列内元素之间的依赖关系,但前馈层的加入进一步扩展了模型处理各种语言现象的能力,使模型更加强大和灵活。
- 独立处理每个位置:在前馈层中,对序列中每个位置的处理是独立的,这意味着同一个前馈网络被应用于序列中的每个位置,但每个位置的处理并不依赖于其他位置。这种设计有助于并行计算,提高模型的效率。
ADD&Norm
同上

6084

被折叠的 条评论
为什么被折叠?



