在了解 机器学习算法 时,很少有概念像前馈神经网络(FFNN)一样基础。如果您曾经构建过第一个神经网络,很大概率就是一个前馈网络。它几乎无处不在——从 简单的分类问题 到为深层架构中的各层提供动力。
首先让我向您展示在更广阔的图景中,前馈神经网络处于什么位置:
在本教程中,我将解释什么是前馈神经网络、它是如何演化而来以及为何至今仍然重要,并结合一些真实案例。
什么是前馈神经网络?
直观地说,描述这种网络架构的最佳方式是 “数据只向前流动,没有回路”。
从本质上讲,FFNN 以单一方向处理数据:从输入到输出。没有回传、没有递归、没有环( 反向传播 除外,我们稍后会讲)。
当我最初学习这一概念时,最能帮助我的心智图像是工厂里的传送带。
为什么呢?
因为流程中的每一步(或网络中的每一层)都会在传递给下一步之前,对输入做一件简单的事情。
其工作方式如下:
输入进入第一层(输入层)。
通过权重与偏置进行变换,并经过激活函数。
这一过程会继续经过一个或多个 隐藏层 。
最后,输出层给出预测。
在展示这种网络架构长什么样之前,我想先澄清一个常见误解:
“ 前馈神经网络与 MLP 是一回事。”
要澄清这一误解,我们需要回顾一下深度学习的早期历史。
深度学习的早期历史
感知机: 最早从 感知机 开始,这是 Frank Rosenblatt 于 1950 年代提出的。它是一个单层二分类器,虽然无法解决所有问题(如 XOR),但为神经网络奠定了基础。
通俗地说,感知机的工作流程如下:
输入 :每个输入(如 x_1、x_2 等)都有一个对应的权重(w_1、w_2 等)。
加权求和 :输入与其权重相乘后相加,再加上偏置项: z = w 1 * x 1 + w 2 * x 2 + ... + b 。
激活 :结果通过阶跃函数(激活函数)。若值高于阈值,则输出 1;否则输出 0。
本质上,感知机是一个线性分类器,只能画出直线(或超平面)决策边界。一方面,感知机的优点在于非常简单且富有美感(受生物学启发),并且计算代价低。另一方面,它无法解决非线性可分的问题,如 XOR 问题。
多层感知机(MLP): 快进到 1980 年代,研究者发现,如果将多个感知机堆叠并加入非线性激活函数,就能解决更复杂的问题。这种结构被称为 多层感知机 。
其工作方式如下:
输入层 :接收数据集中的原始特征。
隐藏层 :一个或多个感知机层应用变换。每个神经元执行 z = w*x + b ,并通过 非线性激活函数 (如 sigmoid、tanh 等)。
输出层 :最终一层产生最终预测(例如类别概率、回归值)。
加入这些 非线性激活 至关重要。没有它们,层与层的堆叠最终会退化为一次线性变换;有了它们,MLP 就能表示高度复杂的非线性函数。
这引出了神经网络理论中最著名的结果之一: 通用逼近定理。
该定理指出:只要具有非线性激活函数并拥有足够的神经元,即使只有一个隐藏层的神经网络,也能在有界域上逼近任意连续函数。
深度学习时代: 进入 2010 年代,我们迈入了 深度学习时代 。随着 GPU 与大数据的出现,FFNN 演化为更深更强的架构,成为 CNN、RNN 与 Transformers 的基础,这基本上就是我们当下所处的位置。
回到最初的误解,我们现在可以明确:
前馈神经网络(FFNN) :任意一种数据单向流动(输入 → 隐藏 → 输出)、无回路的神经网络的通称。
多层感知机(MLP) :一种 特定类型 的 FFN,且 至少包含一个隐藏层 (由具备权重、偏置和激活的神经元构成)。
换言之, 所有 MLP 都是 FFNN,但并非所有 FFNN 都是 MLP。 这是一个非常重要的要点。另一个常见误解与单层感知机(即仅有输入到输出)有关。
单层感知机是 FFNN,但不是 MLP!只有当我们加入了隐藏层,它才成为 MLP。
这一区分很重要,因为 MLP 具备 通用函数逼近 能力(只要有足够的隐藏单元和非线性激活函数),而简单的单层感知机在可表达性上是受限的。
前馈神经网络的架构
从上一节我们已经对 FFNN 有了很多了解,但简单来说,它可以被看作是 一串简单变换的堆叠。 构成 FFNN 的组件很多,下面我们更详细地探究,特别是 MLP 结构。
在 MLP 中,有三类层:输入层、隐藏层和输出层,我们之前已简要提及。
在我们更详细地探讨这些层时,请参考上图。
输入层
这是网络的入口。此处每个神经元代表 数据集中的一个特征 。重要的是,输入层 不 进行任何计算——它只是在向前传递原始数值。在我们的示例中,输入层只有两个神经元,这意味着数据集包含两个特征(或我们仅考虑两个特征)。
隐藏层
这里 才是实际计算发生的地方。我们有两个隐藏层,每层包含四个神经元。隐藏层中的每个神经元会做三件事:
加权求和: 每个输入乘以一个权重,然后相加。
偏置: 加入一个常数偏置,以便灵活地平移函数。
激活函数: 应用 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 而不是 a l-1 。下一步是 激活步骤 。为更严谨地表述,我们可以将权重与偏置写为:
反向传播
当我们得到输出后,如何告诉网络结果对不对?更进一步,如何让网络在既定任务上变得更好?这就是 反向传播 登场的地方。可以把它看作网络的反馈系统,它告知模型偏离了多少以及如何调整。可分解为以下步骤:
比较预测 :查看模型的预测(ŷ)与真实答案(y)。
计算误差 :使用损失函数衡量预测 有多错 ,例如 MSE。
反向传播(链式法则) :计算相对于所有偏置和权重的梯度。 ∂L/∂w,∂L/∂b 。
梯度下降更新 :使用下面的规则更新相应参数以降低损失:
其中, η 为学习率,用于控制每次更新时参数变化的幅度。
经过多轮上述过程,网络会逐步学习并提升任务表现。
为更清晰起见,我们一起走过一个很小的示例。假设我们有:
输入:x = 2
目标输出:y = 4
预测:ŷ = 3
现在按照步骤来:
比较预测: ŷ = 3,y = 4
误差: 在这个例子中,我们使用 MSE: L=(y−y^ ) 2 =(4−3 ) 2 =1
反向传播: 网络使用导数计算出每个权重与偏置对该误差的贡献,然后使用梯度下降更新步骤来更新各个参数。
用 PyTorch 编写前馈神经网络
我们已经覆盖了构建 FFNN(具体来说是 MLP)所需的数学基础。接下来,我们将用 PyTorch 来实现。
多层感知机
import torch
import torch. nn as nn
import torch. optim as optim
X, y = dataset
model = nn. Sequential(
nn. Linear( 2 , 4 ) ,
nn. ReLU( ) ,
nn. Linear( 4 , 4 ) ,
nn. ReLU( ) ,
nn. Linear( 4 , 1 )
)
criterion = nn. MSELoss( )
optimizer = optim. SGD( model. parameters( ) , lr= 0.1 )
EPOCHS = 200
for epoch in range ( EPOCHS) :
outputs = model( X)
loss = criterion( outputs, y)
optimizer. zero_grad( )
loss. backward( )
optimizer. step( ) 技术支持
此时,您应当能够将上述 PyTorch 代码与我们之前推导的数学步骤一一对应。不过,您可能会对“epoch”有疑问。
一个 epoch(轮次) 是指整个训练数据集完整地通过神经网络一次。比如,我们有 1,000 个训练样本且 batch size = 100,那么当网络看过全部 1,000 张图像(即 10 个 batch)后,就完成了 1 个 epoch。 训练通常需要多个 epoch ,以便模型不断改进其权重。
卷积神经网络
我还想简要提及其他 FFNN,其中一个非常著名的是 卷积神经网络(CNN) 。
虽然 CNN 的末端也包含一个 MLP,但起始部分包含一些特殊的层,称为卷积层与池化层。先说卷积层,它们很关键,因为它们使用 滤波器 (或卷积核)一次只关注输入的一个小局部区域。
这在图像分类中特别有用,因为:
全连接层会将每个像素视为独立个体,忽略空间结构。
而卷积层可以在小块中检测边缘、纹理和形状——随着网络加深,再将它们组合为更复杂的模式。
除了卷积层,CNN 还使用 池化层 。
需要注意的是,池化层不学习参数,而是对特征图进行 降采样 ,使其更小、更易处理。
最常见的是 最大池化(Max Pooling) ,它从每个小区域(例如 2×2 窗口)中取最大值。
池化让网络更高效,也带来 平移不变性 (网络更关注特征是否存在,而非其精确位置)。
我们可以用 PyTorch 像这样编写一个 CNN:
class SimpleCNN ( nn. Module) :
def __init__ ( self) :
super ( ) . __init__( )
self. conv = nn. Conv2d( 1 , 8 , 3 )
self. pool = nn. MaxPool2d( 2 , 2 )
self. fc = nn. Linear( 8 * 13 * 13 , 10 )
def forward ( self, x) :
x = self. pool( torch. relu( self. conv( x) ) )
x = x. view( x. size( 0 ) , - 1 )
return self. fc( x) 技术支持
在上述代码中,我们创建了一个非常简单的 CNN,包含一个卷积层、一个池化层和一个线性层。
其他前馈神经网络的例子
我们已经覆盖了两个非常著名且重要的 FFNN 示例,但在各自领域中还有许多具有革命性的例子,例如:
Transformers : 每个块包含一个 MLP/FFN 部分(自注意力之后,“前馈层”会先扩展后收缩维度)。
视觉 Transformer(ViT) :将带有 FFNN 的 Transformer 模块应用于图像 patch。
自编码器 (基础型): 编码器与解码器都由 FFNN 构成。
推荐系统(基于 MLP): 例如用于排序与预测的 Wide & Deep 模型。
结语
希望您已经意识到 FFNN 在人工智能领域的重要性。没有它们,就不会有当今的深度学习格局。
接下来,我强烈建议您 掌握反向传播 ,并深入学习 激活函数 。由于这是深度学习的基础,我也推荐学习 用 PyTorch 进行深度学习 。
在了解 机器学习算法时,很少有概念像前馈神经网络(FFNN)一样基础。如果您曾经构建过第一个神经网络,很大概率就是一个前馈网络。它几乎无处不在——从简单的分类问题到为深层架构中的各层提供动力。
首先让我向您展示在更广阔的图景中,前馈神经网络处于什么位置:
在本教程中,我将解释什么是前馈神经网络、它是如何演化而来以及为何至今仍然重要,并结合一些真实案例。
什么是前馈神经网络?
直观地说,描述这种网络架构的最佳方式是“数据只向前流动,没有回路”。
从本质上讲,FFNN 以单一方向处理数据:从输入到输出。没有回传、没有递归、没有环(反向传播除外,我们稍后会讲)。
当我最初学习这一概念时,最能帮助我的心智图像是工厂里的传送带。
为什么呢?
因为流程中的每一步(或网络中的每一层)都会在传递给下一步之前,对输入做一件简单的事情。
其工作方式如下:
在展示这种网络架构长什么样之前,我想先澄清一个常见误解:
“前馈神经网络与 MLP 是一回事。”
要澄清这一误解,我们需要回顾一下深度学习的早期历史。
深度学习的早期历史
感知机:最早从感知机开始,这是 Frank Rosenblatt 于 1950 年代提出的。它是一个单层二分类器,虽然无法解决所有问题(如 XOR),但为神经网络奠定了基础。
通俗地说,感知机的工作流程如下:
本质上,感知机是一个线性分类器,只能画出直线(或超平面)决策边界。一方面,感知机的优点在于非常简单且富有美感(受生物学启发),并且计算代价低。另一方面,它无法解决非线性可分的问题,如 XOR 问题。
多层感知机(MLP):快进到 1980 年代,研究者发现,如果将多个感知机堆叠并加入非线性激活函数,就能解决更复杂的问题。这种结构被称为多层感知机。
其工作方式如下:
加入这些非线性激活至关重要。没有它们,层与层的堆叠最终会退化为一次线性变换;有了它们,MLP 就能表示高度复杂的非线性函数。
这引出了神经网络理论中最著名的结果之一:通用逼近定理。
该定理指出:只要具有非线性激活函数并拥有足够的神经元,即使只有一个隐藏层的神经网络,也能在有界域上逼近任意连续函数。
深度学习时代:进入 2010 年代,我们迈入了深度学习时代。随着 GPU 与大数据的出现,FFNN 演化为更深更强的架构,成为 CNN、RNN 与 Transformers 的基础,这基本上就是我们当下所处的位置。
回到最初的误解,我们现在可以明确:
换言之,所有 MLP 都是 FFNN,但并非所有 FFNN 都是 MLP。这是一个非常重要的要点。另一个常见误解与单层感知机(即仅有输入到输出)有关。
单层感知机是 FFNN,但不是 MLP!只有当我们加入了隐藏层,它才成为 MLP。
这一区分很重要,因为 MLP 具备通用函数逼近能力(只要有足够的隐藏单元和非线性激活函数),而简单的单层感知机在可表达性上是受限的。
前馈神经网络的架构
从上一节我们已经对 FFNN 有了很多了解,但简单来说,它可以被看作是一串简单变换的堆叠。构成 FFNN 的组件很多,下面我们更详细地探究,特别是 MLP 结构。
在 MLP 中,有三类层:输入层、隐藏层和输出层,我们之前已简要提及。
在我们更详细地探讨这些层时,请参考上图。
输入层
这是网络的入口。此处每个神经元代表数据集中的一个特征。重要的是,输入层不进行任何计算——它只是在向前传递原始数值。在我们的示例中,输入层只有两个神经元,这意味着数据集包含两个特征(或我们仅考虑两个特征)。
隐藏层
这里 才是实际计算发生的地方。我们有两个隐藏层,每层包含四个神经元。隐藏层中的每个神经元会做三件事:
输出层
输出层产生最终预测,其设计取决于我们要解决的问题:
供您参考,下图展示了 FFNN 和更广义深度学习中常用的九种激活函数的形状。
在继续之前,还需注意:前一层中的每个神经元会连接到后一层中的每个神经元(因此称为“全连接”)。
回到我们的示例:
参数量 = (2·4+4)+(4·4+4)+(4·1+1)=12+20+5=37
每一对括号表示相邻两层之间的参数个数,即前一层与当前层的神经元数量相乘后,再加上偏置的数量(即当前层神经元数量)。请尝试在其他神经网络示例上进行类似计算以加深理解!
训练前馈神经网络
在深度学习中,训练分为两个步骤:前向传播与反向传播。简言之,前向传播给出预测,而反向传播则是我们如何从错误中学习。
前向传播
目前为止我们所覆盖的内容,都属于前向传播。概括来说,当数据流经 MLP 时,每一层都执行相同的两个步骤,可用如下公式表示:
其中,z 是将前一层的输出与当前层的权重相乘并加上偏置后的结果,也称为线性步骤。
如果前一层是输入层,那么这里就是x 而不是 al-1。下一步是激活步骤。为更严谨地表述,我们可以将权重与偏置写为:
反向传播
当我们得到输出后,如何告诉网络结果对不对?更进一步,如何让网络在既定任务上变得更好?这就是反向传播登场的地方。可以把它看作网络的反馈系统,它告知模型偏离了多少以及如何调整。可分解为以下步骤:
其中,η为学习率,用于控制每次更新时参数变化的幅度。
经过多轮上述过程,网络会逐步学习并提升任务表现。
为更清晰起见,我们一起走过一个很小的示例。假设我们有:
现在按照步骤来:
用 PyTorch 编写前馈神经网络
我们已经覆盖了构建 FFNN(具体来说是 MLP)所需的数学基础。接下来,我们将用PyTorch 来实现。
多层感知机
此时,您应当能够将上述 PyTorch 代码与我们之前推导的数学步骤一一对应。不过,您可能会对“epoch”有疑问。
一个epoch(轮次)是指整个训练数据集完整地通过神经网络一次。比如,我们有 1,000 个训练样本且 batch size = 100,那么当网络看过全部 1,000 张图像(即 10 个 batch)后,就完成了 1 个 epoch。训练通常需要多个 epoch,以便模型不断改进其权重。
卷积神经网络
我还想简要提及其他 FFNN,其中一个非常著名的是卷积神经网络(CNN)。
虽然 CNN 的末端也包含一个 MLP,但起始部分包含一些特殊的层,称为卷积层与池化层。先说卷积层,它们很关键,因为它们使用滤波器(或卷积核)一次只关注输入的一个小局部区域。
这在图像分类中特别有用,因为:
除了卷积层,CNN 还使用池化层。
需要注意的是,池化层不学习参数,而是对特征图进行降采样,使其更小、更易处理。
我们可以用 PyTorch 像这样编写一个 CNN:
在上述代码中,我们创建了一个非常简单的 CNN,包含一个卷积层、一个池化层和一个线性层。
其他前馈神经网络的例子
我们已经覆盖了两个非常著名且重要的 FFNN 示例,但在各自领域中还有许多具有革命性的例子,例如:
结语
希望您已经意识到 FFNN 在人工智能领域的重要性。没有它们,就不会有当今的深度学习格局。
接下来,我强烈建议您掌握反向传播,并深入学习激活函数。由于这是深度学习的基础,我也推荐学习用 PyTorch 进行深度学习。