跳至主要内容

前馈神经网络详解:完整教程

前馈神经网络(FFNN)是深度学习的基石,广泛应用于图像识别、Transformers 和推荐系统。本教程完整讲解其架构、与 MLP 的区别、激活函数、反向传播、真实案例以及 PyTorch 实现。
· 11分钟 阅读

使用 AI 探索

在了解 机器学习算法时,很少有概念像前馈神经网络(FFNN)一样基础。如果您曾经构建过第一个神经网络,很大概率就是一个前馈网络。它几乎无处不在——从简单的分类问题到为深层架构中的各层提供动力。

首先让我向您展示在更广阔的图景中,前馈神经网络处于什么位置:

图示展示了前馈神经网络在 AI 体系中的位置。作者制图

在本教程中,我将解释什么是前馈神经网络、它是如何演化而来以及为何至今仍然重要,并结合一些真实案例。

什么是前馈神经网络?

直观地说,描述这种网络架构的最佳方式是“数据只向前流动,没有回路”。

从本质上讲,FFNN 以单一方向处理数据:从输入到输出。没有回传、没有递归、没有环(反向传播除外,我们稍后会讲)。

当我最初学习这一概念时,最能帮助我的心智图像是工厂里的传送带。

为什么呢?

因为流程中的每一步(或网络中的每一层)都会在传递给下一步之前,对输入做一件简单的事情。

其工作方式如下:

  1. 输入进入第一层(输入层)。
  2. 通过权重与偏置进行变换,并经过激活函数。
  3. 这一过程会继续经过一个或多个隐藏层。
  4. 最后,输出层给出预测。

在展示这种网络架构长什么样之前,我想先澄清一个常见误解:

“前馈神经网络与 MLP 是一回事。”

要澄清这一误解,我们需要回顾一下深度学习的早期历史。

深度学习的早期历史

感知机:最早从感知机开始,这是 Frank Rosenblatt 于 1950 年代提出的。它是一个单层二分类器,虽然无法解决所有问题(如 XOR),但为神经网络奠定了基础。

通俗地说,感知机的工作流程如下:

  1. 输入:每个输入(如 x_1、x_2 等)都有一个对应的权重(w_1、w_2 等)。
  2. 加权求和:输入与其权重相乘后相加,再加上偏置项: z = w1*x1 + w2*x2+ ... + b。
  3. 激活:结果通过阶跃函数(激活函数)。若值高于阈值,则输出 1;否则输出 0。

图示展示了单个感知机的内部工作原理。作者制图。

本质上,感知机是一个线性分类器,只能画出直线(或超平面)决策边界。一方面,感知机的优点在于非常简单且富有美感(受生物学启发),并且计算代价低。另一方面,它无法解决非线性可分的问题,如 XOR 问题。

多层感知机(MLP):快进到 1980 年代,研究者发现,如果将多个感知机堆叠并加入非线性激活函数,就能解决更复杂的问题。这种结构被称为多层感知机。

其工作方式如下:

  1. 输入层:接收数据集中的原始特征。
  2. 隐藏层:一个或多个感知机层应用变换。每个神经元执行z = w*x + b,并通过非线性激活函数(如 sigmoid、tanh 等)。
  3. 输出层:最终一层产生最终预测(例如类别概率、回归值)。

加入这些非线性激活至关重要。没有它们,层与层的堆叠最终会退化为一次线性变换;有了它们,MLP 就能表示高度复杂的非线性函数。

这引出了神经网络理论中最著名的结果之一:通用逼近定理。

线性与非线性边界对比。作者制图。

该定理指出:只要具有非线性激活函数并拥有足够的神经元,即使只有一个隐藏层的神经网络,也能在有界域上逼近任意连续函数。

深度学习时代:进入 2010 年代,我们迈入了深度学习时代。随着 GPU 与大数据的出现,FFNN 演化为更深更强的架构,成为 CNN、RNN 与 Transformers 的基础,这基本上就是我们当下所处的位置。

回到最初的误解,我们现在可以明确:

  • 前馈神经网络(FFNN):任意一种数据单向流动(输入 → 隐藏 → 输出)、无回路的神经网络的通称。
  • 多层感知机(MLP):一种特定类型的 FFN,且至少包含一个隐藏层(由具备权重、偏置和激活的神经元构成)。

换言之,所有 MLP 都是 FFNN,但并非所有 FFNN 都是 MLP。这是一个非常重要的要点。另一个常见误解与单层感知机(即仅有输入到输出)有关。

单层感知机是 FFNN,但不是 MLP!只有当我们加入了隐藏层,它才成为 MLP。

这一区分很重要,因为 MLP 具备通用函数逼近能力(只要有足够的隐藏单元和非线性激活函数),而简单的单层感知机在可表达性上是受限的。

前馈神经网络的架构

