一、从一句最朴素的话开始
如果你问我「神经网络到底是什么」,我会先把所有教材合上,然后给你一句朴素得近乎敷衍的话——神经网络就是一个函数。
仅此而已。它接收一些输入,吐出一些输出。中间有什么呢?有一些可以调节的旋钮——我们叫它们参数 \(W\) 和 \(b\)。所谓「训练」,就是不断地拧这些旋钮,让函数的输出越来越像我们想要的样子。所谓「推理」,就是把旋钮固定下来,让函数对新的输入做出预测。
这个视角看似平淡,却是我自己学习深度学习这么多年来最受用的一句话。它能帮你在被各种花哨的术语——Transformer、注意力、残差连接、LayerNorm、Mixture of Experts——淹没的时候,迅速拉回到一个简单的问题:「这一坨东西,作为一个函数,输入是什么、输出是什么、参数在哪里?」一旦回答清楚这三件事,你对它的理解就立住了一半。
所以本篇我们不急着讲注意力,也不急着讲 Transformer。我们退回到中学数学课,从 \(y = f(x)\) 开始,一砖一瓦地把「神经网络」这座房子搭起来。前三篇我们已经备好了砖头:向量、点积、矩阵乘法。这一篇我们用这些砖头砌墙。
二、\(y = f(x)\):你早就认识它了
中学数学课上,老师写下 \(y = f(x)\) 的时候,可能配了一句轻飘飘的解释:「\(y\) 是 \(x\) 的函数」。当时我没觉得这有什么了不起。直到很多年后,我才意识到,这个等号是整个现代科学的支点之一。
它说的是什么?它说,对每一个输入 \(x\),都有一个唯一确定的输出 \(y\)。函数 \(f\) 是这种映射关系的「打包」。你可以把它想象成一个黑盒:把 \(x\) 投进去,它吐 \(y\) 出来。
最简单的函数是常数函数,\(f(x) = 3\),无论你输入什么,它都吐出 3。再复杂一点是一次函数,\(f(x) = ax + b\),它有两个旋钮:斜率 \(a\) 和截距 \(b\)。再复杂一点是二次函数 \(f(x) = ax^2 + bx + c\),它有三个旋钮。再复杂一点是多项式、三角函数、指数函数……我们整个高中和大学低年级,都在学习各种各样的「具体的」函数。
但深度学习问的问题是反过来的——给我一堆 \((x, y)\) 数据点,请你猜出那个未知的 \(f\) 是什么样子。
这个问题叫做「函数拟合」或「回归」。它有一些经典做法:最小二乘、样条、核回归、支持向量回归……每一种做法都有它的假设和限制。深度学习的做法是:我不假设 \(f\) 是某个特定形式,我用一个非常灵活的「函数空间」去逼近它。这个函数空间,就是神经网络。
三、向量函数:从一维到多维
中学的 \(y = f(x)\) 里,\(x\) 和 \(y\) 都是一个数。但现实世界很少有这么简单的关系。
预测房价:输入是面积、卧室数、楼层、地段、装修……几十上百个数,输出是价格。 图像分类:输入是 \(224 \times 224 \times 3 \approx 15\) 万个像素值,输出是 1000 个类别上的概率分布。 机器翻译:输入是一句英文(变长向量序列),输出是一句中文(也是变长向量序列)。
这些任务的输入输出都是向量,甚至是矩阵、张量。所以现代的「函数」长这样:
\[\mathbf{y} = f(\mathbf{x}), \quad \mathbf{x} \in \mathbb{R}^n, \mathbf{y} \in \mathbb{R}^m\]
它把 \(n\) 维向量映射到 \(m\) 维向量。\(n\) 和 \(m\) 可以非常大——在大语言模型里动辄几万、几十万维。
我之所以在这里多花一段笔墨,是因为很多初学者一开始没有把「函数」从「一维」推广到「多维」的意识。他们脑子里 \(y = f(x)\) 永远是一条曲线。但在神经网络的世界里,一条曲线只是退化的特例。绝大多数时候,你要想象的是一个高维空间里的「映射」:左边是一个云团(输入分布),右边是一个云团(输出分布),函数 \(f\) 把左边的每一个点对应到右边的某个点。这个画面比「曲线」更接近真相。
四、最简单的可学习函数:线性变换
回到最简单的情形:\(y = ax + b\)。这是一条直线,有两个旋钮 \(a, b\)。给我一堆 \((x_i, y_i)\) 数据点,最小二乘可以告诉我最佳的 \(a, b\)。这就是一次函数的「学习」。
把它推广到向量。输入是 \(n\) 维向量 \(\mathbf{x}\),输出是 \(m\) 维向量 \(\mathbf{y}\)。最自然的「直线推广」是:
\[\mathbf{y} = W \mathbf{x} + \mathbf{b}\]
这里 \(W\) 是一个 \(m \times n\) 的矩阵,\(\mathbf{b}\) 是一个 \(m\) 维向量。它的旋钮个数是 \(m \times n + m\)。
这个公式看起来朴素,但它就是神经网络中最基本的积木——线性层(Linear
Layer / Dense Layer / Fully Connected
Layer,名字一堆,本质都一样)。PyTorch 里的
nn.Linear(n, m)、TensorFlow 里的
Dense(m)、Transformer 里 Q/K/V 的投影、FFN
的两层、输出 logits 的投影……全是这个公式。
我学神经网络的时候,被各种「层」迷惑了好久——卷积层、池化层、Dropout 层、BatchNorm 层、LayerNorm 层、Embedding 层、Attention 层……后来才意识到,真正具有可学习参数、真正在做「线性映射」的,绝大多数都是同一个公式 \(W\mathbf{x} + \mathbf{b}\)。其他「层」要么是固定的非线性变换(激活、归一化),要么是参数极少的特殊形式。
所以记住这个公式。它是接下来一切的起点。
五、为什么仅有线性是不够的
一个朴素的问题:既然线性变换 \(W\mathbf{x} + \mathbf{b}\) 这么强,我们叠它一千层,是不是就有一个超强的函数了?
来算一下。两层线性层串起来:
\[\mathbf{y} = W_2 (W_1 \mathbf{x} + \mathbf{b}_1) + \mathbf{b}_2 = (W_2 W_1) \mathbf{x} + (W_2 \mathbf{b}_1 + \mathbf{b}_2)\]
把 \(W_2 W_1\) 记作 \(W'\),\(W_2 \mathbf{b}_1 + \mathbf{b}_2\) 记作 \(\mathbf{b}'\),结果是:
\[\mathbf{y} = W' \mathbf{x} + \mathbf{b}'\]
——还是一个线性变换。
无论你叠多少层线性变换,它的总效果都等价于一层线性变换。这是线性代数的基本结论:线性变换的复合还是线性变换。
这是一个让人哭笑不得的事实。它意味着:如果你只用 \(W\mathbf{x} + \mathbf{b}\),你的整个网络再深,也只能拟合「直线」(在多维空间里是「超平面」)。它无法拟合任何弯曲的、复杂的关系。
而现实世界几乎所有有意思的关系都是非线性的。房价不是面积的线性函数(小户型每平米贵)。图像中的猫不是像素的线性函数(差一个像素就可能从猫变成狗)。语言不是字符位置的线性函数(一个 not 就能把整个意思反过来)。
所以神经网络必须引入非线性。而非线性的引入方式,就是在两个线性层之间插入一个激活函数。下一篇我们专门讲激活函数;这一篇我们先用最简单的 ReLU 来占个位置:
\[\text{ReLU}(z) = \max(0, z)\]
它把负数砍成零,正数留着。这个看起来傻乎乎的函数,恰恰是非线性的——它在 \(z = 0\) 处「拐了一下」。一拐之后,整个性质就变了。
六、两层网络:第一台真正的拟合机器
把线性 + 非线性 + 线性串起来,我们得到一个两层神经网络(也叫单隐藏层神经网络):
\[\mathbf{y} = W_2 \cdot \text{ReLU}(W_1 \mathbf{x} + \mathbf{b}_1) + \mathbf{b}_2\]
我们来一层一层看它做了什么。
输入 \(\mathbf{x}\) 是 \(n\) 维向量。\(W_1\) 是 \(h \times n\) 矩阵(\(h\) 是隐藏层维度),\(\mathbf{b}_1\) 是 \(h\) 维向量,所以 \(W_1 \mathbf{x} + \mathbf{b}_1\) 是 \(h\) 维向量。ReLU 逐元素作用,结果还是 \(h\) 维。\(W_2\) 是 \(m \times h\) 矩阵,\(\mathbf{b}_2\) 是 \(m\) 维向量,最终 \(\mathbf{y}\) 是 \(m\) 维向量。
参数总数:\(h \times n + h + m \times h + m = h(n + m + 1) + m\)。
这个网络长得朴素,但它是第一个能拟合任意复杂函数的结构——只要 \(h\) 足够大。这就是著名的「万能逼近定理」(Universal Approximation Theorem)。我们等会再正式讲它。
我喜欢把两层网络比作「乐高拼装机」:
- 第一层 \(W_1\mathbf{x} + \mathbf{b}_1\):负责把输入空间切成很多个「区域」。每一行 \(\mathbf{w}_i^\top \mathbf{x} + b_i\) 是一个超平面方程,决定了一个分界面。\(h\) 个超平面把空间切成 \(O(h^n)\) 个小区域。
- ReLU:负责「按区域开关」。某个超平面的「正侧」激活,「负侧」归零。
- 第二层 \(W_2\):负责把每个区域的特征线性组合成最终输出。
合起来:网络在每个小区域里都是一个线性函数,但不同区域的线性函数不同——它整体上是一个分段线性函数。当区域足够多、足够细,分段线性可以逼近任何连续函数。
这个画面对我帮助极大。深度学习并不神秘——它在做的事情,是用大量的「分段线性面片」去拼一个曲面。
七、深度:层次化的特征
两层就够了,为什么还要深度?理论上 \(h\) 足够大的两层网络可以逼近任何函数,但实际上「足够大」可能意味着 \(10^{20}\) 个神经元——根本训不动也存不下。
深度的好处是层次化(hierarchical)的特征复用。把多层网络写出来:
\[\mathbf{h}_1 = \text{ReLU}(W_1 \mathbf{x} + \mathbf{b}_1)\] \[\mathbf{h}_2 = \text{ReLU}(W_2 \mathbf{h}_1 + \mathbf{b}_2)\] \[\mathbf{h}_3 = \text{ReLU}(W_3 \mathbf{h}_2 + \mathbf{b}_3)\] \[\cdots\] \[\mathbf{y} = W_L \mathbf{h}_{L-1} + \mathbf{b}_L\]
每一层的输入是前一层的输出。早期层学到「低级特征」(边缘、纹理、字符),中间层学到「中级特征」(眼睛、鼻子、词组),后期层学到「高级特征」(人脸、句子的意图)。这是 Hubel & Wiesel 在猫的视觉皮层里发现的层次结构,被深度学习借走了。
我用过的最直观比喻:浅层网络像一个「单步推理者」,深层网络像一个「多步推理者」。前者一步把输入变成输出,后者把推理拆成几十步,每一步只做一点点变换,最后累积出复杂的能力。Transformer 的 12 层、24 层、96 层堆叠,背后的逻辑就是这个。
八、宽度 vs 深度:一个有意思的辩题
宽度(每层的神经元数 \(h\))和深度(层数 \(L\))哪个更重要?这在深度学习史上吵过很久。
- 万能逼近定理说:两层就够,只要 \(h\) 足够大。
- 实践和后续理论说:深度更高效。某些函数用深网络只需 \(O(n)\) 个神经元,用浅网络需要 \(O(2^n)\) 个。
直观地讲,深度提供了「指数级的表达能力」。每一层可以把上一层的「概念」组合成更高级的概念。每多一层,组合数翻倍。所以同样的参数预算下,深更省。
但深也有代价:梯度消失/爆炸、训练不稳、长程信息丢失……ResNet(残差连接,2015)和 LayerNorm 是深度学习能突破到几十层、上百层的关键技术。Transformer 把这些技术全用上了,所以可以堆到 96 层、175 层、甚至更深。
实际经验: - 经典 CNN 时代:宽 → 深,VGG(19 层)→ ResNet(50/101/152 层)→ DenseNet。 - Transformer 时代:深 + 宽并重。GPT-3 有 96 层、隐藏维度 12288;GPT-4 据传更深更宽。 - 大模型时代:参数量主要堆在 FFN(宽)和层数(深)上。
我的经验:如果不知道选什么,先把宽度调到能放进显存的最大值,再加深。但具体任务里,深和宽的最佳比例需要靠实验。
九、参数与超参数:两类完全不同的旋钮
「神经网络是一个函数,旋钮可以调」这句话其实有歧义——到底哪些是旋钮?
仔细分一下,神经网络里有两类「数」:
参数(parameters):\(W\) 和 \(\mathbf{b}\),通过训练自动学到。一个 70B 大模型有 700 亿个参数。这些是「自动调」的旋钮。
超参数(hyperparameters):层数、每层维度、激活函数选哪个、学习率、batch size、Dropout 率、优化器选什么……人为设定,训练前确定。这些是「手动调」的旋钮。
新手常犯的错是把这两个混为一谈。「我把模型调好了」——你调的是哪个?参数(写代码的人不直接动它,是优化器在动它)还是超参数(写代码的人直接选)?这两件事混淆起来,讨论问题就会鸡同鸭讲。
我自己的总结:写代码 = 选超参数 + 写训练循环;训练 = 让优化器找到好参数;调试 = 在两个层面都可能出问题。
十、「学习」到底是什么
到这里,我们终于可以回答最核心的问题:所谓「神经网络的学习」,到底在学什么?
答:在找一组让损失函数最小化的参数 \(W, \mathbf{b}\)。
展开讲:
- 我们手上有数据集 \(\{(\mathbf{x}_i, \mathbf{y}_i)\}_{i=1}^N\)。
- 我们定义网络 \(f_\theta\),其中 \(\theta = (W_1, \mathbf{b}_1, W_2, \mathbf{b}_2, \cdots)\) 是所有参数的总和。
- 我们定义损失函数 \(L(\theta) = \frac{1}{N} \sum_i \ell(f_\theta(\mathbf{x}_i), \mathbf{y}_i)\),衡量当前 \(\theta\) 下网络输出与真实值的差距。
- 我们用梯度下降(或其变种 Adam、SGD with momentum 等)去找一个让 \(L(\theta)\) 尽可能小的 \(\theta\):
\[\theta \leftarrow \theta - \eta \nabla_\theta L\]
其中 \(\eta\) 是学习率。
「学习」就是这四步。它不是什么神秘的事情,就是一个高维空间里的优化问题。
我反复强调这一点,是因为很多初学者会把「神经网络学到了语言的本质」想象成某种近乎魔法的过程。其实没有魔法。模型只是在 700 亿维空间里下山,找到了一个让损失低的位置。它学到的「知识」,全都编码在这 700 亿个数字里。
十一、损失函数:告诉网络「错在哪里」
损失函数 \(\ell(\hat{\mathbf{y}}, \mathbf{y})\) 是「真实输出」和「网络输出」之间差距的度量。不同任务用不同损失:
回归任务(输出是连续值,比如房价):均方误差(MSE)。
\[\ell_{\text{MSE}} = \frac{1}{2}(\hat{y} - y)^2\]
分类任务(输出是概率分布):交叉熵(Cross Entropy)。
\[\ell_{\text{CE}} = -\sum_k y_k \log \hat{y}_k\]
语言模型(下一个 token 预测):本质也是分类,用交叉熵。
损失函数是网络的「老师的红笔」。它告诉网络「你这次预测错了多少、错在哪个方向」。梯度下降根据这个红笔涂下来的方向调整参数。
我曾经被「为什么要用交叉熵不用 MSE 做分类」纠结过。简单的答案:用 MSE 做分类训练会很慢(梯度小),交叉熵 + softmax 的组合让梯度长得漂亮。深入的答案在「最大似然」和「指数族分布」里,咱们以后再讲。
十二、梯度下降:朝着最低点走一步
梯度 \(\nabla_\theta L\) 是损失函数相对于参数的导数向量。它指向「损失增加最快的方向」。所以「负梯度」指向「损失减小最快的方向」——也就是下山最快的方向。
梯度下降一步:
\[\theta \leftarrow \theta - \eta \nabla_\theta L(\theta)\]
\(\eta\) 是学习率,控制步长。太大会越过山底,太小会走得太慢。
这是最基础的优化算法。深度学习里实际用的优化器(SGD、Momentum、Adam、AdamW、Lion)都是它的变体——加上动量、自适应学习率、权重衰减等等。但内核还是「沿负梯度方向走一步」。
我习惯把损失函数想象成一个「沟壑纵横的山地」,参数 \(\theta\) 是一个游荡在这片山地上的小人。训练就是这个小人不停地下山。山地有:
- 平地:梯度近乎为零,小人困住了(梯度消失)。
- 悬崖:梯度极大,小人一脚踏出去飞了(梯度爆炸)。
- 山谷:长长的低洼地,小人在两侧来回振荡(病态条件)。
- 鞍点:四面都是上坡,但其实还有一个方向能下(鞍点逃逸)。
- 局部最低:周围都比这里高,但远处还有更低(局部最优)。
- 平坦盆地:很大一片都很低,进去就出不来(这反而是好事,泛化好)。
深度学习训练的所有「黑魔法」(warmup、cosine schedule、warmup restart、SAM、SWA),都在和这片山地的奇形怪状作斗争。
十三、反向传播:链式法则的工程实现
怎么算梯度 \(\nabla_\theta L\)?参数有上百亿个,损失是一个数。这是一个「多变量函数的复合求导」问题。
数学上的工具是链式法则:
\[\frac{\partial L}{\partial \theta_l} = \frac{\partial L}{\partial \mathbf{h}_L} \cdot \frac{\partial \mathbf{h}_L}{\partial \mathbf{h}_{L-1}} \cdot \cdots \cdot \frac{\partial \mathbf{h}_{l+1}}{\partial \theta_l}\]
工程上的实现是反向传播(Backpropagation):从输出层往输入层,逐层反向计算梯度,每层利用前向时的中间结果。
反向传播之所以高效,是因为它避免了重复计算——它用动态规划的思想,把链式法则里的中间项一次算完,然后传递。
PyTorch 和 TensorFlow
之所以叫「自动微分框架」,就是因为它们自动帮你做了反向传播。你只需写出前向计算,调用
loss.backward(),它就会自动算出每一个参数的梯度。这是深度学习能爆炸式发展的工程基础。
我自己手写过几次反向传播——为了真正搞懂它。强烈推荐每一个深度学习从业者都手写一次。Karpathy 的 micrograd(150 行 Python 实现自动微分)是绝佳的入门材料。
十四、万能逼近定理:理论的保证
「两层网络可以逼近任何连续函数」——这个说法不是吹牛,是有严格数学证明的,叫做万能逼近定理(Universal Approximation Theorem,UAT)。
Cybenko (1989) 证明:对任何连续函数 \(f: [0,1]^n \to \mathbb{R}\) 和任何 \(\epsilon > 0\),存在一个用 sigmoid 激活的两层神经网络 \(\hat{f}\),使得 \(|\hat{f}(\mathbf{x}) - f(\mathbf{x})| < \epsilon\) 对所有 \(\mathbf{x}\) 成立。
Hornik (1991) 把它推广到了任何「非多项式」的激活函数。
Leshno et al. (1993) 给出了完整的「激活函数应当满足的条件」。
这些定理告诉我们一件好事:神经网络作为「函数空间」是足够大的。原则上,任何你想拟合的连续函数,都有一个神经网络可以任意逼近它。
但它们也藏着一件坏事——「存在」不等于「找得到」。
定理保证了「存在一个 \(\theta^*\) 使得网络逼近你想要的函数」,但它没说你能用梯度下降找到这个 \(\theta^*\)。事实上,梯度下降是一个局部搜索算法,它只能找到局部最优。在高维非凸的损失曲面上,找到全局最优是没有保证的。
这就是深度学习的尴尬——理论说能做到,实践能不能做到要靠运气和工程。但奇妙的是,过去十年的实践告诉我们,用足够大的模型 + 足够好的数据 + 现代优化器,梯度下降几乎总能找到一个「足够好」的 \(\theta\)。这是一个让理论家也难以完全解释的奇迹。
我的看法:UAT 让我们对深度学习有了基本的「许可证」——它证明了「方向是对的」。但具体怎么训得动、训得好,还是另外一门学问。
十五、归纳偏置:函数空间不是越大越好
UAT 说函数空间足够大。但实际上,函数空间太大也不好——会过拟合。
什么是过拟合?模型不仅学到了数据中的「真实规律」,还学到了「噪声」。在训练集上表现极好,在测试集上一塌糊涂。
怎么对抗过拟合?给模型加归纳偏置(inductive bias)——人为限制函数空间,让它只能在「合理的」子集中找。
不同的网络结构有不同的归纳偏置:
- MLP(全连接):几乎没有偏置,把输入当作扁平向量。表达力强但容易过拟合,需要大量数据。
- CNN(卷积):偏置「局部性 + 平移不变性」。适合图像。
- RNN(循环):偏置「时序 + 共享参数」。适合短序列。
- Transformer:偏置「全连接的 token 间关系 + 位置编码」。比 CNN/RNN 弱的归纳偏置,但用大量数据补回来。
这是深度学习里一个让人兴奋的趋势——模型越大、数据越多,归纳偏置可以越弱。GPT 系列就是这个趋势的极致:用 Transformer 的最弱偏置,加上海量数据,硬学出语言的全部规律。
我以前觉得「归纳偏置弱 = 模型差」。后来想通了:归纳偏置弱 = 模型不预设任何结构 = 数据怎么说我怎么学。这恰恰是大模型时代追求的。
十六、为什么是「神经」?一段历史
为什么这个东西叫「神经网络」?因为最早的灵感来自生物神经元。
1943 年,McCulloch 和 Pitts 写了一篇论文《A Logical Calculus of the Ideas Immanent in Nervous Activity》。他们试图用数学描述生物神经元的工作方式:神经元接收多个输入信号,按权重相加,超过阈值就「发放」(输出 1),否则不发放(输出 0)。
这个模型用公式写就是:
\[y = \mathbb{1}\left(\sum_i w_i x_i > \theta\right)\]
是不是和现代的 \(\text{ReLU}(W\mathbf{x} + \mathbf{b})\) 神似?
1958 年,Rosenblatt 提出感知机(Perceptron),实现了这个模型并在硬件上跑了起来。当时的媒体兴奋地宣称「机器要能思考了」。
1969 年,Minsky 和 Papert 出版《Perceptrons》一书,证明了单层感知机连 XOR 这种简单逻辑都做不了。打击巨大,AI 进入第一次寒冬。
实际上,他们的证明只针对单层。多层网络 + 隐藏层 + 非线性激活,可以解 XOR——但当时没人知道怎么训练多层网络。
1986 年,Rumelhart、Hinton、Williams 发表了关于反向传播的著名论文,让多层网络的训练成为可能。神经网络第二次复兴。
但很快又遇到瓶颈——多层网络训练不稳定、SVM 横空出世(1995)、计算资源不足。整个 1990 年代到 2000 年代初,神经网络再次冷下去。
直到 2006 年 Hinton 的「深度信念网络」、2012 年 Krizhevsky 的 AlexNet 在 ImageNet 上一鸣惊人,深度学习才真正崛起。然后是 2017 年的 Transformer,2020 年的 GPT-3,2022 年的 ChatGPT……一发不可收拾。
我喜欢把这段历史讲给学生听,因为它告诉我们:深度学习不是凭空冒出来的,它是 80 年的积累、两次寒冬、无数人坚持的结果。如果你今天觉得它很「热」,请记住,热度是几代研究者用冷板凳换来的。
十七、生物神经元真的是这样吗?
老实讲,人工神经元和生物神经元只是名字像。
生物神经元的复杂性远远超过 \(y = \text{ReLU}(W\mathbf{x} + b)\)。它有树突、轴突、突触、神经递质、动作电位、各种离子通道、时间常数、可塑性……一个真正的神经元的计算复杂度,可能相当于几千个甚至几万个人工神经元。
所以「神经网络」这个名字其实有点误导。它更像是「受神经元启发的可微分函数复合」。今天的从业者大多直接把它当成数学对象在用,已经很少回头去和生物对应。
我的态度:你不用真的相信「这是脑子的工作方式」。这个名字是历史遗留,至于它现在做的事情——更接近于「高维统计」和「函数逼近」。
十八、神经网络与传统机器学习的关系
学过传统机器学习(线性回归、SVM、决策树、随机森林、XGBoost)的人,可能会问:神经网络和它们是什么关系?
我的总结:
- 线性回归 = 单层无激活的神经网络。
- 逻辑回归 = 单层 + sigmoid 激活的神经网络。
- SVM = 用 hinge loss 训练的特殊神经网络(核 SVM 是另一回事)。
- 决策树 = 不可微的「分段常数」函数。神经网络是「分段线性」函数。两者都能拟合复杂关系,但训练方式完全不同(GBDT vs SGD)。
- k 近邻 = 非参数方法,没有「训练」过程。神经网络是参数方法。
更重要的视角:神经网络是把「特征工程」和「模型」打包学习的方法。传统机器学习里,特征工程占了 80% 的时间。神经网络让网络自己学特征——你只管把原始数据喂进去。
这也是为什么深度学习在「原始数据复杂、特征工程难做」的领域(图像、文本、音频)压倒了传统方法,而在「特征已经被人精心做出来」的领域(一些表格数据),传统方法(XGBoost)依然不输。
十九、计算图:函数复合的可视化
每一个神经网络都对应一个计算图(computational graph)——一个有向无环图(DAG),节点是「张量」或「操作」,边是「数据流」。
举例:\(\mathbf{y} = W_2 \cdot \text{ReLU}(W_1 \mathbf{x} + \mathbf{b}_1) + \mathbf{b}_2\) 的计算图:
x ──→ MatMul(W1) ──→ Add(b1) ──→ ReLU ──→ MatMul(W2) ──→ Add(b2) ──→ y
每一步都是一个函数。整个网络是它们的复合。
计算图不仅是可视化工具,它是反向传播的基础。PyTorch
在前向时记录计算图,反向时沿图反向走一遍,用链式法则计算每个节点的梯度。这就是
autograd 的工作原理。
我学计算图的时候顿悟了一件事:「网络结构」其实只是「计算图的形状」。Transformer、ResNet、UNet、GAN,所有「架构创新」本质上都是在画不同的计算图。一旦你能画出图,剩下的就是工程实现。
二十、可微性:为什么我们到处插小心思
梯度下降需要梯度,所以网络的所有操作必须可微——至少是「几乎处处可微」。
这个要求带来很多约束:
- 激活函数必须可微。ReLU 在 0 处不可导,但「左导 0、右导 1」的次梯度足够了。
- 离散操作很麻烦——比如 argmax、采样、整数索引。它们没有连续梯度,需要特殊处理(Gumbel-softmax、REINFORCE、straight-through estimator)。
- 网络结构里的分支也得小心——条件 if-else 会让梯度路径复杂化。
这就是为什么深度学习里到处充满「软化」(softening)的小心思:
- argmax 太硬 → 用 softmax。
- 阶跃函数太硬 → 用 sigmoid。
- 离散选择太硬 → 用 Gumbel-softmax。
- 哈希查表太硬 → 用 embedding。
- ……
「让一切都可微」是深度学习的工程基本功。你看到的每一个 softmax、sigmoid、tanh,背后都是这个动机。
二十一、神经网络的通用结构
把前面所有内容总结一下,任何一个神经网络都可以拆成三件事:
- 结构:网络长什么样?多少层?每层做什么操作?计算图怎么连?
- 参数:哪些权重需要学?初始化怎么设?
- 训练:损失函数是什么?优化器选哪个?数据怎么喂?
这三件事独立又耦合。结构决定了参数数量和计算图;参数决定了函数的具体值;训练决定了参数最终落在哪里。
这是我看任何一篇深度学习论文时的「三联问」——它的结构是什么?它的参数怎么用?它怎么训的?回答了这三个问题,论文 80% 的内容就懂了。
二十二、「函数」的边界:神经网络做不到什么
神经网络是函数,但不是所有问题都能被「函数化」。
它做不到的事情:
- 保证逻辑正确性。神经网络是统计的,不是符号的。它会算 \(1 + 1 = 2\),但你永远没法证明它对所有的 \(a + b = c\) 都对。
- 精确记忆。它的记忆是分布式的、有损的、可遗忘的。
- 处理无限维输入。它需要把输入压缩到一个固定维度。
- 完全确定性。同样的输入,权重稍微不同,输出可能差异巨大。
- 解释自己。它是黑盒;可解释性是另一个研究方向。
所以现代 AI 系统越来越倾向于「神经网络 + 符号系统 + 工具调用」的混合架构。神经网络负责模糊的、统计的部分;符号和工具负责精确的、确定的部分。这是 LLM Agent、检索增强(RAG)、代码解释器等技术的共同思路。
二十三、一段离题的牢骚:为什么深度学习「丑」却有效?
学纯数学出身的人,第一次接触深度学习可能会皱眉头。它太「丑」了——一堆奇怪的网络结构、一堆调得人哭的超参数、一堆没有数学保证的 trick、训练曲线神秘地起起伏伏。
我有几年也很反感。那时我觉得 SVM 才是「优雅」的——凸优化、唯一最优、理论完备。神经网络?不就是堆参数堆数据嘛,毫无美感。
后来我转变了。深度学习的丑,是来自现实世界的丑。语言、图像、声音这些高维数据的内在结构,本来就乱七八糟,没有那么多漂亮的几何。强行用「优雅的数学」去描述它们,结果就是模型表达力不够。
深度学习放弃了「优雅」,换来「通用」。它愿意接受任何一个奇怪的形状、任何一个奇怪的损失、任何一个奇怪的优化路径——只要最后能把任务做好。这种「不偏不倚的表达力」是它的核心竞争力。
后来我明白了:通用性比优雅性更值钱。这是过去十年深度学习给我的最大思想冲击之一。
二十四、从函数视角看 Transformer
绕了一大圈,我们终于可以回到 Transformer。Transformer 也是一个函数。它的输入是一个 token 序列,输出是另一个 token 序列(或下一个 token 的概率分布)。
Transformer 的内部结构展开看,每一个 Block 是这样的:
\[\mathbf{x}' = \mathbf{x} + \text{Attention}(\text{LN}(\mathbf{x}))\] \[\mathbf{x}'' = \mathbf{x}' + \text{FFN}(\text{LN}(\mathbf{x}'))\]
其中:
- \(\text{LN}\) 是 LayerNorm,归一化。
- \(\text{Attention}\) 是注意力(核心,下一篇之后专讲)。它内部全是矩阵乘法和 softmax。
- \(\text{FFN}\) 是「Feed-Forward Network」——其实就是一个两层神经网络!通常是 \(\text{Linear}(d \to 4d) \to \text{GELU} \to \text{Linear}(4d \to d)\)。
Transformer 的 FFN 部分,就是本篇讲的两层神经网络的应用。它在每个 token 上独立作用,把每个 token 的表示变得更丰富。
研究表明:Transformer 的「事实记忆」主要存在 FFN 里。论文《Transformer Feed-Forward Layers Are Key-Value Memories》(2020)就在做这件事。如果你把 Transformer 看成一个推理机器,那 FFN 就是它的「知识库」。
所以本篇看似在讲基础,实则讲的是 Transformer 的一半(另一半是注意力)。FFN 占了 Transformer 大约 2/3 的参数量。理解了 FFN,你就理解了 Transformer 的「记忆」部分。
二十五、从函数视角看大语言模型
继续往上看。大语言模型(LLM)也是一个函数。
它的输入是一段文字 prompt,把它分词成 token 序列 \([t_1, t_2, \cdots, t_n]\)。它的输出是「下一个 token」的概率分布——一个长度为词表大小 \(V\) 的向量,每个元素是一个概率。
形式化:
\[P(t_{n+1} | t_1, \cdots, t_n) = \text{LLM}_\theta([t_1, \cdots, t_n])\]
参数 \(\theta\) 包含整个模型的所有权重——70B 模型就有 700 亿个参数。
「自回归生成」就是反复调用这个函数:
- 输入 prompt \([t_1, \cdots, t_n]\),得到 \(P(t_{n+1})\)。
- 从 \(P(t_{n+1})\) 采样(或 argmax)得到 \(t_{n+1}\)。
- 把 \(t_{n+1}\) 接到序列后面,输入 \([t_1, \cdots, t_{n+1}]\),得到 \(P(t_{n+2})\)。
- 反复,直到生成结束 token。
整个过程,LLM 始终是同一个函数——只是反复调用而已。所谓「思考」「推理」「记忆」,全都发生在 700 亿个参数和反复的前向传播中。
这是我对 LLM 的「祛魅」。它不是一个会思考的智能体,它是一个很大的函数 + 一个采样循环。函数本身是死的,但函数足够大、训得足够好,循环采样出来的输出就能让人类感到「智能」。
二十六、概念回顾:术语小词典
写到这里我们已经覆盖了很多概念。整理一个小词典,方便后面的篇章引用。
| 术语 | 中文 | 含义 |
|---|---|---|
| Function | 函数 | 输入到输出的映射 |
| Linear Layer / Dense | 线性层 / 全连接层 | \(\mathbf{y} = W\mathbf{x} + \mathbf{b}\) |
| Activation | 激活函数 | 非线性变换,让网络能拟合复杂关系 |
| MLP | 多层感知机 | 多个线性层 + 激活的堆叠 |
| Hidden Layer | 隐藏层 | 输入和输出之间的层 |
| Width | 宽度 | 每层的神经元数(向量维度) |
| Depth | 深度 | 层数 |
| Parameters | 参数 | 通过训练学到的 \(W, \mathbf{b}\) |
| Hyperparameters | 超参数 | 人为设定的(层数、学习率等) |
| Loss | 损失 | 衡量预测与真值差距 |
| Gradient | 梯度 | 损失对参数的偏导 |
| Backprop | 反向传播 | 链式法则的工程实现 |
| UAT | 万能逼近定理 | 两层网络可以逼近任意连续函数 |
| Inductive Bias | 归纳偏置 | 网络结构带来的先验假设 |
| Computational Graph | 计算图 | 神经网络的有向无环图表示 |
| FFN | 前馈网络 | Transformer 中的两层 MLP |
二十七、和前几篇的连接
回头看:
- 第一篇讲了 Transformer 的全局图景。
- 第二篇讲了向量与点积——「相似度」的代数。
- 第三篇讲了矩阵乘法——「多个点积一起算」。
- 第四篇讲了函数与神经网络——「为什么要做这一连串矩阵乘法」。
三、四两篇是「计算的两面」:第三篇讲计算「怎么算」,第四篇讲计算「为什么这么算」。从信息流的角度看,神经网络就是「输入向量 → 一连串矩阵乘法 + 非线性 → 输出向量」。
下一篇(第五篇)讲激活函数——非线性的具体形式。Sigmoid、Tanh、ReLU、GELU、SwiGLU,每一个都背着一段故事。
二十八、关键概念回顾
回到开头那句朴素的话——神经网络就是一个函数。
这句话可以从几个层次理解。
第一层,它是一个数学对象:从 \(\mathbb{R}^n\) 到 \(\mathbb{R}^m\) 的映射,由参数 \(\theta\) 决定具体形式。我们不预设它具体长什么样,而是让数据来告诉我们。
第二层,它是一组结构化的复合函数:一系列线性变换 \(W\mathbf{x} + \mathbf{b}\) 和非线性激活的交替。每一层都是一个简单的「积木」,整体堆出复杂的能力。线性提供了「方向」,非线性提供了「弯曲」,深度提供了「层次」。
第三层,它是一个可学习的系统:通过损失函数 + 梯度下降 + 反向传播,让参数自动找到一个让任务表现好的位置。「学习」不是魔法,是高维空间里的优化。
第四层,它有理论保证(UAT),但理论不等于实践。能逼近 ≠ 能找到。深度学习能 work,是理论 + 数据 + 算力 + 工程的合力。
第五层,它是 Transformer 和 LLM 的「半边天」。Transformer 的 FFN、LLM 的整体框架,都建立在「神经网络作为函数」这一根基上。
把这五层叠起来,你对「神经网络是什么」的理解就完整了。
二十九、常见误解
误解一:神经网络模拟了大脑。
人工神经元和生物神经元只是名字像。生物神经元的复杂性远超 \(\text{ReLU}(W\mathbf{x} + \mathbf{b})\)。神经网络更像「受启发的可微分函数」,不是大脑模型。研究神经网络不能告诉你大脑怎么工作,研究大脑也不能直接告诉你神经网络怎么改进。
误解二:神经网络越深越好。
深度有边际效应。早期增加深度收益巨大,到一定层数后收益急剧下降。深度还会带来梯度问题、训练不稳。深度学习的进展不是「无脑加深」,而是「加深 + 残差 + 归一化 + 优化器改进」综合的结果。
误解三:神经网络越大越好。
参数量大确实能力强,但需要更多数据、更多算力。如果数据少,大模型会严重过拟合;如果算力少,大模型训不动。「大」是手段不是目的。Chinchilla 缩放定律告诉我们,参数量和数据量需要匹配。
误解四:训练好了就万事大吉。
训练只是第一步。还有部署、量化、加速、监控、迭代……一个能用的 AI 系统里,模型本身只是其中一环。你看到的 ChatGPT 背后是模型 + 推理引擎 + 安全过滤 + 用户界面 + RLHF 反馈闭环 + 缓存 + 负载均衡,缺一不可。
误解五:神经网络可以拟合任何函数(万能逼近)。
理论上,两层网络 + 足够多神经元 + 合适激活 + 全局最优解 = 可以逼近任何连续函数。但「足够多」可能是天文数字,「全局最优」可能根本找不到。UAT 是「可能性证明」,不是「方法保证」。
误解六:损失越低越好。
不是。训练损失低 + 测试损失高 = 过拟合,是失败。我们追求的是「测试损失低」,等价于「泛化好」。所以训练时要看 train/val 两条曲线,光看训练损失会被骗。
误解七:参数都在学有用的东西。
恰恰相反,神经网络的参数大量是「冗余」的。剪枝(pruning)研究告诉我们,一个训练好的网络通常可以削减 50%-90% 的参数而几乎不损失性能。但训练时这些「冗余」参数有用——它们提供了优化的「松弛空间」。这是一个吊诡的事实。
误解八:只要有数据,模型自动就能学好。
数据需要质量。脏数据、错标、不平衡,都会让模型学偏。LLM 时代有句话:garbage in, garbage out。OpenAI 等大公司花在数据清洗上的人力,远超你想象。
误解九:深度学习是黑盒,所以不可信。
「黑盒」不等于「不可信」。我们用药、坐飞机、过马路,都信任了我们不完全理解的复杂系统。重要的是「可验证」——能否在测试上验证它的表现。可解释性是研究方向,但不是使用前提。
误解十:神经网络就是「大数据 + 算力」的暴力解。
这是最常见的、最浅薄的误解。深度学习背后有大量的算法创新——ReLU、Dropout、BatchNorm、Adam、残差连接、Transformer……每一个都是巨大的洞察。「暴力」只是表象,「巧思」才是内核。
三十、下一步
下一篇(第五篇)我们讲激活函数。
我们将详细对比 Sigmoid、Tanh、ReLU 这三大经典激活函数:它们的形状、它们的导数、它们的优缺点,以及为什么 ReLU 在 2012 年颠覆了深度学习的训练。然后我们讲现代激活函数 GELU、SwiGLU——它们是 Transformer 时代的标配。我们还会回答一个看似简单但很多人答不好的问题:为什么 ReLU 这么简单的函数,反而比 Sigmoid 更好?
之后的篇章里,我们还会用本篇的视角不断审视 Transformer 的每一个组件:
- 第六篇讲向量空间和嵌入(embedding)——把离散 token 变成可微分向量。
- 第七篇讲位置编码——给序列里的位置打标签。
- 第八篇讲 softmax——把任意向量变成概率分布的「软化」器。
- 第九、十篇讲 Q/K/V——注意力的源头。
- 第十一篇讲注意力本身——把所有积木拼起来。
每一篇我们都会回到「它是一个函数」的视角:输入是什么、输出是什么、参数在哪、怎么训。坚持这个朴素视角,复杂的东西就不会太可怕。
三十一、参考文献
- Cybenko, G. (1989). Approximation by superpositions of a sigmoidal function. Mathematics of Control, Signals, and Systems.
- Hornik, K. (1991). Approximation capabilities of multilayer feedforward networks. Neural Networks.
- Leshno, M. et al. (1993). Multilayer feedforward networks with a nonpolynomial activation function can approximate any function. Neural Networks.
- McCulloch, W. & Pitts, W. (1943). A Logical Calculus of the Ideas Immanent in Nervous Activity. Bulletin of Mathematical Biophysics.
- Rosenblatt, F. (1958). The Perceptron: A Probabilistic Model for Information Storage and Organization in the Brain. Psychological Review.
- Minsky, M. & Papert, S. (1969). Perceptrons: An Introduction to Computational Geometry.
- Rumelhart, D., Hinton, G., Williams, R. (1986). Learning representations by back-propagating errors. Nature.
- LeCun, Y., Bengio, Y., Hinton, G. (2015). Deep learning. Nature.
- Goodfellow, I., Bengio, Y., Courville, A. (2016). Deep Learning(花书). MIT Press.
- Geva, M. et al. (2020). Transformer Feed-Forward Layers Are Key-Value Memories. arXiv:2012.14913.
- Karpathy, A. micrograd 与 makemore 系列教程:手写自动微分、从零搭建神经网络。
- 3Blue1Brown 的 Neural Networks 系列视频:把神经网络的几何直觉讲得极好。
三十二、再谈「学习」:从一个最小的例子说起
如果上面那么多概念你一时消化不下来,那我们用一个最小的例子重新走一遍——让神经网络学会 XOR。
XOR 是一个简单的逻辑运算:
| \(x_1\) | \(x_2\) | \(y\) |
|---|---|---|
| 0 | 0 | 0 |
| 0 | 1 | 1 |
| 1 | 0 | 1 |
| 1 | 1 | 0 |
这是个看起来很无聊的任务。但它在神经网络史上意义非凡——单层感知机做不了 XOR,这一点曾经把神经网络打入冷宫。
为什么单层做不到?因为 XOR 不是线性可分的。想象在 \((x_1, x_2)\) 平面上画四个点:\((0,0)\) 和 \((1,1)\) 标 0,\((0,1)\) 和 \((1,0)\) 标 1。你画不出一条直线把两类点分开——它们呈对角线分布。
而两层网络 + 非线性激活,可以做到。我们来看看怎么做的。
设隐藏层有两个神经元,参数为:
\[W_1 = \begin{pmatrix} 1 & 1 \\ 1 & 1 \end{pmatrix}, \quad \mathbf{b}_1 = \begin{pmatrix} 0 \\ -1 \end{pmatrix}\]
\[W_2 = \begin{pmatrix} 1 & -2 \end{pmatrix}, \quad b_2 = 0\]
激活函数用 ReLU。前向计算:
\[\mathbf{h} = \text{ReLU}(W_1 \mathbf{x} + \mathbf{b}_1) = \text{ReLU}\begin{pmatrix} x_1 + x_2 \\ x_1 + x_2 - 1 \end{pmatrix}\]
\[y = W_2 \mathbf{h} = h_1 - 2h_2\]
代入四个点:
- \((0,0)\):\(\mathbf{h} = (0, 0)\),\(y = 0\)。✓
- \((0,1)\):\(\mathbf{h} = (1, 0)\),\(y = 1\)。✓
- \((1,0)\):\(\mathbf{h} = (1, 0)\),\(y = 1\)。✓
- \((1,1)\):\(\mathbf{h} = (2, 1)\),\(y = 0\)。✓
漂亮!两层网络解决了 XOR。
这个例子的意义在于:它告诉你两层网络不是「比一层多一点」,而是「质变」。一层只能划直线;两层可以「先映射再划直线」——而第一次映射后,原本不可分的点变得可分了。
这个想法是 SVM 核函数的本质,也是深度学习「逐层抽象」的本质。神经网络的每一层都在重新组织输入,让后面的层更容易处理。
三十三、从 XOR 到大模型:本质没变
XOR 这个 toy example 看起来跟 70B 大语言模型没什么关系。但本质是一样的。
70B 模型在做的事情,也是「逐层重组输入,让后面的层好处理」。最初的 token embedding 只是「这个词的初始向量」;经过几十层 Transformer Block 之后,最后一层的向量已经是「整个上下文里这个位置应该输出什么」的浓缩信息。
中间这几十层每一层都做着类似 XOR 的工作——把信息重组到一个对下一层更友好的空间里。只不过 XOR 是 2 维 → 2 维 → 1 维,70B 模型是 12288 维 → 12288 维 →…→ 12288 维 → 词表大小维。
我喜欢这种「连续性」——从最简单的 XOR 到最大的 LLM,背后是同一种思想。这让深度学习既有数学的优雅,又有工程的实用。
三十四、训练动力学:一个让我着迷的话题
我个人最着迷的一个研究方向是「神经网络训练的动力学」——参数在训练过程中是怎么变化的?损失曲面长什么样?为什么 SGD 总能找到「好的」解?
这里有几个有意思的现象:
「双重下降」(Double Descent):传统统计学告诉我们,模型越大越容易过拟合。但深度学习里发现:模型继续变大,过拟合反而消失。损失先降、再升、再降——形成「双重下降」曲线。这违反了经典理论。
「彩票假设」(Lottery Ticket Hypothesis):Frankle & Carbin (2018) 发现,一个大网络里似乎隐藏着一个小的「中奖子网络」,它单独训练就能达到大网络的效果。这是对「神经网络冗余性」的经典证据。
「神经切线核」(NTK):当网络非常宽时,训练动力学可以用一个固定的核函数描述。这给了无限宽神经网络一个数学性质,但有限宽网络的训练仍然是个谜。
「损失曲面的几何」:研究表明,深度神经网络的损失曲面有大量的「平坦盆地」,SGD 偏向于走进这些盆地,而盆地里的解通常泛化好。这是个连接「优化」和「泛化」的关键观察。
「特征学习」(Feature Learning)vs「核回归」(Kernel Regime):训练时网络是在「学新特征」还是「在固定核上做回归」?这是现在前沿研究的争论。
我提这些不是要在本篇详细展开(这都得专著),而是想告诉你:「神经网络是函数」这句话简单,但「这个函数怎么训成的」可以写出几十年的研究。深度学习是一个广阔的领域,有非常多有意思的问题。
三十五、神经网络与「智能」:一个哲学问题
最后聊点哲学。
「神经网络只是函数,它能算作智能吗?」
这是个哲学问题,没有标准答案。但我有个倾向性的看法。
反方观点:神经网络只是模式匹配,没有理解、没有意识、没有真正的推理。它再大也只是一个 stochastic parrot(随机鹦鹉)——重复训练数据里的模式而已。
正方观点:「智能」本身就是个模糊概念。如果一个系统能完成需要智能的任务(写文章、写代码、解题),我们没有理由不叫它「智能」。「真正的理解」如果不可定义不可测量,就是个空概念。
我自己倾向后者,但保留一点谨慎。当前的 LLM 已经在很多任务上展现了「类智能」的行为,但它们也表现出明显的局限——长程推理薄弱、易被欺骗、缺乏自我修正。
更有意思的问题是:现在的局限,是「函数视角的根本局限」吗?还是「目前规模/训练方法的局限」?
如果是前者,那我们需要在「函数」之外加点别的东西(比如符号系统、世界模型、强化学习反馈)。如果是后者,那继续 scaling 就行。
我个人猜测:两者都有。所以未来的 AI 一定是「神经网络 + 其他」的混合体,而不是纯 LLM。
三十六、给写代码的人的提示
如果你是写代码的人(程序员/工程师),本篇知识怎么对你的工作有帮助?
第一,写训练代码时永远问「我的输入输出是什么形状」。99% 的训练 bug 是 shape 错配。把每一层的输入输出形状都写在注释里,bug 数量会断崖式下降。
第二,调超参数时先调最敏感的几个。学习率 > batch size > 模型大小 > 优化器选择 > 正则化。前期不要一次调多个。
第三,画 loss 曲线。train loss + val loss 都要画。不画曲线就训模型,等于闭眼开车。
第四,梯度爆炸了用 grad clipping,梯度消失了换激活/初始化/归一化。这两个问题有标准对策,不要硬扛。
第五,先在小数据上跑通,再上大数据。别一开始就拉满 batch、拉满 epoch。先用 100 个样本能不能让模型 overfit?如果不能,模型/代码有问题。这是 Karpathy 的「neural networks recipe」第一条。
这些不是论文里的内容,是写代码人的「肌肉记忆」。希望对你有用。
三十七、给做研究的人的提示
如果你是做研究的人(研究生/博士),本篇内容怎么帮你?
第一,理解「函数视角」是论文创新的脚手架。你想改进 Transformer?请先回答:你在改它的哪部分函数?输入空间?输出空间?中间映射?参数化方式?训练方式?没有清晰回答,论文就缺骨架。
第二,理论与实验要互相校准。深度学习里很多「新现象」是实验先发现、理论后追上的(比如双重下降、grokking、emergent ability)。但也有理论指导实验的反例(比如 NTK、信息瓶颈)。两者都得跟。
第三,写作要把「直觉」放在「公式」前面。读者先要理解你为什么这么想,再才能消化你的公式。本系列的写作就是这种风格。
第四,复现比新研究更重要的时候。一个声称「我有新方法」的论文,如果你不能复现别人的 baseline,新方法的提升数字毫无意义。
第五,读经典。Cybenko 1989、Hornik 1991、Rumelhart 1986、LeCun 1998 ……这些老论文今天读起来仍然清晰、深刻。你越往新的读,越要回去读老的。
三十八、一些常见问题答疑
Q1:神经网络的「神经元」是什么?
A1:是「线性变换的一个输出维度 + 激活函数」的合称。\(\mathbf{h} = \text{ReLU}(W\mathbf{x} + \mathbf{b})\) 里 \(\mathbf{h}\) 是 \(h\) 维向量,每一维就是一个「神经元」。每个神经元有自己的权重行 \(\mathbf{w}_i^\top\) 和偏置 \(b_i\)。
Q2:偏置 \(\mathbf{b}\) 真的有用吗?
A2:有用。它让 \(W\mathbf{x} + \mathbf{b}\) 这条「超平面」可以不过原点,覆盖更广的函数空间。但有些现代架构里(比如某些 LLM),为了简化和数值稳定,会把 bias 去掉,由 LayerNorm 替代它的作用。
Q3:为什么 ReLU 在 0 不可导也能用?
A3:0 是一个测度为零的点,正常训练几乎不会精确踩到。即使踩到,框架里默认 ReLU 在 0 处的梯度是 0(或 1,看实现)。这叫「次梯度」(subgradient),数学上是合法的扩展。
Q4:为什么不用所有数据一次性算梯度?
A4:理论上是可以(叫 batch gradient descent)。但 1)数据装不进显存;2)每一步太慢;3)随机性其实有助于跳出局部最优。所以实际用 mini-batch SGD——每次用一小批样本估计梯度。
Q5:训练时 loss 不降怎么办?
A5:先排查「代码错」(没接梯度、没把 .train() 切回去、loss 算错)。然后排查「学习率」(太大太小都不行)。再排查「初始化」(爆炸或饱和)。再排查「数据」(脏数据、标签错)。最后才是「换模型/换损失」。
Q6:训练完 loss 很低,但用起来效果差?
A6:典型过拟合。检查 train loss vs val loss——如果 train 远低于 val,肯定过拟合。对策:加数据、加正则、减小模型、早停。
Q7:模型预测时为什么要 model.eval()?
A7:因为 Dropout 和 BatchNorm
在训练和推理时行为不同。Dropout
训练时随机丢,推理时关掉;BatchNorm 训练时用当前 batch
统计,推理时用累积统计。.eval()
切到推理模式。忘了切是新手最常踩的坑。
Q8:为什么有的模型用 Tanh 有的用 ReLU 有的用 GELU?
A8:历史 + 任务 + 经验三方面的结果。Tanh 在 RNN 时代是标配(输出有界,方便处理梯度),CNN 时代换成了 ReLU(训练快),Transformer 时代用 GELU(在大模型上略好)。下一篇详细讲。
Q9:参数初始化有那么重要吗?
A9:非常重要。初始化太大 → 梯度爆炸;太小 → 梯度消失。深度网络对初始化敏感得多。常用的有 Xavier 初始化、He 初始化、LSUV 等。Transformer 里还有「残差缩放」等技巧。
Q10:神经网络能保证一定收敛吗?
A10:理论上不能。损失曲面是非凸的,SGD 是局部搜索。但实践中,足够大的网络 + 合适的学习率 + 现代优化器(Adam)几乎总能收敛到一个「足够好」的解。这是工程奇迹,不是数学定理。
三十九、相关概念辨析
梯度(gradient)vs 导数(derivative):导数是单变量函数的「斜率」;梯度是多变量函数对每个变量的导数组成的向量。梯度指向「函数增加最快的方向」。
反向传播(backprop)vs 自动微分(autodiff):反向传播是自动微分的一个特例(reverse mode)。还有 forward mode,适合输入维度小输出维度大的情况。深度学习里几乎全用 reverse mode,因为输入维度(参数)远大于输出维度(loss 是一个数)。
SGD vs Adam:SGD 是基础梯度下降,每个参数同样的学习率。Adam 是「自适应学习率」,每个参数根据自己的历史梯度调整自己的学习率。Adam 对超参数不敏感,初学者首选;SGD 调好了泛化更好,老司机最爱。
Loss vs Cost:在大多数语境里,loss 指「单个样本的误差」,cost 指「整个数据集的平均误差」。但混用的情况很多,不必太纠结。
Epoch vs Iteration vs Step:epoch 是「遍历一次完整数据集」,iteration/step 是「一次梯度更新」。如果数据集 1000 样本,batch size 100,那 1 个 epoch 等于 10 个 step。
Train / Val / Test:训练集用来更新参数,验证集用来选超参/早停,测试集用来最终报告性能。测试集严禁用来调任何东西——一旦用了就不再是「测试集」了。
四十、本篇的局限与延伸
我必须承认本篇有几个没讲到的重要话题:
- 正则化:L1/L2、Dropout、数据增强、早停。这些是抗过拟合的基本工具。
- 优化器细节:Momentum、Adam、AdamW、Lion 等的具体公式。
- 学习率调度:warmup、cosine、step decay。LLM 训练的标配。
- 批归一化(BatchNorm)vs 层归一化(LayerNorm):训练稳定的关键。
- 残差连接(Residual):让深度网络可训练的革命。
- 梯度裁剪(gradient clipping):防爆。
这些都是「让神经网络真正能训起来」的工程技术。我把它们留到「LLM 训练实战」的篇章再讲,因为它们涉及大量代码和经验。
如果你等不及,我推荐:
- Karpathy 的视频系列:《Neural Networks: Zero to Hero》——从 micrograd 一路讲到 GPT。
- 花书第六章到第十章——经典中的经典。
- 《Hands-On Machine Learning》——工程导向,代码丰富。
四十一、收尾
好了,关于「神经网络是函数」这件事,我话很多。现在做个收束。
如果你只能从本篇带走一句话,我希望是:
神经网络 = 一个由参数 \(\theta\) 决定的函数族 + 一个用数据找好 \(\theta\) 的优化过程。
这一句把「结构」「参数」「训练」三件事打包了。带着它去看下一篇的激活函数、再下一篇的注意力、之后的 Transformer、最终的 LLM——你会发现所有的「新东西」都只是这个朴素结构的具体实例。
我们下一篇见。
上一篇:03. 矩阵乘法的几何与代数:从批量点积到 QKᵀ 下一篇:05. 激活函数:让网络「弯下来」的非线性魔法
同主题继续阅读
把当前热点继续串成多页阅读,而不是停在单篇消费。
【Transformer 与注意力机制】05. 激活函数:让网络「弯下来」的非线性魔法
上一篇我们论证了一件事——纯线性的网络再深,也只是一个线性变换。把 $W2(W1\mathbf{x} + \mathbf{b}1) + \mathbf{b}2$ 展开就是 $W'\mathbf{x} + \mathbf{b}'$。线性的复合还是线性,这是线性代数的铁律。
【Transformer 与注意力机制】03 矩阵乘法的两种视角
把矩阵乘法掰开成两种等价但风格不同的视角——『行 × 列』的点积视角和『列的线性组合』视角,最终落到 QK^T 的形状分析。
【Transformer 与注意力机制】02 向量与点积的几何直觉
从二维平面上的箭头开始,把『向量、内积、夹角、相似度』这几个概念用几何方式串起来,最后落到注意力公式里那个 QK^T 的来历。
【Transformer 与注意力机制】01|为什么要从这里开始
这是【Transformer 与注意力机制】系列的第一篇,承担两件事:一是把这套五十多篇文章为谁写、解决什么问题、彼此之间是什么关系交代清楚;二是为完全没基础的读者画出一条从向量、点积、矩阵乘法走到自注意力、再走到大语言模型的爬升路径,让你在投入时间之前先知道终点在哪、路上要经过哪些坎、读完之后你会、还不会做什么事。