编程与 AI13 分钟阅读更新于 2026-08-03

前馈神经网络是什么:注意力之后如何加工每个位置的信息

理解 Transformer 编码器中的前馈网络,掌握两次线性变换、激活函数、逐位置计算和残差归一化之间的关系,并看清它与多头注意力各自负责什么。

相关工具

注意力把信息带来,前馈网络负责加工

在前几篇里,我们看到多头注意力会让一个位置读取序列中其他位置的信息。它解决的是“当前位置应该从哪里取上下文”。但信息取回来之后,还需要经过进一步的变换,才能形成更适合下一层使用的表示。Transformer 编码器中的前馈神经网络,就是承担这一步工作的组件。

可以把一层 Transformer 想成两个连续的动作:先在不同位置之间交换信息,再在每个位置内部加工信息。多头注意力负责前者,前馈网络负责后者。两者都处理向量,但关注范围不同。

前馈网络没有再次建立位置之间的连接。它看到的是某个位置已经融合上下文后的向量,然后用一套非线性变换把这个向量重新表达一遍。

Transformer 中多头注意力和前馈网络分工的示意图
多头注意力与前馈网络的分工

注意力负责位置之间的信息交换,前馈网络使用相同结构独立加工每个位置的表示。

前馈网络的基本结构只有两次线性变换

经典 Transformer 中的前馈网络通常写成 FFN(x)=max(0,xW_1+b_1)W_2+b_2。这里的 max(0,·) 是 ReLU 激活函数。实际模型也常使用 GELU 等其他激活函数,但整体结构仍然是“线性变换—激活—线性变换”。

第一层线性变换把模型维度 d_model 扩展到更大的中间维度 d_ff,激活函数在其中加入非线性,第二层线性变换再把维度映射回 d_model。它不是单纯把向量放大再缩小,而是在更宽的空间里重新组织特征。

如果只有线性变换,无论叠加多少层,整体仍然可以合并成一个线性变换,表达能力会受到限制。激活函数让不同输入区域可以采用不同的变换方式,这正是前馈网络能够加工复杂特征的关键。

Transformer 前馈网络从输入到输出的计算结构图
前馈网络的两次线性变换

输入先从 d_model 扩展到 d_ff,经过 ReLU 或 GELU 后,再映射回 d_model。

为什么要先扩大维度

假设模型主维度是 d_model,前馈网络把它扩展到 d_ff。这个中间空间通常比 d_model 更宽,给模型提供更多通道来组合和筛选特征。可以把它理解为先把一张小尺寸的特征表展开,再在更大的工作区里做非线性加工。

维度扩大并不等于每个特征都变得更重要。第一层线性变换会把原来的特征重新投影到多个方向,激活函数再决定哪些方向被保留、哪些方向被压低。第二层则把这些中间结果重新压回模型维度,供后续残差连接和下一层使用。

d_ff 越大,前馈网络通常拥有更强的单位置变换能力,同时参数量和计算量也会增加。模型设计需要在表达能力、速度和内存之间做平衡。

激活函数让变换不再是一条直线

ReLU 的形式是 max(0,x),小于 0 的值被置为 0,大于 0 的值保留。它简单、计算快,也容易理解。GELU 则采用更平滑的方式决定一个值保留多少,许多现代语言模型会选择 GELU 或与之相近的激活函数。

激活函数的作用不是给结果增加一个固定偏移,而是根据中间特征的数值进行选择。相似的输入可能进入相近的变换区域,不同输入则可能被激活出不同的特征组合。这样,前馈网络才能做比线性映射更细致的判断。

理解时不必先陷入每个激活函数的精确曲线。先抓住一点:两次线性变换之间必须有非线性,否则前馈网络的多层表达不会真正增加。

逐位置计算是什么意思

“逐位置”指的是,序列中每个位置都单独经过同一个前馈网络。假设输入表示为 B×L×d_model,前馈网络会对最后一个维度做变换,批次维度 B 和序列长度 L 仍然保留。位置 1、位置 2 和位置 3 互不交换信息。

这里的“同一个”很重要:同一层中的所有位置共享 W_1、b_1、W_2、b_2。模型不会为句首、句中和句尾各复制一套参数。共享参数让前馈网络学习一种适用于所有位置的特征加工规则,也使计算可以批量并行。

注意力和前馈网络的差别由此更加清楚。注意力的参数也可以共享,但它会通过 QKᵀ 建立位置之间的交互;前馈网络只作用于每个位置自身的向量,不会读取其他位置的向量。

前馈网络为什么还需要残差连接

在编码器层中,多头注意力和前馈网络通常都配有残差连接与层归一化。残差连接会把子层输入直接加回子层输出,例如 x+FFN(x)。这样做可以保留原有信息,也为梯度在多层之间传播提供更直接的路径。

如果前馈网络某一层暂时没有学到有用的变换,残差路径仍然可以让输入继续向后传递。随着训练进行,网络再逐渐学习应该在原表示上补充哪些信息。

