一、先接上第 4 讲留下的缺口

第 4 讲结尾指出了 n-gram 的死穴:用计数表估计概率,见不到的组合就是 0,而且"苹果"和"香蕉"在表里是两个毫不相干的条目,没有举一反三的能力。

解法的方向也说了一半:把计数表换成一个函数。给这个函数喂一个上下文的向量(第 3 讲),它直接算出一个概率分布(第 4 讲),不需要先"见过"这个组合。

问题是——这个函数具体应该长什么样? 这一讲要盖的,就是这个最基础的积木:神经网络里"一层"到底是什么,以及为什么只有这一块积木还不够,必须再加一个看似很小的操作。

二、打个比方:一根只会拉伸的橡皮筋

假设你手里有一根橡皮筋,代表一条直线上的点。你只被允许对它做两种操作:均匀拉伸(把所有点到某个方向的距离,统一乘上一个倍数)和整体平移(把所有点一起挪个位置)。

不管你把这两个操作组合、重复多少次——拉伸完再拉伸,平移完再平移,交替做——橡皮筋出来还是一条直线。你没有办法用"拉伸+平移"这两个动作,把一条直线变成一个 S 形,或者对折成一个 V 字。要做到"弯折",你需要一个新的、性质完全不同的动作。

⭐ 这一讲要讲的核心内容,就是这个比方的数学版本:“矩阵乘法 + 加一个偏移”(第三节会看到,这正是第 3 讲讲的"变换")不管叠多少层,效果都等价于只做了一次——它就是那根只会拉伸和平移的橡皮筋。要让网络具备"弯折"的能力,必须引入一个新的操作,叫非线性(non-linearity)。

三、把"一层"钉成数学

一层:矩阵乘法加一个偏移

回忆第 3 讲:矩阵乘法的直觉是"对一批向量做同一种变换"。神经网络里的一层(layer),就是这个变换再加一个小动作:

y = Wx + b

x 是输入向量,W 是一个矩阵(第 3 讲的"变换"),b 是一个同样维度的向量,叫偏置(bias),作用是把变换后的结果整体挪一个位置——对应到第二节的比方,Wx 是"拉伸",+b 是"平移"。W 和 b 里的每一个数字,都是这一层的参数,训练(第 6 讲)要调的就是这些数字。

为什么叠多少层线性变换都没用

把两层这样的变换叠在一起会发生什么?

第一层:h = W₁x + b₁
第二层:y = W₂h + b₂

代入:
y = W₂(W₁x + b₁) + b₂
  = (W₂W₁)x + (W₂b₁ + b₂)
  = W'x + b'          ← 其中 W' = W₂W₁, b' = W₂b₁ + b₂

⭐ 最后一行是全讲最关键的一步:把两层的参数乘到一起、加到一起,结果依然是"某个矩阵乘以 x,再加某个偏置"——和一层的形式一模一样。不管你叠 2 层、20 层还是 200 层,只要每一层都是"矩阵乘法加偏置",最终折叠出来的,在数学上永远等价于一层。这就是第二节那根橡皮筋:反复拉伸平移,出来的还是直线。

⚠️ 这一路的操作严格来说叫仿射变换(affine transformation)——“线性变换"在数学上特指 y = Wx(没有偏置项 b 那部分),但机器学习的语境里"线性层"这个说法通常把偏置也算在内,本讲沿用这个习惯说法,只是这里先把这个术语上的松动点出来,避免你查资料时被两种说法绕晕。

引入非线性:只做一个动作,但换了整个游戏规则

打破"叠多少层都白叠"这件事,办法出奇地简单:在每一层的输出上,逐个数字套一个非线性函数 σ:

h = σ(Wx + b)

最常用的选择之一是 ReLU(Rectified Linear Unit),规则极其简单:负数变成 0,非负数不变:

ReLU(z) = max(0, z)

只要中间插了哪怕一个这样的非线性,第三节那套"合并成一层"的代数把戏就彻底失效了——σ(W₂ · σ(W₁x+b₁) + b₂) 没有办法再被拆开、合并成 W'x + b' 的形式,因为 σ 会在中间"折断"这条链条。

非线性 / 激活函数(activation function):逐个数字施加、破坏"矩阵乘法可以合并"这一性质的函数。它是神经网络能够拟合复杂函数的必要条件,没有它,网络无论多"深"都等价于一层。

