基础 · 08

神经网络与反向传播

一个神经元是一条线加一个弯。把线叠起来,正方形变成八边形变成圆——这就是深度学习的全部秘密。

14 min read

线性分类器的天花板

上一篇我们看到,线性分类器——无论是 logistic 回归还是 linear SVM——只能画一条直线。对于非线性可分的数据(比如两个新月),它们的准确率卡在 50% 左右,不管你怎么调参。

核技巧可以绕过这个限制:先把数据映射到高维,再在高维画直线。但核函数的映射 ϕ(x)\phi(\mathbf{x})预先固定的——你选了 RBF 核就是 RBF,选了多项式核就是多项式。如果你选错了核,分类效果照样差。

那能不能让模型自己学一个最适合这份数据的映射?这就是神经网络的核心想法:

不预设 ϕ\phi,而是用可训练的参数搭一个映射函数,让梯度下降自动找到最好的那个。

一个神经元 = 一条线 + 一个弯

一个神经元做的事只有两步:

第一步:线性变换。 把输入向量 x\mathbf{x} 和权重 w\mathbf{w} 做点积,加上偏置 bb

z=wx+bz = \mathbf{w} \cdot \mathbf{x} + b

这跟 logistic 回归完全一样——在特征空间里画一条超平面。

第二步:非线性激活。zz 喂进一个非线性函数 σ\sigma

a=σ(z)a = \sigma(z)

最常用的激活函数是 ReLU(Rectified Linear Unit):

ReLU(z)=max(0,z)\text{ReLU}(z) = \max(0, z)

几何意义:ReLU 把超平面一侧的输出截断为零,另一侧保留原值。整个操作就是「画一条线,然后把一边折下去」。

为什么这个弯至关重要?因为线性变换叠线性变换还是线性变换——两个矩阵相乘 W2W1W_2 W_1 等于一个新矩阵 WW。没有激活函数,不管堆多少层,效果跟一层一样。正是这个「弯」让叠加有了意义。

叠起来:多边形逼近任意形状

把多个神经元并排放在一层:每个神经元画自己的线、折自己的弯。一层 NN 个 ReLU 神经元就是 NN 条线同时作用——几何上,它们切出一个 NN 边形的区域。

数学上,一个隐藏层的前向计算:

h=ReLU(W1x+b1)\mathbf{h} = \text{ReLU}(W_1 \mathbf{x} + \mathbf{b}_1) y^=w2h+b2\hat{y} = \mathbf{w}_2^\top \mathbf{h} + b_2

W1W_1 的每一行是一个神经元的权重向量(= 一条线的法向量),b1\mathbf{b}_1 是偏置(= 线到原点的距离),w2\mathbf{w}_2 控制怎么组合这些「折叠」。

下面的数据是两个同心环——内圈紫色,外圈青色,线性分类器完全没办法。切换隐藏层宽度感受:

线性分类器acc 41%
切换隐藏层宽度。4 个 ReLU 神经元画出正方形,8 个画八边形,16 个接近圆——每个神经元贡献一条直线,合在一起逼近任意形状。

4 个神经元画出正方形(4 条边),只在四个对角方向漏了。8 个画八边形,16 个已经几乎是圆。这就是**万能逼近定理(Universal Approximation Theorem)**的直觉:

只要隐藏层够宽,一层神经网络就能逼近任意连续函数到任意精度。

实际上,深度网络(多层)比宽网络(一层很宽)更高效——因为叠层是变换的复合 f3f2f1f_3 \circ f_2 \circ f_1,每一层可以在前一层的特征上做进一步的「折叠」。同样表达能力,深网络需要的参数更少。这也是为什么 Transformer 要堆 96 层而不是 1 层。

反向传播:梯度怎么流回去

网络搭好了,怎么训练?目标跟以前一样:定义一个损失 LL,算出 LL 对每个参数的梯度,然后用梯度下降更新参数。

关键问题是:参数藏在很多层里,LL 对第一层权重的梯度要穿过后面所有层才能算出来。链式法则告诉我们,把每一段的局部导数乘起来就行:

Lw=Ly^y^zzw\frac{\partial L}{\partial w} = \frac{\partial L}{\partial \hat{y}} \cdot \frac{\partial \hat{y}}{\partial z} \cdot \frac{\partial z}{\partial w}

反向传播(backpropagation) 就是把这条乘法链从后往前算一遍。来看一个具体例子——单个神经元,输入 x=2x = 2,权重 w=0.5w = 0.5,偏置 b=0.3b = -0.3,目标 t=1t = 1

w=0.5, b=−0.3target=1.0输入线性 wx+bReLU损失 (ŷ−t)²

点「前向传播」看数据怎么流过网络,再点「反向传播」看梯度怎么流回去。

一个单神经元的前向 / 反向传播。真实网络有几十亿参数,但每个参数的梯度都是这条链的一环。

前向传播算出预测 y^=0.70\hat{y} = 0.70,损失 L=0.09L = 0.09。反向传播从 LL 出发,逐层乘回去:L/w=1.2\partial L / \partial w = -1.2。这告诉优化器:ww 应该增大(梯度为负,沿负梯度方向走就是增大),从而把预测往目标推近。

真实网络有几十亿参数,但每个参数的梯度都是同样的链式乘法,PyTorch / JAX 只是帮你自动地把这条链算出来。

让训练跑起来的关键

有了反向传播,理论上可以训练任意深的网络。但实践中有几个工程上绕不开的问题:

批量梯度下降(mini-batch SGD)——不拿全部数据算一次梯度(太慢),也不只拿一个样本(太噪),而是每次取一个小批量(batch size 64–4096)。噪声反而帮助跳出局部最小值。

学习率调度——开头用小学习率(warm-up),让参数在初始化附近稳定住;中间放大,大步搜索;后期衰减(cosine decay),精细收敛。这套 warm-up + cosine 几乎是 Transformer 训练的标配。

Adam 优化器——不是裸用 L-\nabla L,而是给每个参数维护梯度均值梯度方差的滑动平均,自适应调步长。LLM 训练几乎全用 AdamW(Adam 加权重衰减)。

梯度消失与残差连接——如果每一层的局部导数都小于 1,链式乘法会让梯度指数衰减,深层参数几乎不更新。ResNet 的解决方案:加一条 skip connection y=f(x)+x\mathbf{y} = f(\mathbf{x}) + \mathbf{x},梯度可以沿着 +x+\mathbf{x} 那条路直接流到底。Transformer 的每个子层也都有残差连接。

归一化——Batch Norm(CNN 时代)和 Layer Norm(Transformer 时代)把每层输出的均值和方差拉到标准范围,防止中间层的数值越来越飘。

这些技巧不是装饰——没有它们,GPT 级别的模型根本训不动。

这个想法在前沿里