🧠 第八章 神经网络训练
📄 一句话概括

4 个点的异或,单层网络输出全是 0.500,损失 0.6931(就是 ln2,完全瞎猜的值), 一步都没动;两层网络(2-4-1,17 个参数)输出 0.000/1.000/1.000/0.001,损失 0.0004。

📝 本节和前面几节的关系

第七章讲完了怎么把数据标出来。 从这一章起进真正的训练:数据和标签都有了,怎么让一个网络把它们记住。

一、一个神经元只做两件事

把输入乘上各自的权重加起来,再加一个偏置——这一步叫线性变换。 然后过一个非线性函数,把结果压到某个范围里——这一步叫激活。 就这两件事。没有任何神秘的地方。一个神经元的输出是「权重乘输入求和,过一下激活函数」。 所谓「网络」,就是把很多个这样的东西分层排起来,前一层的输出当后一层的输入。 所以神经网络这个名字里的「神经」,只是个比喻。 它跟生物神经元的关系,仅限于「多条输入汇成一条输出」这个形状。

二、一层能做的事很有限

一层网络画出来就是一条直线(高维时是一个超平面)。它只能回答「这个点在线的哪一边」。 异或这个问题,四个点是 (0,0)、(0,1)、(1,0)、(1,1),标签 0、1、1、0。 两个 1 在对角线上,任何一个方向画一条直线,都只能切对一个、切错一个。 Demo 里单层那列跑完是四个 0.500。 这不是「训练不充分」,是它压根没有可学的信号:两个正样本、两个负样本,梯度正好互相抵消成 0, 权重从第一步到最后一步一个数都没变。 损失 0.6931 就是 ln2。 二分类里「两个类别各占一半、模型完全不知道」的理论值就是 ln2,所以看到 0.693 就该明白: 模型什么都没学到。

三、两层做的事:先把点搬走

两层网络多了一个隐藏层。 它的作用是把输入搬到一个新空间里,在那个空间里,原本一条线切不开的点变成能切开了。 Demo 用的是 2-4-1:输入 2 维,隐藏层 4 维,输出 1 维。 参数一共 17 个(2×4 个权重加 4 个偏置,再加 4×1 个权重和 1 个偏置)。 结果四个点全对:0.000、1.000、1.000、0.001,损失 0.0004。 所以「神经网络强」这件事最朴素的说法是:它学的不只是那条线,还有「把数据搬到哪去」。 后者才是它比线性模型多出来的能力。

四、那 14 个参数是怎么定下来的

初始化是随机的。第一次前向,输出基本是乱猜。 然后算损失(预测和答案差多少),再把损失对每个参数的导数算出来——这叫反向传播。 导数告诉你「这个参数往哪个方向调会让损失变小」。 沿着导数反方向挪一小步,再前向、再反向,重复几千次。Demo 里跑了 4000 轮。 所以训练的本质是「猜一个方向,走一小步,再猜」。没有解析解,只有迭代。 这也是为什么它需要那么多算力。 补一句:反向传播本身不是「学习算法」,它只是求导的算法。 真正决定往哪走的是优化器,那是 8.1.3 的内容。

五、动手 Demo:异或:单层怎么调都只有 0.5,两层全对

用 4 个点的异或数据,分别训一个单层逻辑回归(2 个权重加 1 个偏置) 和一个 2-4-1 的两层网络(tanh 隐藏层加 sigmoid 输出)。 两者都用全量梯度下降跑 4000 轮,比最终输出和损失。

h = np.tanh(X @ W1 + b1)                 # 隐藏层:把 2 维搬到 4 维
p = H.sigmoid(h @ W2 + b2)
g = (p - yv) / 4                         # 输出层误差
gh = (g @ W2.T) * (1 - h * h)            # 反传到隐藏层
W1 -= 1.5 * (X.T @ gh)

实跑输出:

--------------------------------------------------------------------
一个神经元能做什么:XOR 为什么非要两层
--------------------------------------------------------------------
  样本                     4 个点:(0,0)(0,1)(1,0)(1,1)
  标签                     0、1、1、0(异或)
  输入     正确答案   单层输出   两层输出
  --------------------------------------
  (0, 0)          0      0.500      0.000
  (0, 1)          1      0.500      1.000
  (1, 0)          1      0.500      1.000
  (1, 1)          0      0.500      0.001

  单层参数                 3 个(2 个权重 + 1 个偏置)
  两层参数                 17 个
  单层损失                 0.6931
  两层损失                 0.0004

  单层那列四个数全是 0.500,损失 0.6931——这个数就是 ln2,也就是「完全瞎猜」的值。它一步都没动:四个样本里两个正两个负,梯度正好互相抵消成 0。
  就算不抵消,它也只能画一条直线。异或的两个 1 在对角线上,一条直线切不开。
  两层那列全部正确。多出来的 14 个参数干的事,是把输入先折到 4 维空间,在那个空间里异或就变成线性可分了。
  所以「神经网络强」这件事,最朴素的解释就是:它先把数据搬到另一个空间,再在那边画直线。

单层那列四个数一模一样,全是 0.500。这是它一开始的值,跑完 4000 轮还是这个值。 原因是四个样本的梯度加起来正好是 0,一步都迈不出去。 损失 0.6931 就是 ln2,二分类「完全不知道」的理论值。 以后看到这个数,不用想别的,就是模型没学到东西。 两层那列全对,损失 0.0004。对比 0.6931,差了三个数量级。 17 个参数里真正起作用的是隐藏层那 12 个——它们定义了「把平面折成什么样」。 输出层那 5 个只是在新平面里画一条线。 这里我用的隐藏层是 4 个神经元。少于 4 个也常常能解异或(3 个就够),但 4 个比较稳。 这不是定理,是经验。

30 秒实验

  1. 把隐藏层从 4 个改成 2 个,看还解不解得出来。
  2. 把激活函数从 tanh 换成 ReLU,看重跑十次有几次失败。
  3. 想一想:为什么单层网络在异或上的梯度恰好是 0?

常见误区

  1. 「一层不行就多训几轮」——异或上单层的梯度恒为 0,训多久都一样。
  2. 「损失 0.693 说明还差一点」——它就是 ln2,等于完全没学。
  3. 「隐藏层越多越好」——多一层多一堆参数,简单问题上只会更容易过拟合。
自测三问(点开对答案) 1. 一个神经元做哪两件事? —— 先做线性变换(权重乘输入求和加偏置),再过激活函数做非线性。 2. 为什么单层网络解不了异或? —— 单层只能画一条直线,异或的两个正样本在对角线上,任何直线都切不开。 3. 两层网络凭什么能解开? —— 隐藏层把输入搬到一个新空间,异或在那个空间里变成线性可分了。

知道了网络能干什么,下一节把它拆开:一层里到底有哪几样东西,参数是怎么数出来的。

相关笔记