一个可以手算的反例:XOR

光讲道理还是抽象,来看一个具体到可以手算验证的例子。**异或(XOR)**是一个只有 4 种输入的极简任务:

输入 (x₁, x₂)  →  输出
  (0, 0)       →   0
  (0, 1)       →   1
  (1, 0)       →   1
  (1, 1)       →   0

先证明:一个单层线性函数 y = w₁x₁ + w₂x₂ + b 无论如何都做不到这件事。 把 4 个数据点代进去,会得到一组互相矛盾的方程:

(0,0)→0:  b = 0
(1,0)→1:  w₁ + b = 1   →  w₁ = 1
(0,1)→1:  w₂ + b = 1   →  w₂ = 1
(1,1)→0:  w₁ + w₂ + b = 0   →   1 + 1 + 0 = 2 ≠ 0   ✗ 矛盾!

前三个点唯一确定了 w₁=1, w₂=1, b=0,但这组参数代入第四个点算出来是 2,不是要求的 0。没有任何一组 w₁, w₂, b 能同时满足全部 4 个点——这不是没找对参数,是这个函数的表达能力从结构上就不够,无论怎么调参数都不可能凑出这 4 个点。

现在加一层 ReLU 非线性,用下面这组(人工设计好的)参数:

h₁ = ReLU(x₁ + x₂)         第一个隐藏单元
h₂ = ReLU(x₁ + x₂ − 1)     第二个隐藏单元
y  = h₁ − 2h₂                输出层(这一层不需要非线性)

逐个代入验证:

输入 h₁ = ReLU(x₁+x₂) h₂ = ReLU(x₁+x₂−1) y = h₁−2h₂ 目标
(0,0) ReLU(0)=0 ReLU(−1)=0 0−0=0 0 ✓
(0,1) ReLU(1)=1 ReLU(0)=0 1−0=1 1 ✓
(1,0) ReLU(1)=1 ReLU(0)=0 1−0=1 1 ✓
(1,1) ReLU(2)=2 ReLU(1)=1 2−2=0 0 ✓

⭐ 四个全对。 同样是"矩阵乘法+偏置"这套积木,唯一的区别是中间多套了一层 ReLU,就从"结构上不可能"变成了"精确可解”。这不是巧合或者运气好凑出来的参数——它具体地、可验证地证明了非线性带来的不是"效果好一点",是表达能力的类别发生了变化。

把这样的"一层 + 非线性"多层堆叠起来,就是多层感知机(MLP,Multi-Layer Perceptron),也是"深度学习"里"深度"这个词最朴素的含义:层数堆得多。

Softmax:把输出接回"概率分布"

MLP 最后一层直接算出来的一串数字(术语叫 logits),可以是任意大小的正数负数,并不满足第 4 讲对"概率分布"的两条硬性要求(非负、加起来等于 1)。需要再套一个函数把它"整形"成合法的概率分布,这个函数叫 softmax:

softmax(z)ᵢ = exp(zᵢ) / Σⱼ exp(zⱼ)

直觉很直接:先用指数函数把每个数字都变成正数(exp 的输出永远大于 0),再除以总和,让所有数字的比例保持相对大小的同时,强制加起来等于 1。

小例子:如果模型对"好"“热"“香蕉"这三个候选词算出的 logits 是 [2.0, 1.0, -1.0]:

exp(2.0)=7.39,  exp(1.0)=2.72,  exp(-1.0)=0.37
总和 = 7.39+2.72+0.37 = 10.48

P(好)   = 7.39/10.48 ≈ 0.71
P(热)   = 2.72/10.48 ≈ 0.26
P(香蕉) = 0.37/10.48 ≈ 0.03

三个数字都非负、加起来等于 1——这正是第 4 讲对概率分布的定义。softmax 是整个模型从"一堆原始数字"接回"第 1 讲说的那个概率分布"的最后一步。

四、这一讲的局限:会算,但还不会"对”

到这里为止,我们拼出了一个完整的、可以从头算到尾的函数:输入一个向量,经过若干层"矩阵乘法 + ReLU”,最后套一个 softmax,输出一个合法的概率分布。

但这里有一个必须现在就说清楚的局限:W 和 b 里的每一个数字,目前都是随便设的(甚至是随机的)。上一节 XOR 的例子里,那组能解出正确答案的参数是人工凑出来的——现实中的任务远比 XOR 复杂,没有人能手工凑出正确答案。