从上一节我们已经对 FFNN 有了很多了解,但简单来说,它可以被看作是一串简单变换的堆叠。构成 FFNN 的组件很多,下面我们更详细地探究,特别是 MLP 结构。

在 MLP 中,有三类层:输入层、隐藏层和输出层,我们之前已简要提及。

全连接前馈神经网络(MLP)的架构。作者制图。

在我们更详细地探讨这些层时,请参考上图。

输入层

这是网络的入口。此处每个神经元代表数据集中的一个特征。重要的是,输入层不进行任何计算——它只是在向前传递原始数值。在我们的示例中,输入层只有两个神经元,这意味着数据集包含两个特征(或我们仅考虑两个特征)。

隐藏层

这里 才是实际计算发生的地方。我们有两个隐藏层,每层包含四个神经元。隐藏层中的每个神经元会做三件事:

  1. 加权求和:每个输入乘以一个权重,然后相加。
  2. 偏置:加入一个常数偏置,以便灵活地平移函数。
  3. 激活函数:应用 ReLU、tanh 或 sigmoid 等非线性压缩函数。正是这一步使网络能够学习复杂的非线性模式。

输出层

输出层产生最终预测,其设计取决于我们要解决的问题:

  • 回归 问题,例如预测房价。此时输出层包含一个不带激活的神经元(线性)。为什么是线性?因为我们不想压缩数值,房价可以是任意实数。
  • 二分类 问题(是/否决策),如预测邮件是否为垃圾邮件。这里输出层为一个带 sigmoid 激活的神经元。为什么是 sigmoid?因为我们希望网络输出 0 到 1 之间的值(我们在预测概率)。
  • 多分类(3 类及以上),例如将图像分类为不同动物。输出层将对每个类别设一个神经元,并使用 softmax 激活。为什么是 softmax?因为它将原始分数转化为和为 1 的概率(例如:70% 猫、20% 狗、10% 马)。

供您参考,下图展示了 FFNN 和更广义深度学习中常用的九种激活函数的形状。

常见激活函数可视化。作者制图。

在继续之前,还需注意:前一层中的每个神经元会连接到后一层中的每个神经元(因此称为“全连接”)。

回到我们的示例:

参数量 = (2·4+4)+(4·4+4)+(4·1+1)=12+20+5=37

每一对括号表示相邻两层之间的参数个数,即前一层与当前层的神经元数量相乘后,再加上偏置的数量(即当前层神经元数量)。请尝试在其他神经网络示例上进行类似计算以加深理解!

训练前馈神经网络

在深度学习中,训练分为两个步骤:前向传播与反向传播。简言之,前向传播给出预测,而反向传播则是我们如何从错误中学习。

前向传播

目前为止我们所覆盖的内容,都属于前向传播。概括来说,当数据流经 MLP 时,每一层都执行相同的两个步骤,可用如下公式表示:

其中,z 是将前一层的输出与当前层的权重相乘并加上偏置后的结果,也称为线性步骤。

如果前一层是输入层,那么这里就是x 而不是 al-1。下一步是激活步骤。为更严谨地表述,我们可以将权重与偏置写为:

反向传播

当我们得到输出后,如何告诉网络结果对不对?更进一步,如何让网络在既定任务上变得更好?这就是反向传播登场的地方。可以把它看作网络的反馈系统,它告知模型偏离了多少以及如何调整。可分解为以下步骤:

  1. 比较预测:查看模型的预测(ŷ)与真实答案(y)。
  2. 计算误差:使用损失函数衡量预测有多错,例如 MSE。
  3. 反向传播(链式法则):计算相对于所有偏置和权重的梯度。∂L/∂w,∂L/∂b 。
  4. 梯度下降更新:使用下面的规则更新相应参数以降低损失:

其中,η为学习率,用于控制每次更新时参数变化的幅度。

梯度下降可视化——展示了每个 epoch 后损失函数如何下降。作者制图。

经过多轮上述过程,网络会逐步学习并提升任务表现。

为更清晰起见,我们一起走过一个很小的示例。假设我们有:

  • 输入:x = 2
  • 目标输出:y = 4
  • 预测:ŷ = 3

现在按照步骤来:

  1. 比较预测: ŷ = 3,y = 4
  2. 误差:在这个例子中,我们使用 MSE:L=(y−y^​)2=(4−3)2=1
  3. 反向传播:网络使用导数计算出每个权重与偏置对该误差的贡献,然后使用梯度下降更新步骤来更新各个参数。

用 PyTorch 编写前馈神经网络

我们已经覆盖了构建 FFNN(具体来说是 MLP)所需的数学基础。接下来,我们将用PyTorch 来实现。

多层感知机

# Imports we will be needing
import torch
import torch.nn as nn
import torch.optim as optim

X,y = dataset # Here will be our dataset 

