神经网络 入门

读懂任何深度学习论文之前所需的最少神经网络解剖学。4 个短小主题:每个模型最底下的那一个神经元、 让非线性成为可能的激活函数(以及为什么非线性是必需的)、神经元怎么组成层, 以及把它们串起来的前向传播 —— 输入箭头 → 一层 → 一层 → 输出。

01

单个神经元

每个现代模型的「原子」。

随便拿一篇深度学习论文,把它的计算一路往下追,最后一定会落到同一样东西上:神经元。 几个数进来,按一组权重组合一下,加上一个偏置,过一个非线性函数,出一个数。 几十亿个这样的东西按正确方式堆起来,就是一个 Transformer。我们从一个开始。

单个神经元的数学就一行:

output = activation(W · x + b)

四样东西,各司其职:

  • 输入 x —— 进来的一串数字。可以是原始特征 (像素、面积、一个 token 的嵌入),也可以是上一层的输出。
  • 权重 W —— 每个输入对应一个数。 告诉这个神经元每个输入有多重要、是正向还是反向。这些是训练要学的东西。
  • 偏置 b —— 一个标量,加到加权和上。 让神经元能独立于输入,把激活值整体上下挪一挪。
  • 激活函数 —— 一个非线性函数,把加权和变成神经元的输出。第 2 节的主题。

具体例子。两个输入、一个神经元、ReLU 激活。取 x = (1.5, −0.7)W = (0.8, −0.3)b = 0.2:

  W · x       =  0.8 · 1.5  +  (−0.3) · (−0.7)
              =  1.20      +  0.21
              =  1.41

  W · x + b   =  1.41 + 0.20  =  1.61

  ReLU(1.61)  =  max(0, 1.61)  =  1.61   ← 神经元输出
output = activation(W · x + b)w1 = 0.8w2 = -0.31.5x1-0.7x2ΣΣReLUReLU输入和权重都摆好了 —— 但还没开始算。
1 / 4
一个神经元:输入的加权和、加上偏置、过一个非线性激活。每个现代模型都是用这个搭起来的。

W · x 那一部分,就是线性代数 primer §5 里的点积。权重向量决定了 「什么样的输入模式」会激活这个神经元;任何点积都可以看成一个相似度评分, 所以 W · x 衡量当前输入「有多像」这个神经元在找的东西。 点积大,激活高;点积小(或为负),激活低。

偏置就是一个平移 —— 它定义了「当加权和为 0 时神经元的默认输出」。 没有偏置,每个神经元在输入全部抵消时都只能输出 activation(0); 有了偏置,神经元就可以偏向开火、或偏向沉默。 正是偏置让网络能表达「不过原点」的关系。

「神经元」这个比喻从哪来?粗略上来自生物学。生物神经元在树突上汇总信号, 如果总和过了阈值,就沿轴突放出一个电脉冲。本 primer 里的人工神经元是它一个 非常粗略的近似:加权和 + 类似阈值的非线性。生物学和数学早就分道扬镳了, 现代深度网络在任何有意义的层面上,都不是大脑的模型。但名字一直没改。

单独一个神经元,本身就是「线性分类器 + 一个挤压函数」 —— 跟监督学习 primer 里的线性回归 几乎一回事。从「神经元」跨到「神经网络」,靠的是把很多神经元并排放 (§3)再把这些并排堆成多层(§4)。 但每一个神经元本身,一路到 GPT 级模型,都还是这么简单。

在 Transformer 里:一个 attention head 的输出、前馈层、value 投影 —— Transformer 里每一个可学习操作,都是由这种形式的神经元组成的, 只是被堆成了更大的矩阵、再加上注意力和残差连接。打开一个 700 亿参数的 LLM, 最底下没有什么特别的东西,就是 700 亿份这个 W · x + b, 按正确的拓扑粘起来。

02

激活函数(Activation)

把一堆矩阵乘法变成「真正强大的东西」靠的就是这一道非线性。

§1 里那个神经元,先做加权和 W · x + b,再套一个激活函数。加权和那部分简单 —— 就是线性代数。真正的魔法在激活函数。没有它,再深的神经网络,表达力也不会超过一层线性变换。

