神经网络的计算和更新,本质上可以理解成一句话:先用当前参数把输入一步步算成预测值,再比较预测值和真实值之间的误差,然后沿着误差产生的方向反推每个参数该怎么改,最后把权重和偏置往"让误差变小"的方向移动一点。前向传播、损失函数、梯度、反向传播、权重更新这些概念并不是分开的,它们其实是一条连续链路中的不同环节。
先从最简单的一个神经元开始。假设输入只有一个数 (x),神经元里有两个可以学习的参数,一个叫权重 (w),一个叫偏置 (b)。这个神经元会先计算一个线性组合:
z=wx+b\] \[ z = wx + b \] \[z=wx+b
这里的权重 (w) 决定输入 (x) 对结果的影响有多大,偏置 (b) 决定即使输入为零时,神经元本身还保留多少基础输出。也就是说,权重控制"斜率",偏置控制"平移"。如果没有偏置,所有映射都被迫经过原点,表达能力会变弱。接下来,神经元通常还会把 (z) 输入到一个激活函数里,例如 ReLU、sigmoid 或 tanh,得到最终输出:
y\^=f(z)\] \[ \\hat{y} = f(z) \] \[y\^=f(z)
这个 (\hat{y}) 就是神经网络根据当前参数算出来的预测值。所谓"前向传播",就是从输入 (x) 出发,依次经过权重、偏置、激活函数,最后得到预测输出 (\hat{y}) 的过程。它叫"前向",是因为信息沿着输入层到输出层的方向流动。此时网络并没有学习,它只是拿着当前已有的参数做了一次计算。
但是神经网络不能只会算,它还要知道自己算得好不好。于是需要把预测值 (\hat{y}) 和真实值 (y) 进行比较,这个比较结果就是损失函数。最常见的均方误差可以写成:
L=12(y\^−y)2\] \[ L = \\frac{1}{2}(\\hat{y} - y)\^2 \] \[L=21(y\^−y)2
这里前面的 (\frac{1}{2}) 不是本质需要,只是为了后面对平方求导时抵消系数 2,让公式更简洁。损失 (L) 越大,说明预测值和真实值差得越远;损失越小,说明网络当前参数越合适。所以训练神经网络的真正目标,不是直接"让预测值变好",而是通过不断调整 (w) 和 (b),让损失函数 (L) 变小。
关键问题就来了:网络怎么知道 (w) 和 (b) 应该往哪个方向改?这时就需要梯度。梯度本质上是"损失函数对某个参数的变化敏感程度"。比如 (\frac{\partial L}{\partial w}) 表示权重 (w) 改变一点点,损失 (L) 会怎么变;(\frac{\partial L}{\partial b}) 表示偏置 (b) 改变一点点,损失 (L) 会怎么变。如果 (\frac{\partial L}{\partial w}) 是正的,说明 (w) 增大时损失会增大,那么为了让损失变小,(w) 就应该减小;如果 (\frac{\partial L}{\partial w}) 是负的,说明 (w) 增大时损失会减小,那么 (w) 就应该增大。梯度不是一个神秘量,它就是告诉参数"你现在对错误负多少责任,以及该往哪边改"。
把刚才的最简单神经元串起来看,假设先不使用复杂激活函数,直接令 (\hat{y}=z=wx+b),那么损失为:
L=12(wx+b−y)2\] \[ L = \\frac{1}{2}(wx+b-y)\^2 \] \[L=21(wx+b−y)2
现在要求 (w) 和 (b) 的梯度,就是看 (L) 对它们分别怎么变化。根据链式法则:
∂L∂w=(y\^−y)x\] \[ \\frac{\\partial L}{\\partial w} = (\\hat{y}-y)x \] \[∂w∂L=(y\^−y)x
∂L∂b=y\^−y\] \[ \\frac{\\partial L}{\\partial b} = \\hat{y}-y \] \[∂b∂L=y\^−y
这两个公式非常重要,因为它们已经把神经网络更新的核心逻辑暴露出来了。误差项是 (\hat{y}-y),表示当前预测比真实值高了还是低了;输入 (x) 参与到权重梯度里,说明权重的责任大小不仅取决于误差,还取决于这个输入在本次计算中有多大影响;偏置的梯度就是误差本身,因为偏置是直接加到输出上的,它不依赖输入大小。
然后参数更新就很自然了。既然梯度表示损失上升最快的方向,那么想让损失下降,就要沿着梯度的反方向移动。于是有:
wnew=wold−η∂L∂w\] \[ w_{\\text{new}} = w_{\\text{old}} - \\eta \\frac{\\partial L}{\\partial w} \] \[wnew=wold−η∂w∂L
bnew=bold−η∂L∂b\] \[ b_{\\text{new}} = b_{\\text{old}} - \\eta \\frac{\\partial L}{\\partial b} \] \[bnew=bold−η∂b∂L
这里的 (\eta) 叫学习率,它决定每次更新参数时走多大一步。学习率太小,网络学得很慢;学习率太大,参数可能一步跨过最优点,甚至导致损失震荡或发散。所谓"优化器",本质上就是在这个基本更新公式上做改进,例如 SGD 直接按梯度下降,Adam 则会结合历史梯度的一阶矩和二阶矩,让更新更稳定、更自适应。
用一个具体数值会更清楚。假设输入 (x=2),真实值 (y=5),当前权重 (w=1),偏置 (b=0)。前向传播得到:
y\^=wx+b=1×2+0=2\] \[ \\hat{y}=wx+b=1\\times2+0=2 \] \[y\^=wx+b=1×2+0=2
预测值是 2,真实值是 5,误差为 (\hat{y}-y=-3)。损失为:
L=12(2−5)2=4.5\] \[ L=\\frac{1}{2}(2-5)\^2=4.5 \] \[L=21(2−5)2=4.5
这说明当前网络明显预测偏低。接下来计算梯度:
∂L∂w=(y\^−y)x=−3×2=−6\] \[ \\frac{\\partial L}{\\partial w}=(\\hat{y}-y)x=-3\\times2=-6 \] \[∂w∂L=(y\^−y)x=−3×2=−6
∂L∂b=y\^−y=−3\] \[ \\frac{\\partial L}{\\partial b}=\\hat{y}-y=-3 \] \[∂b∂L=y\^−y=−3
如果学习率 (\eta=0.1),那么更新为:
wnew=1−0.1×(−6)=1.6\] \[ w_{\\text{new}}=1-0.1\\times(-6)=1.6 \] \[wnew=1−0.1×(−6)=1.6
bnew=0−0.1×(−3)=0.3\] \[ b_{\\text{new}}=0-0.1\\times(-3)=0.3 \] \[bnew=0−0.1×(−3)=0.3
更新后,权重和偏置都变大了。为什么?因为原来预测值太低,网络需要把输出往上抬。权重变大以后,同样的输入 (x=2) 会产生更大的贡献;偏置变大以后,整体输出也会被平移上去。再次前向传播:
y\^new=1.6×2+0.3=3.5\] \[ \\hat{y}_{\\text{new}}=1.6\\times2+0.3=3.5 \] \[y\^new=1.6×2+0.3=3.5
预测从 2 变成了 3.5,已经向真实值 5 靠近了。虽然还没有完全准确,但只要不断重复"前向计算---计算损失---反向求梯度---更新参数"这个循环,参数就会逐渐调整到更合适的位置。
真正的多层神经网络只是把这个过程堆叠起来。单个神经元是 (z=wx+b),多层网络则是每一层都做类似计算。第一层接收原始输入 (x),计算得到隐藏特征 (h_1);第二层接收 (h_1),继续计算得到更高层特征 (h_2);最后一层把这些特征变成预测结果 (\hat{y})。写成形式就是:
h1=f(W1x+b1)\] \[ h_1 = f(W_1x+b_1) \] \[h1=f(W1x+b1)
h2=f(W2h1+b2)\] \[ h_2 = f(W_2h_1+b_2) \] \[h2=f(W2h1+b2)
y\^=W3h2+b3\] \[ \\hat{y} = W_3h_2+b_3 \] \[y\^=W3h2+b3
这里的 (W_1,W_2,W_3) 是不同层的权重矩阵,(b_1,b_2,b_3) 是不同层的偏置向量。单输入单输出时权重是一个数,多输入多输出时权重就变成矩阵。矩阵并没有改变本质,它只是同时表示很多个神经元之间的连接强度。每一层的权重矩阵都决定上一层的特征如何组合成下一层的特征,每一层的偏置则给下一层神经元提供独立的平移自由度。
多层网络中,反向传播的核心仍然是链式法则。损失 (L) 直接由输出 (\hat{y}) 决定,而 (\hat{y}) 又由最后一层参数决定,最后一层的输入又来自前一层,前一层又来自更前面的层。所以损失对前面某个参数的影响不是直接发生的,而是通过一条计算链传递过去的。反向传播就是沿着这条链从后往前逐层计算梯度。
可以把它理解成责任追溯。输出错了,首先最后一层肯定有责任,因为它直接生成预测值;但最后一层的输入来自倒数第二层,所以倒数第二层也有责任;继续往前追溯,第一层也有责任,因为它最早决定了原始输入被提取成什么样的特征。反向传播并不是随便分配责任,而是用链式法则精确计算每一层、每一个权重、每一个偏置对最终损失的贡献。
如果把网络看成一串函数复合,例如:
y\^=f3(f2(f1(x)))\] \[ \\hat{y}=f_3(f_2(f_1(x))) \] \[y\^=f3(f2(f1(x)))
那么损失是:
L=ℓ(y\^,y)\] \[ L = \\ell(\\hat{y},y) \] \[L=ℓ(y\^,y)
当我们想知道第一层参数对损失的影响时,不能只看第一层本身,而要看第一层如何影响第二层,第二层如何影响第三层,第三层如何影响损失。数学上就是:
∂L∂W1=∂L∂y\^∂y\^∂h2∂h2∂h1∂h1∂W1\] \[ \\frac{\\partial L}{\\partial W_1}= \\frac{\\partial L}{\\partial \\hat{y}} \\frac{\\partial \\hat{y}}{\\partial h_2} \\frac{\\partial h_2}{\\partial h_1} \\frac{\\partial h_1}{\\partial W_1} \] \[∂W1∂L=∂y\^∂L∂h2∂y\^∂h1∂h2∂W1∂h1
这就是反向传播的灵魂。它不是另一个独立算法,而是链式法则在神经网络计算图上的系统化应用。前向传播保存了每一层的中间结果,比如 (z_1,h_1,z_2,h_2),反向传播就利用这些中间结果计算梯度。没有前向传播,反向传播就不知道每一层当时算出了什么;没有反向传播,网络就不知道每个参数该怎么改。
激活函数在这个链条里也很关键。如果没有激活函数,多层线性变换叠加起来仍然只是一个线性变换。比如 (W_2(W_1x+b_1)+b_2) 最后仍然可以合并成一个新的 (Wx+b),网络堆再深也表达不了复杂非线性关系。激活函数的作用,就是在每层之间引入非线性,让网络能够拟合曲线、边界、图像特征、语言语义以及复杂动力学关系。反向传播时,激活函数也要参与求导。例如 ReLU 在正区间导数为 1,在负区间导数为 0,这意味着被 ReLU 截断为 0 的神经元在本次反向传播中可能不会更新前面的相关连接,这也是所谓"神经元是否被激活"的数学含义。
从训练循环的角度看,神经网络的完整更新过程其实非常固定。首先把一批输入数据送入网络,网络用当前权重和偏置逐层计算输出,这一步是前向传播。然后用损失函数衡量预测输出和真实标签之间的差距,这一步得到一个标量损失。接着从损失出发,沿计算图反向计算每个参数的梯度,这一步是反向传播。最后优化器根据梯度更新所有参数,使下一次前向传播时预测更接近真实值。这个循环重复很多次,网络就逐渐从"随机参数导致胡乱预测",变成"参数结构逐渐适配数据规律"。
因此,权重、偏置、梯度、前向传播、反向传播和损失函数之间的关系可以压缩成一条完整因果链:权重和偏置决定前向传播怎么算,前向传播产生预测值,预测值和真实值产生损失,损失通过反向传播产生梯度,梯度告诉权重和偏置如何更新,更新后的权重和偏置又会改变下一次前向传播的结果。神经网络学习的本质,就是这条闭环反复运行。
如果说得更直观一点,权重和偏置是网络当前的"知识状态",前向传播是用这些知识去答题,损失函数是判卷,梯度是指出每个知识点错在哪里、错得多严重,反向传播是把错误责任从答案层层追溯回每个参数,优化器更新是根据责任大小修改知识状态。神经网络并不是一次性理解数据,而是在大量样本上反复答题、判卷、追责、修正,最终形成一组能够让整体误差较小的参数。
真正要建立整体感,最重要的是不要把梯度孤立地理解成"求导结果",而要把它放回训练闭环中。梯度之所以重要,是因为神经网络参数太多,不可能靠人手动调节。每个权重和偏置都需要一个明确的调整方向,而损失函数就是总目标,链式法则就是从总目标分解到每个参数的数学路径。前向传播负责建立"参数到损失"的计算关系,反向传播负责求出"损失对参数"的敏感程度,优化器负责把这种敏感程度转化为实际参数更新。这样看,神经网络训练就不再是一堆概念的堆叠,而是一个非常清晰的动态系统:当前参数产生当前预测,当前预测产生当前误差,当前误差产生当前梯度,当前梯度推动参数进入下一个状态。