# We have created a MLP here using nn.Sequential()
model = nn.Sequential(
    nn.Linear(2, 4),  # input layer → hidden layer (2 → 4)
    nn.ReLU(),        # relu activation function
    nn.Linear(4, 4), # hidden layer 1 → hidden layer 2 (4 → 4)
    nn.ReLU(), 
    nn.Linear(4, 1)   # hidden layer 2 → output (4 → 1)
)


criterion = nn.MSELoss()         # regression loss, i.e our loss function
optimizer = optim.SGD(model.parameters(), lr=0.1) # Optimizer using the Stochastic Gradient Descent

# Training Loop
EPOCHS = 200 # Number of epochs we will be training for
for epoch in range(EPOCHS):
    # Forward pass
    outputs = model(X)
    loss = criterion(outputs, y)

    # Backward pass
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

此时,您应当能够将上述 PyTorch 代码与我们之前推导的数学步骤一一对应。不过,您可能会对“epoch”有疑问。

一个epoch(轮次)是指整个训练数据集完整地通过神经网络一次。比如,我们有 1,000 个训练样本且 batch size = 100,那么当网络看过全部 1,000 张图像(即 10 个 batch)后,就完成了 1 个 epoch。训练通常需要多个 epoch,以便模型不断改进其权重。

卷积神经网络

我还想简要提及其他 FFNN,其中一个非常著名的是卷积神经网络(CNN)。

卷积神经网络示意图。图片来自 Mathworks - https://www.mathworks.com/discovery/convolutional-neural-network.html

虽然 CNN 的末端也包含一个 MLP,但起始部分包含一些特殊的层,称为卷积层与池化层。先说卷积层,它们很关键,因为它们使用滤波器(或卷积核)一次只关注输入的一个小局部区域。

这在图像分类中特别有用,因为:

  • 全连接层会将每个像素视为独立个体,忽略空间结构。
  • 而卷积层可以在小块中检测边缘、纹理和形状——随着网络加深,再将它们组合为更复杂的模式。

除了卷积层,CNN 还使用池化层。

需要注意的是,池化层不学习参数,而是对特征图进行降采样,使其更小、更易处理。

  • 最常见的是最大池化(Max Pooling),它从每个小区域(例如 2×2 窗口)中取最大值。
  • 池化让网络更高效,也带来平移不变性(网络更关注特征是否存在,而非其精确位置)。

我们可以用 PyTorch 像这样编写一个 CNN:

class SimpleCNN(nn.Module): # Define our model as a class
    def __init__(self):
        super().__init__()
        self.conv = nn.Conv2d(1, 8, 3)     # 1→8 channels, 3x3 kernel
        self.pool = nn.MaxPool2d(2, 2)
        self.fc   = nn.Linear(8*13*13, 10) # flatten → 10 classes

    def forward(self, x): # Forward propagation function 
        x = self.pool(torch.relu(self.conv(x)))
        x = x.view(x.size(0), -1)          # flatten
        return self.fc(x)

在上述代码中,我们创建了一个非常简单的 CNN,包含一个卷积层、一个池化层和一个线性层。

其他前馈神经网络的例子

我们已经覆盖了两个非常著名且重要的 FFNN 示例,但在各自领域中还有许多具有革命性的例子,例如:

  1. Transformers:每个块包含一个 MLP/FFN 部分(自注意力之后,“前馈层”会先扩展后收缩维度)。
  2. 视觉 Transformer(ViT):将带有 FFNN 的 Transformer 模块应用于图像 patch。
  3. 自编码器(基础型):编码器与解码器都由 FFNN 构成。
  4. 推荐系统(基于 MLP):例如用于排序与预测的 Wide & Deep 模型。

Transformer 架构。图片来自原始论文《Attention is all you need》。

结语

希望您已经意识到 FFNN 在人工智能领域的重要性。没有它们,就不会有当今的深度学习格局。

接下来,我强烈建议您掌握反向传播,并深入学习激活函数。由于这是深度学习的基础,我也推荐学习用 PyTorch 进行深度学习。

前馈神经网络常见问答

FFNN 与 MLP 是一回事吗?

不,它们并不相同,这是一种很常见的误解!FFNN 只表示数据前向流动。MLP 是一种至少包含一个隐藏层的 FFNN。

为什么要使用激活函数?

它们引入非线性。没有激活函数,多个层会表现得像一个大的线性层,网络就无法学习复杂模式。

FFNN 在现实中用于哪些场景?

应用无处不在:推荐系统、图像分类器(CNN)、Transformers 和自编码器都依赖它们。

如何在 PyTorch 中编写一个 FFNN?

我们可以堆叠 nn.Linear 层,加入 nn.ReLU 等激活函数,选择损失函数与优化器,并以前向 + 反向传播进行训练。

什么是反向传播?

一句话概括:这是网络学习的过程——将预测与目标比较、度量误差,并用梯度下降更新权重。

Vaibhav Mehra

作者

Vaibhav Mehra

主题