层归一化则帮助控制表示的数值范围和分布,使不同层之间的训练更稳定。具体是先归一化还是后归一化,会随架构实现而变化,但“前馈变换需要和残差、归一化一起理解”这一点保持不变。

前馈网络并不是简单的记忆仓库

在一些解释中,前馈网络常被描述为存放知识的地方。这个说法可以帮助建立直觉,但不能把它理解得过于绝对。前馈层确实拥有大量参数,能够学习输入特征到输出特征的复杂变换;但具体信息如何分布在注意力层、前馈层和多层组合中,通常不是清晰的一对一存储。

更稳妥的理解是:注意力把相关上下文送到当前位置,前馈网络根据当前位置当前拥有的内容和上下文,完成一次非线性特征变换。它可能参与知识关联,也可能参与词义、句法和任务模式的加工。

把它只看成记忆仓库,容易忽略它最基本的计算作用;把它只看成普通全连接层,又容易低估它在每个位置上反复加工表示的价值。

编码器一层是怎样串起来的

加入词嵌入和位置编码后,表示先进入多头自注意力。注意力输出经过残差连接和层归一化,再进入前馈网络。前馈网络完成两次线性变换和激活后,再经过第二次残差连接和层归一化,得到这一层的输出。

这条顺序解释了为什么前馈网络不能孤立地看。它接收的不是最初的词嵌入,而是已经经过位置编码和上下文交换的表示。它的输出也不是最终答案,而是下一层继续交换和加工的输入。

编码器堆叠多层后,同一个位置会反复经历“读取上下文—独立变换”的循环。浅层可能更容易形成局部关系,深层则可以在多轮信息交互后表达更复杂的语义结构。

Transformer 编码器层从输入到输出的模块顺序图
Transformer 编码器层的顺序

输入先经过多头注意力,再经过残差归一化、前馈网络和第二次残差归一化。

前馈网络和卷积、循环结构有什么不同

前馈网络本身不沿时间方向循环,也不使用邻域窗口。它对每个位置独立应用同一个变换,位置之间的交互由同一层中的注意力完成。把这两个模块分开后,Transformer 既能全局交换信息,又能保持每个位置的局部非线性加工。

卷积更偏向固定范围的局部交互,循环结构依赖前一步状态传递信息;前馈网络则不负责建立位置关系。它的优势不是替代所有结构,而是和注意力形成互补。

因此,看到“逐位置前馈网络”时,不要把它理解成只处理某个孤立词。它处理的是已经包含上下文的向量,只是这一阶段不再主动访问其他位置。

用形状检查前馈网络是否完整

设输入为 B×L×d_model。第一层权重可以看成 d_model×d_ff,经过线性变换后得到 B×L×d_ff;激活函数不改变形状;第二层权重把最后一维从 d_ff 映射回 d_model,输出回到 B×L×d_model。

如果第二层没有把维度映射回 d_model,就无法顺利和原输入做残差相加。若把序列长度 L 错当成需要变换的维度,也会破坏逐位置计算的含义。检查时重点看最后一维,而不是把整个三维张量拆成许多互不相关的小块。

学习公式时,可以先记住这一条形状链:d_model → d_ff → d_model。再补上激活函数、残差连接和归一化,前馈网络在编码器中的位置就清楚了。

前馈网络的四个检查点
步骤 1
扩大维度

第一层把最后一维从 d_model 映射到 d_ff。

步骤 2
加入非线性

在线性变换之间使用 ReLU、GELU 等激活函数。

步骤 3
逐位置共享

所有位置使用同一套参数,但彼此不交换向量。

步骤 4
恢复主维度

第二层回到 d_model,才能接入残差连接。

把前馈网络放回 Transformer 的整体理解

Transformer 的一层并不是只有注意力。位置编码让表示带上顺序,多头注意力让位置之间交换信息,前馈网络在每个位置内部做非线性加工,残差连接和层归一化让这些操作能够稳定堆叠。每个模块都解决一个不同的问题。

从阅读 相关的结构图到自己画出编码器层,最值得保留的主线是:输入先获得位置,再进行全局交互,随后进行逐位置变换。只要这条主线不乱,具体公式、维度和实现细节就有地方可放。

接下来继续学习层归一化和残差连接,会看到 Transformer 如何把多个子层组织成可训练、可堆叠的深层结构。它们不是装饰性的辅助模块,而是让注意力和前馈网络真正协同工作的基础。

常见问题

前馈网络会不会让不同位置互相通信?

标准的逐位置前馈网络不会主动读取其他位置,它对每个位置独立应用同一套变换。位置之间的通信主要由注意力完成。

为什么前馈网络要扩大后再缩小维度?

更宽的中间空间可以容纳更多特征组合,激活函数在其中加入非线性,第二次线性变换再把结果恢复到模型主维度。

前馈网络和全连接层是一回事吗?

它由全连接或线性层组成,但 Transformer 中的前馈网络通常特指两次线性变换加激活函数,并且按位置独立、共享参数地应用。