论证如下:两层线性层叠起来、中间不加激活,算出来是W₂ · (W₁ · x + b₁) + b₂。把乘法分配一下,就变成(W₂ · W₁) · x + (W₂ · b₁ + b₂)。两层在代数上塌陷成单层等价的线性层, 权重是 W₂ · W₁,偏置是 W₂ · b₁ + b₂。再叠一百层, 结果还是单一线性函数。再深,也只是给一根直线套了花架子。

激活函数,就是阻止这种塌陷的东西。在层之间塞一个非线性 —— 任何不是直线的函数都行 —— 多层就再也合并不成一层了。叠加真的能增加表达力。万能逼近定理也是这时候才生效: 足够深 + 带非线性激活的网络,基本上能逼近任何连续函数。

四种激活函数,基本能覆盖你会碰到的所有场景:

  • ReLU —— max(0, x)。正数原样通过,负数变成 0。 简单粗暴:一次比较,没有任何超越函数调用。快、对梯度友好(导数只有 1 或 0), 从 2010 年前后开始就是绝大多数前馈层的默认选择。
  • Sigmoid —— σ(x) = 1 / (1 + e^(−x))。 从 0 到 1 的平滑 S 形。最早的神经网络激活,适合「输出必须落在 [0, 1]」 (比如预测一个概率)的场景。隐藏层里基本已被替换,因为两端饱和处梯度会消失。
  • Tanh —— tanh(x)。从 −1 到 1 的 S 形 —— 可以看作零中心的 sigmoid。很多老式 RNN(LSTM、GRU)用它; 需要「零中心输出」时仍然常见。
  • GELU —— x · Φ(x),其中 Φ 是高斯 CDF。 长得像「带一点负尾巴」的平滑 ReLU。现代 Transformer 前馈层的主流激活 (BERT、GPT 及几乎所有近期 LLM 都用)。 比 ReLU 的梯度流更好,代价是多一次超越函数计算。
-33xReLUmax(0, x)简单粗暴。正数原样通过、负数清零。2010 年前后开始的隐藏层主流激活。
1 / 4
四种激活函数。选一个(基本上 ReLU 或 GELU);网络其余部分都一样。

看 demo 时三件事值得留意:

  • 四个都是非线性的。没有哪一个是直线 —— 这是关键。 ReLU 在 x = 0 处那一个折点就已经够「非线性」, 足以解锁万能逼近;sigmoid / tanh / GELU 那条平滑曲线,带来的是连续可导的同种性质。
  • sigmoid 和 tanh 两端会饱和。离 0 远的地方,它们的导数缩到接近 0。 反向传播(微积分 primer §3)时,这些微小梯度在多层间相乘, 信号传到前几层就「消失」了。这就是为什么现在 ReLU 和 GELU 大行其道 —— 它们的梯度不会消失。
  • ReLU 有个「死区」。负输入下,输出和梯度都精确为 0 —— 一个神经元如果整轮训练都待在负区,就永远学不到任何东西。Leaky ReLU、PReLU、ELU、 GELU 等变种,部分就是为解决这个问题而存在。

选激活函数几乎从来不是影响最大的决策;现代经验是「ReLU 几乎万能、Transformer 默认用 GELU、 要的是概率才用 sigmoid」。先操心数据、架构、优化器; 剩下的东西都搞清楚之后,再回头来调激活。

在 Transformer 里:每个 Transformer 块里的前馈子层, 算的是 GELU(x · W₁ + b₁) · W₂ + b₂ —— 两层线性中间夹一个 GELU。 架构图里的「FFN」「MLP」就是这个。更新的变种(LLaMA、PaLM 用的 SwiGLU) 把 GELU 换成了一种带门控的稍微复杂的结构,但原则一模一样:插一个非线性,否则整摞会塌陷成单层线性映射。

03

层(Layers)

一排神经元看着同一个输入,被组装成一个矩阵。

§1 那个神经元,一次只产出一个数 —— 这是个瓶颈,大多数实用模型每一步要输出很多个数。 最自然的解法,就是:把好几个神经元并排放,让它们看同一个输入, 每个都用自己的权重和偏置,把它们的输出收成一个新向量。就这样。 一个层,就是一排看着同一个输入的神经元。

