智能体在车联网中的应用:第13天 深度学习入门:前向传播与反向传播的数学本质与PyTorch/TensorFlow实践
本文深入解析多层感知机(MLP)的核心计算过程——前向传播与反向传播。前向传播通过输入数据的逐层加权计算和激活函数变换得到预测结果,反向传播则利用链式法则逆向计算参数梯度以优化网络。文章详细推导了单隐藏层MLP的数学原理,并通过PyTorch和TensorFlow/Keras双框架实践演示:使用PyTorch手动构建训练流程,展示梯度计算与参数更新;利用Keras高阶API快速实现模型定义与训练。
在人工智能的浪潮中,深度学习已成为推动技术变革的核心动力。无论是最新的国产D20 AI加速卡宣称支持千亿参数大模型部署,还是我们日常使用的图像识别、语音助手,其底层都离不开一个基础而强大的计算模型——多层感知机(MLP)。理解MLP,关键在于掌握其两个核心的生命周期:前向传播(Forward Propagation) 与 反向传播(Backpropagation)。本文将从数学原理入手,深入剖析这两个过程,并手把手教你使用PyTorch和TensorFlow构建你的第一个MLP模型,为你的深度学习之旅打下坚实基础。
1. 神经网络的计算核心:前向传播与反向传播概览
神经网络模仿人脑神经元的工作方式,通过层层连接对数据进行处理和分析。前向传播和反向传播是神经网络训练过程中两个相互依存、循环往复的核心步骤。
简单来说,前向传播是“推理”的过程。输入数据从网络第一层(输入层)进入,经过每一层的加权求和与激活函数变换,逐步向前计算,最终得到输出层的预测结果。我们可以将其视为一个复杂的复合函数,输入数据x,通过函数f(即整个网络),得到输出f(x)。
然而,网络的初始预测通常是错误的。反向传播则是“学习”的过程。它根据预测结果与真实标签之间的误差(损失),利用链式法则,从输出层开始反向逐层计算每个参数(权重和偏置)对总误差的“贡献度”(即梯度)。随后,优化算法(如梯度下降)利用这些梯度来更新参数,使得网络的预测下次能更接近真实值。
这两个过程紧密配合:前向传播为反向传播提供计算所需的中间变量;反向传播利用这些变量计算梯度来优化网络;参数更新后,下一次前向传播会产生更准确的输出。如此反复迭代,网络性能得以持续提升。
2. 深入原理:前向传播的数学推导
让我们以一个单隐藏层的MLP为例,详细拆解前向传播的数学计算。假设输入样本是一个向量 𝐱 ∈ ℝ^𝑑,隐藏层有 ℎ 个神经元,输出层有 𝑞 个神经元。
第一步:从输入层到隐藏层
- 线性变换:隐藏层的输入是输入向量的加权和。设隐藏层权重矩阵为
𝐖^(1) ∈ ℝ^(ℎ×𝑑),则中间变量𝐳 = 𝐖^(1) 𝐱。如果考虑偏置项𝐛^(1),则𝐳 = 𝐖^(1) 𝐱 + 𝐛^(1)。 - 非线性激活:将线性变换的结果通过一个非线性激活函数
ϕ,得到隐藏层的激活值𝐡 = ϕ(𝐳)。激活函数(如ReLU、Sigmoid)的引入至关重要,它使神经网络能够拟合复杂非线性关系,而不仅仅是线性组合。
第二步:从隐藏层到输出层
- 线性变换:将隐藏层的输出
𝐡作为输出层的输入。设输出层权重矩阵为𝐖^(2) ∈ ℝ^(𝑞×ℎ),偏置为𝐛^(2),则输出层的未激活值𝐨 = 𝐖^(2) 𝐡 + 𝐛^(2)。 - 输出激活(可选):根据任务类型,可能对
𝐨再施加一个激活函数。例如,多分类任务常用Softmax函数将输出转化为概率分布。
第三步:计算损失
前向传播的终点是计算损失函数 𝐿。损失函数衡量了网络预测值 𝐨 与真实标签 𝑦 之间的差距,例如均方误差或交叉熵损失。我们训练网络的终极目标就是最小化这个损失。
为了更直观地理解数据流动和计算依赖关系,我们可以绘制计算图。在计算图中,节点代表变量(输入、权重、中间结果)或操作(矩阵乘法、激活函数),边表示数据流向。前向传播就是沿着计算图从输入到输出的方向,顺序计算所有节点的值。
3. 理解学习:反向传播与链式法则
反向传播是训练神经网络的引擎,其核心是链式法则。我们的目标是求出损失函数 𝐿 对网络中每一个参数(如 𝐖^(1), 𝐖^(2))的梯度 ∂𝐿/∂𝐖,然后沿着梯度下降的方向更新参数。
由于网络是分层复合的,损失 𝐿 对底层参数 𝐖^(1) 的梯度无法直接计算。链式法则允许我们将这个梯度分解为一系列中间梯度相乘的形式。反向传播的过程,就是从损失 𝐿 开始,逆向遍历前向传播的计算图,逐层计算并传递梯度。
我们继续以上述单隐藏层MLP为例,忽略偏置和正则化项,简要展示梯度计算过程:
- 输出层梯度:首先计算损失
𝐿对输出𝐨的梯度∂𝐿/∂𝐨,这取决于损失函数的形式。 - 隐藏层输出梯度:接着,计算
𝐿对隐藏层输出𝐡的梯度:∂𝐿/∂𝐡 = (𝐖^(2))^⊤ (∂𝐿/∂𝐨)。这里(𝐖^(2))^⊤是权重矩阵的转置,误差从输出层“反向”传播到了隐藏层。 - 隐藏层输入梯度:然后,计算
𝐿对隐藏层输入𝐳的梯度:∂𝐿/∂𝐳 = (∂𝐿/∂𝐡) ⊙ ϕ‘(𝐳)。其中⊙表示按元素相乘,ϕ‘是激活函数的导数。这体现了非线性激活在梯度传播中的作用。 - 参数梯度:最后,我们可以得到损失对权重的梯度:
∂𝐿/∂𝐖^(2) = (∂𝐿/∂𝐨) 𝐡^⊤∂𝐿/∂𝐖^(1) = (∂𝐿/∂𝐳) 𝐱^⊤
可以看到,在计算 ∂𝐿/∂𝐖^(1) 时,我们用到了前向传播中存储的中间变量 𝐱 和 𝐳。这正是反向传播需要额外内存的原因:它必须保留前向传播的中间结果以供反向计算使用,其内存占用量与网络层数和批量大小成正比。
4. 实践出真知:用PyTorch构建MLP
理解了理论之后,我们使用PyTorch框架快速构建一个MLP模型。这里我们以经典的Fashion-MNIST图像分类数据集为例。
第一步:导入库并定义网络架构
PyTorch的nn.Module提供了构建网络所需的所有模块。
import torch
from torch import nn
from torch.nn import functional as F
class MLP(nn.Module):
def __init__(self, input_size=784, hidden_size=256, num_classes=10):
super(MLP, self).__init__()
# 展平层:将28x28的图像展平为784维向量
self.flatten = nn.Flatten()
# 隐藏层:全连接层 + ReLU激活函数
self.hidden = nn.Linear(input_size, hidden_size)
# 输出层:全连接层(未激活),输出10个类别的分数
self.output = nn.Linear(hidden_size, num_classes)
def forward(self, x):
# 前向传播定义
x = self.flatten(x)
x = self.hidden(x)
x = F.relu(x) # 应用ReLU激活函数
x = self.output(x)
return x
第二步:初始化模型、损失函数和优化器
# 超参数
batch_size = 256
learning_rate = 0.1
num_epochs = 10
# 实例化模型
net = MLP()
# 定义交叉熵损失函数(内部包含Softmax)
criterion = nn.CrossEntropyLoss()
# 定义随机梯度下降优化器,并将网络参数传递给它
optimizer = torch.optim.SGD(net.parameters(), lr=learning_rate)
第三步:训练循环(整合前向与反向传播)
训练循环清晰地展示了前向传播、反向传播和参数更新的交替进行。
for epoch in range(num_epochs):
for data, labels in train_loader: # 假设train_loader已定义
# 前向传播
predictions = net(data)
loss = criterion(predictions, labels)
# 反向传播
optimizer.zero_grad() # 清空上一轮的梯度
loss.backward() # 自动计算梯度(反向传播)
# 参数更新
optimizer.step() # 根据梯度更新网络参数
print(f‘Epoch {epoch+1}, Loss: {loss.item():.4f}‘)
在loss.backward()这一步,PyTorch的自动微分(Autograd)系统自动为我们完成了链式法则的所有计算,这正是深度学习框架的强大之处。
5. 双框架对比:用TensorFlow/Keras构建MLP
为了展示不同框架的灵活性,我们同样使用TensorFlow的高级API Keras来实现功能相同的MLP。
第一步:使用Sequential API定义模型
Keras的Sequential API允许我们以层堆叠的方式直观定义模型。
import tensorflow as tf
from tensorflow.keras import layers, models
# 使用Sequential API定义模型
model = models.Sequential([
layers.Flatten(input_shape=(28, 28)), # 输入展平层
layers.Dense(256, activation=‘relu‘), # 全连接隐藏层,使用ReLU激活
layers.Dense(10) # 输出层,10个神经元
])
# 打印模型概要
model.summary()
第二步:编译模型
在Keras中,编译步骤需要指定优化器、损失函数和评估指标。
model.compile(
optimizer=tf.keras.optimizers.SGD(learning_rate=0.1), # 随机梯度下降优化器
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True), # 损失函数
metrics=[‘accuracy‘] # 评估指标为准确率
)
第三步:训练模型
Keras的fit方法将训练循环高度抽象化,只需一行代码。
# 假设 (train_images, train_labels), (test_images, test_labels) 已加载
history = model.fit(
train_images, train_labels,
epochs=10,
batch_size=256,
validation_data=(test_images, test_labels) # 每轮训练后在验证集上评估
)
TensorFlow/Keras的设计哲学是提供更高层次的抽象,让开发者能更专注于模型结构而非训练细节。model.fit()内部同样完整执行了前向传播、损失计算、反向传播和参数更新的循环。
6. 总结与进阶思考
通过本文,我们系统地探讨了深度学习的基石:前向传播与反向传播的数学原理,并亲手使用PyTorch和TensorFlow两个主流框架构建了MLP模型。理解前向传播如何将输入映射为输出,以及反向传播如何利用梯度下降和链式法则来优化网络参数,是掌握深度学习的关键。
尽管我们构建的MLP结构简单,但它包含了现代深度神经网络的所有核心要素。MLP作为基础构建块,其思想和原理贯穿于更复杂的卷积神经网络(CNN)、循环神经网络(RNN)和Transformer架构中。
进一步探索的方向:
- 深度与宽度:尝试增加隐藏层的数量(深度)或每层的神经元数量(宽度),观察模型性能的变化。在一定范围内,更深的网络具有更强的表达能力。
- 激活函数:将ReLU替换为Sigmoid、Tanh或LeakyReLU等,比较它们对训练速度和效果的影响。
- 优化器:使用Adam、RMSprop等更先进的优化器替代基础的SGD,它们通常能带来更快的收敛速度。
- 正则化:为了防止过拟合,可以在模型中添加Dropout层、L2权重正则化(如我们在数学推导中提到的
𝑠项)或批归一化(Batch Normalization)层。 - 硬件考量:随着模型加深加大,对显存和算力的需求急剧增加。这催生了如国产D20 AI加速卡这类高性能、低功耗的专用AI芯片,它们通过优化底层计算和存储访问,为训练和部署大规模模型提供了硬件基础。
深度学习的世界广阔而深邃。希望本文为你打开了这扇大门,助你在AI的探索之路上稳步前行。
更多推荐

所有评论(0)