⚠️ 一层的表达能力和"参数是否正确"是两件完全不同的事:这一讲证明了"只要有非线性,这个结构在理论上能表达 XOR 这样的函数",但没有回答"这组正确的参数要怎么找到"。随机初始化的网络,输出的会是一堆毫无意义的乱码概率。第 6 讲要解决的正是这个问题:怎么用数据自动地、一步步地把 W 和 b 调整到正确的值,而不是靠人工设计。

顺带一提这一讲没有细讲的一个代价:非线性让"一次性精确求解"变得不可能。像 y=Wx+b 这样的纯线性系统,理论上可以直接用解方程的办法一次性算出最优参数;一旦加了非线性,这条路就被堵死了,只能靠第 6 讲讲的那种"一步步试错、逐渐逼近"的迭代方法。表达能力的提升,是用"能不能一次性精确求解"换来的——这是这门课里第一次,但不会是最后一次,看到"多做一件事,就要放弃另一件事"。

五、和后面课程的关系

  • 第 6 讲直接回答这一讲留下的悬念:W 和 b 怎么从随机的乱码,被训练成有意义的参数。
  • 第 9、10 讲的 Transformer 架构里,“前馈层(feed-forward layer)“在结构上就是这一讲讲的"一层 + 非线性”,只是规模大得多、层数堆得更深;Q、K、V 的计算则是纯粹的矩阵乘法(第 3 讲),没有非线性。
  • softmax 不只用在这一讲说的"网络最终输出"上——第 9 讲的自注意力机制,要把"每个词该多关注哪些词"这件事变成一组合法的权重(非负、加起来等于 1),用的正是同一个 softmax。
  • 这一讲手算的 XOR 例子,也是这门课"纯 Python + NumPy 手写实验"的第一个真正的小样本——Lab 1 会把这一讲的"一层 + ReLU”,连同第 6 讲的训练过程,从头写成可以跑起来的代码。

六、本讲小结

  • 一层神经网络 = 矩阵乘法加一个偏置:y = Wx + b,本质是第 3 讲讲的"对向量做变换"。
  • ⭐ 纯线性变换叠多少层都等价于一层——两层 y = W₂(W₁x+b₁)+b₂ 可以严格代数化简成 y = W'x + b',和一层同一种形式,没有获得任何额外能力。
  • 非线性(如 ReLU:max(0,x))打破了这种可合并性,让堆叠层数第一次真正带来表达能力的提升。
  • ⭐ XOR 是可以手算验证的反例:单层线性无论如何都无法拟合(四个方程互相矛盾),加一层 ReLU 之后存在一组精确解——这具体证明了非线性带来的是"能不能做到"的类别变化,不是效果的微调。
  • softmax 把网络最后一层的原始输出(logits)转换成满足第 4 讲两条规矩的合法概率分布:softmax(z)ᵢ = exp(zᵢ)/Σexp(zⱼ)。
  • ⚠️ 表达能力和参数是否正确是两件事:这一讲拼出的结构能"表示"复杂函数,但参数目前是随机的、没有意义;非线性同时也让"一次性精确求解"变得不可能,只能靠迭代逼近——这是第 6 讲的主题。

思考题

  1. 用第三节的代数推导方式,验证"三层纯线性网络"依然可以化简成 y = W'x + b' 的形式(提示:把第三层也代入,重复一次同样的展开)。
  2. XOR 例子里,h₂ = ReLU(x₁+x₂−1) 这个隐藏单元,直觉上在检测什么条件(提示:只有哪个输入组合能让 x₁+x₂−1 大于 0)?
  3. 如果把 XOR 例子里的 ReLU 换成"什么都不做"(也就是恒等函数 σ(z)=z),这组参数还能正确输出 XOR 吗?动手代入 (1,1) 这一个点验证一下。
  4. softmax 例子里,如果把三个 logits 同时加上 100(变成 [102, 101, 99]),最终算出的三个概率会不会变?为什么(提示:exp(a+c)/Σexp(b+c) 能不能把 exp(c) 提出来约掉)?
  5. 本讲说"非线性让一次性精确求解变得不可能,只能靠迭代逼近"——结合第四节最后一句"多做一件事就要放弃另一件事",你觉得这门课后面还会在哪些地方看到类似的权衡(不要求答对,可以先猜,这是训练你在讲义里主动找这条线索的习惯)?