每个网络都有三种角色:

  • 输入层(input layer)—— 严格来说算不上「层」 —— 就是模型收到的输入向量 x。它的大小由问题决定 (特征数、像素数、一个 token 嵌入的维度)。
  • 隐藏层(hidden layers)—— 网络的中段。每个隐藏层都接上一层的输出, 用自己的 Wb,产出给下一层用的新向量。 所谓「深度」学习,就是这种层有很多个。
  • 输出层(output layer)—— 最后一层。它的大小由任务决定: 回归是 1,ImageNet 10 类子集是 10,LLM 词表是 5 万。

把神经元摞成一层后,线性代数 primer 就把「一排点积」变成了一次「矩阵 × 向量」。 如果一层有 m 个输入、n 个输出:

h = activation(W · x + b)

和 §1 同样的公式 —— 只是现在 W 是个 n × m 矩阵(每个神经元一行)、b 是长度 n 的向量、输出 h 是长度 n 的向量。 线性代数 primer §6(矩阵乘法)负责所有的记账工作。 在整个计算机科学里,「矩阵乘向量」最重要的应用,就是神经网络的层。

具体例子。2 个输入、一层 3 个神经元、ReLU 激活。取 x = (1.5, −0.7):

         x = ( 1.5, −0.7 )

  W (3 × 2)  =  ┌  0.8   −0.3  ┐      ← 神经元 1 的权重
                │ −0.4    0.6  │      ← 神经元 2 的权重
                └  0.5    0.9  ┘      ← 神经元 3 的权重

  b          =  ( 0.2,  0.1, −0.5 )

  W · x      =  ( 0.8·1.5 + (−0.3)·(−0.7),
                  −0.4·1.5 +  0.6 ·(−0.7),
                   0.5·1.5 +  0.9 ·(−0.7) )
             =  ( 1.41, −1.02, 0.12 )

  + b        =  ( 1.61, −0.92, −0.38 )

  ReLU(·)    =  ( 1.61,  0.00,  0.00 )    ← 一层的输出
h = activation(W · x + b)1.5x1-0.7x2n1b = +0.2n2b = +0.1n3b = -0.5两个输入接到三个神经元。每个神经元有自己的一行 W 和自己的偏置。
1 / 3
三个神经元共享两个输入。W 矩阵把它们的权重逐行排好;一次矩阵乘法替代三次点积。

描述任何一层,只需要两个维度:

  • 宽度(width)。这一层有多少个神经元 —— 也就是输出维度。 宽度越大 = 每层参数越多 = 每层潜在表达力越强。
  • 深度(depth)。叠了多少层。深度越大 = 模型能反复执行「提特征、再组合、再提特征」的轮数越多。

现代模型设计就是在「宽 vs 深」的权衡里寻找最优。加宽是平方级地加参数 (输入宽度 w 的一层,输出也是 w,就有 个权重)。 加深是线性地加(再加一层宽度 w,只多 个权重, 跟前面有多少层无关)。常见规模:

  • 表格数据用的小型 MLP。2-3 个隐藏层,每层宽度 64-256。 总共几万参数。
  • ResNet-50(图像分类)。约 50 层,约 2500 万参数。 2018 年左右 ImageNet 上的 SOTA。
  • LLaMA 3(70B)。80 个 Transformer 块,每块里有多个隐藏宽度 8192 的子层。 700 亿参数。

无论规模多大,一层内部的运算永远是 §1 那条 activation(W · x + b) —— 只是矩阵更大。

在 Transformer 里:一个 Transformer 块里包含若干个层, 每个都是上面那种形式。注意力子层把每个输入向量过三个可学习矩阵 (Q、K、V 投影 —— 每个都是这里说的一个「层」)。前馈子层是两层中间夹一个 GELU (§2 的尾注)。LayerNorm 和残差连接包在外面。一个 700 亿参数的 LLM, 就是 80 个这种块串起来。同样的 W · x + b 积木,叠上一万次, 摆成一个非常特别的拓扑。

04

前向传播(Forward Pass)

把输入按顺序过一遍每一层 —— 那就是模型「在做」的事。

