前向传播:从输入到输出
目的:将数据输入网络,经过一层层的计算,最终得出预测结果。
过程 :
假设我们有一个简单的三层网络:输入层、隐藏层、输出层。
- 输入数据 :假设输入特征为向量 xxx。
- 线性变换 :数据到达隐藏层,与该层的权重 WWW 相乘,再加上偏置 bbb。
- 公式:z=W⋅x+bz = W \cdot x + bz=W⋅x+b
- 通俗理解:权重决定了这个特征有多重要,偏置相当于一个触发阈值。
- 非线性激活 :将 zzz 输入到激活函数(如 ReLU、Sigmoid)中,得到这一层的输出 aaa。
- 公式:a=f(z)a = f(z)a=f(z)
- 通俗理解:如果不用激活函数,无论网络多深,本质上还是一个线性回归。激活函数让网络有了处理复杂非线性问题的能力。
- 传递到输出层 :隐藏层的输出 aaa 作为下一层的输入,重复步骤2和3,直到输出层得出最终的预测值 y^\hat{y}y^。
- 计算损失 :将预测值 y^\hat{y}y^ 与真实标签 yyy 进行对比,使用损失函数(如均方误差 MSE 或 交叉熵)计算出误差大小 LLL。
至此,前向传播结束。
反向传播:从输出找原因
目的 :计算出损失函数对网络中每一个权重和偏置的梯度(即导数),告诉网络该如何调整这些参数才能减小误差。
核心数学工具 :链式法则 。
因为损失 LLL 是输出 y^\hat{y}y^ 的函数,而 y^\hat{y}y^ 是上一层的函数,一层层套娃下去。链式法则允许我们将这些导数乘起来,从而求出 LLL 对中间每一个 WWW 和 bbb 的导数。
过程(从后往前推):
-
输出层求导:
- 首先计算损失对输出层线性结果的导数:∂L∂zout\frac{\partial L}{\partial z_{out}}∂zout∂L
- 然后计算损失对输出层权重的导数:∂L∂Wout=∂L∂zout⋅∂zout∂Wout\frac{\partial L}{\partial W_{out}} = \frac{\partial L}{\partial z_{out}} \cdot \frac{\partial z_{out}}{\partial W_{out}}∂Wout∂L=∂zout∂L⋅∂Wout∂zout
- 意义 :这个值告诉我们,输出层的权重 WoutW_{out}Wout 对当前误差负有多大责任。
-
向隐藏层传递误差:
- 计算损失对隐藏层输出的导数:∂L∂ahidden=∂L∂zout⋅∂zout∂ahidden\frac{\partial L}{\partial a_{hidden}} = \frac{\partial L}{\partial z_{out}} \cdot \frac{\partial z_{out}}{\partial a_{hidden}}∂ahidden∂L=∂zout∂L⋅∂ahidden∂zout
- 意义:这相当于把输出层的误差"分配"给隐藏层,告诉隐藏层:"你给我的值不太对,导致了最终误差,你需要调整这么多"。
-
隐藏层求导:
- 继续通过激活函数求导:∂L∂zhidden=∂L∂ahidden⋅f′(zhidden)\frac{\partial L}{\partial z_{hidden}} = \frac{\partial L}{\partial a_{hidden}} \cdot f'(z_{hidden})∂zhidden∂L=∂ahidden∂L⋅f′(zhidden) (其中 f′f'f′ 是激活函数的导数)
- 计算对隐藏层权重的导数:∂L∂Whidden=∂L∂zhidden⋅∂zhidden∂Whidden\frac{\partial L}{\partial W_{hidden}} = \frac{\partial L}{\partial z_{hidden}} \cdot \frac{\partial z_{hidden}}{\partial W_{hidden}}∂Whidden∂L=∂zhidden∂L⋅∂Whidden∂zhidden
-
不断重复 :直到求出网络中所有 WWW 和 bbb 的梯度。
参数更新:闭环
求出梯度后,网络会使用梯度下降算法来更新参数。公式如下:
Wnew=Wold−η⋅∂L∂WW_{new} = W_{old} - \eta \cdot \frac{\partial L}{\partial W}Wnew=Wold−η⋅∂W∂L
- η\etaη 是学习率,决定了我们每次迈出多大的一步去靠近最优解。
- 梯度 ∂L∂W\frac{\partial L}{\partial W}∂W∂L 的方向是指向误差增大的方向,所以前面要加一个负号,表示我们要向着误差减小的方向走。
一个通俗的现实类比
假设有一个工厂流水线生产蛋糕:
- 工人A(输入层)负责和面。
- 工人B(隐藏层)负责烤制。
- 工人C(输出层)负责裱花。
- 质检员(损失函数)尝了一口,发现太甜了(误差很大)。
前向传播 :面粉经过A、B、C的手,变成了一个蛋糕。
反向传播:
- 质检员对C说:"蛋糕太甜了,扣你绩效!"(计算 ∂L∂C动作\frac{\partial L}{\partial C_{动作}}∂C动作∂L)
- C反思:"太甜是因为B给我的胚子太干了,吸了太多糖浆。"于是C把责任分摊给B(链式法则传递梯度:∂L∂B动作\frac{\partial L}{\partial B_{动作}}∂B动作∂L)。
- B反思:"胚子太干是因为A给我的面团水加少了。"于是B把责任分摊给A(继续传递梯度:∂L∂A动作\frac{\partial L}{\partial A_{动作}}∂A动作∂L)。
参数更新:
- A决定下次和面多加5克水(更新权重)。
- B决定下次烤制少烤2分钟(更新权重)。
- C决定下次少放10克糖(更新权重)。
- 循环往复,直到蛋糕味道完美(损失函数收敛)。
总结:它们是如何协同工作的?
在训练神经网络时,这两者是紧密咬合的一个循环(通常称为一个 Epoch 或 Iteration):
- 拿一批数据。
- 前向传播:最后输出一个预测值,损失函数会对比预测值和真实标签,算出一个总误差。
- 反向传播:利用链式法则从后往前算梯度,找出是谁导致了误差。
- 更新参数:根据梯度下降法则,微调所有的权重和偏置。
- 重复1-4,直到误差小到满足我们的要求。
这就是深度学习能够"自动学习"特征的根本奥秘所在。