§3 给了你一层;「深度」学习给你很多层。前向传播就是把这些层一起用起来 的简单配方:把输入喂给第一层、把第一层的输出喂给第二层、把第二层的输出喂给第三层, 如此下去,直到最后一层产出模型的预测。模型表示的那个函数,就是每一层函数的复合。

一行数学就够了:

ŷ = fL( … f2( f1(x) ) … )

其中每个 fi 都是 §3 那种形式的一层activation(Wi · hi−1 + bi)。 前向传播就是函数复合 —— 微积分 primer §3(链式法则)里的概念,只是这次从「模型自己」的 角度看,而不是从「优化器」的角度看。

具体例子。一个小 MLP:2 输入 → 3 神经元隐藏层(ReLU)→ 1 神经元输出层(回归,无激活)。 取 x = (1.5, −0.7)。第 1 层在 §3 里已经算过了,输出 h₁ = (1.61, 0, 0)。 第 2 层接着算出最终预测:

  第 1 层(§3 已算)
  ────────────────────────────────
  x  = (1.5, −0.7)
  W₁ · x + b₁ = (1.61, −0.92, −0.38)
  h₁ = ReLU(·) = (1.61, 0, 0)

  第 2 层(输出)
  ────────────────────────────────
  W₂ = ( 0.6,  −0.2,  0.4 )     (只有一行,因为输出是标量)
  b₂ = 0.1

  W₂ · h₁     =  0.6·1.61 + (−0.2)·0 + 0.4·0  =  0.966
  W₂ · h₁ + b₂  =  0.966 + 0.1  =  1.066

  ŷ = 1.066    ← 模型对 x = (1.5, −0.7) 的预测
ŷ = f₂(f₁(x))输入隐藏层ŷ1.5-0.7h1h2h3ŷ输入 x = (1.5, −0.7)。前面有两层,权重已经设好。
1 / 3
把 x = (1.5, −0.7) 过两层。最后出 ŷ = 1.066。这就是「模型」对一个输入所做的事。

这就是整个模型:一个把 2 维输入 (1.5, −0.7) 映射成标量输出 1.066的函数。训练,就是在所有权重和偏置 —— 每个 Wibi —— 上搜索,让 ŷ 在整个数据集上尽可能接近真实标签。 监督学习 primer §3 的优化、梯度下降 primer 的训练循环,做的就是这件事,重复几十亿次。

关于前向传播,有三点要记住:

  • 它完全是确定性的。权重定下来后,前向传播是个纯函数: 同样的输入总是给出同样的输出。现代 LLM 那种「同一个 prompt 给出不同回答」的随机性, 来自对输出分布的采样(概率统计 primer §2),并不是网络内部有什么随机的东西。
  • 它高度并行。每一层的计算就是一次矩阵乘法 —— 这正是 GPU 设计出来要快速做的事。现代加速器在一个 700 亿参数 LLM 上跑一次前向, 单个输入大概 50ms。
  • 推理时和训练时形状一样。用一个训好的模型(推理)时,你做的只是跑前向。 训练在前向之上再叠一次反向,来算梯度(微积分 primer §3); 但前向那一段两种场景完全相同。

训练跟前向传播什么关系?三步,重复几百万次:

  • 前向传播 —— 把输入过一遍每一层,基于预测算出损失。
  • 反向传播 —— 沿着每一层倒着走一遍,把局部梯度乘起来(链式法则), 得到每个权重的 ∂L / ∂Wi
  • 更新 —— 对每个 Wibi应用一次梯度下降步(梯度下降 primer §1)。

前向传播只是这个循环里的三分之一,但它是唯一一个会在生产环境跑的三分之一。 模型训好以后,每次你调 ChatGPT API、每张扩散模型生成的图、每个 AlphaFold 预测的蛋白质 —— 都是一次前向传播。

在 Transformer 里:前向传播把输入 token 过一遍 token 嵌入 → 80 个 Transformer 块(每块里有注意力、残差、LayerNorm、§3 提到的前馈子层)→ 一次到词表大小的 线性投影 → softmax 得到下一个 token 的分布。从你的视角看,ChatGPT 在打字回复你, 就是同一张网络上千次前向传播,一个输出 token 一次。 Transformer 是架构;前向传播是它在做的事