📕 第4章 类神经网络的基础
📄 一句话概括

激励函数是那个「弯一下」的环节。 没有它,叠多少层都等于一层——因为两个线性变换可以合并成一个矩阵。 三种常见的:sigmoid 把任意实数压到 0~1、tanh 压到 -1~1、ReLU 把负数截成 0。 它们的关键差别在导数: sigmoid 在 z=5 时导数只有 0.0066,tanh 在 5 时 0.0002,ReLU 在正数区恒为 1。 这个数决定了梯度能传多远。

📝 本节和前面几节的关系

上一节把 f 当成阶跃函数,那是最粗糙的选择。这一节看真实网络里用的三种。 这一节和 4.7 节的反向传播直接相关: 反向传播里那个「乘一个因子」的因子,就是激励函数的导数。 第 5 章的卷积 ReLU 层,就是把这里的 ReLU 用在卷积输出上。

一、为什么必须非线性

假设没有激励函数,两层就是 y = W₂(W₁x + b₁) + b₂ = (W₂W₁)x + (W₂b₁ + b₂)。 括号里还是个矩阵和一个向量——等价于一层。 所以「深度」的价值,完全建立在每层之间插一个非线性函数上。 非线性把「能表示的函数族」撑大了,层数才有意义。 这也解释了一个常见困惑: 为什么把激励函数去掉,模型立刻退化成线性回归?不是因为少了什么神奇的东西, 是因为它在数学上真的就是线性回归。

二、sigmoid:把实数压到 0 到 1

σ(z) = 1 / (1 + e⁻ᶻ)。z 从负无穷到正无穷,输出平滑地从 0 升到 1,z=0 时正好 0.5。 它的导数有个漂亮的闭式:σ'(z) = σ(z)(1 - σ(z)),最大值 0.25(在 z=0 处)。 这个 0.25 是个隐患——每穿过一层,梯度最多只剩四分之一。 z=5 时 σ 已经是 0.9933,导数降到 0.0066;z=-5 同理。 两端都饱和,梯度几乎为零,这就是「梯度消失」的字面含义。

三、tanh:把实数压到 -1 到 1

tanh(z) 的形状和 sigmoid 一样,但输出以 0 为中心,范围 -1 到 1。 导数 1 - tanh²,在 z=0 处等于 1——比 sigmoid 的最大 0.25 大四倍。 为什么「以 0 为中心」重要? 因为下一层的输入如果不是 0 均值,梯度方向会系统性偏向一侧,训练会走 Z 字。tanh 缓解了这个问题。 但饱和问题还在:z=5 时导数 0.0002,比 sigmoid 还小。所以 tanh 适合浅层,深层还是会消失。

四、ReLU:负数截成 0

ReLU(z) = max(0, z)。正数原样通过,负数一律 0。导数更简单:正数处 1,负数处 0。 这个「1」是关键。梯度穿过 ReLU 不会被缩小,所以深层网络终于训得动了。 2012 年 AlexNet 能堆到 8 层,ReLU 是必要条件之一。 代价是「死亡 ReLU」:一个神经元如果所有输入的 z 都是负数,它的梯度永远是 0,权重再也不更新, 等于这个神经元废了。学习率太大时,一整片神经元可能同时死掉。

五、选哪个

经验规则:隐层默认 ReLU(快、不消失); 输出层看任务——二分类用 sigmoid、多分类用 softmax、回归直接不加。 RNN 里常用 tanh,因为它的输出有界,反复乘不会爆掉。 第 6 章的 LSTM 内部就同时用了 sigmoid 和 tanh,各管一件事。 还有一个折中叫 Leaky ReLU:负数区给一个很小的斜率(比如 0.01),避免完全死掉。 名字里的 leak 就是「漏一点」。

六、动手 Demo:三种形状,三种脾气

在 z = -3、-1、0、1、3、5 六个点上,把 sigmoid、tanh、ReLU 的函数值和导数一起打出来。 重点看两端的导数。

import numpy as np

def sig(z):
    return 1.0 / (1.0 + np.exp(-z))

def relu(z):
    return max(0.0, z)

for z in (-3.0, -1.0, 0.0, 1.0, 3.0, 5.0):
    s = sig(z)
    t = np.tanh(z)
    print("%5.1f  sig %.4f  导数 %.4f  tanh %.4f  导数 %.4f"
          % (z, s, s * (1 - s), t, 1 - t * t))

实跑输出:

--------------------------------------------------------------------
激励函数:三种形状,三种脾气
--------------------------------------------------------------------

  z     sigmoid  导数    tanh    导数    ReLU  导数
  -------------------------------------------------
  -3.0  0.0474   0.0452  -0.9951 0.0099  0.0   0
  -1.0  0.2689   0.1966  -0.7616 0.4200  0.0   0
  0.0   0.5000   0.2500  0.0000  1.0000  0.0   0
  1.0   0.7311   0.1966  0.7616  0.4200  1.0   1
  3.0   0.9526   0.0452  0.9951  0.0099  3.0   1
  5.0   0.9933   0.0066  0.9999  0.0002  5.0   1

  三个数最该记住:

  **sigmoid 在 z=5 时导数是 0.0066**——几乎为 0。这就是「梯度消失」的字面意思:
  值已经饱和到 0.9933,再往上推它也变不了多少,所以传回来的梯度被压得几乎没有了。

  **tanh 的形状和 sigmoid 一样,但以 0 为中心**,输出范围是 -1 到 1。
  以 0 为中心的好处是下一层的输入不会全是正数,梯度方向不至于总往一边偏。

  **ReLU 在负数区导数直接是 0。**好处是正数区导数恒为 1,梯度不会越传越小;
  坏处是一个神经元如果一直落在负数区,它的梯度永远是 0,从此再也学不动——这叫「死亡 ReLU」。

z=5 那一行最能说明问题:sigmoid 值 0.9933、导数 0.0066;tanh 值 0.9999、导数 0.0002。 两个都饱和了,梯度几乎传不回去。 tanh 的导数在 z=0 处是 1.0000,sigmoid 只有 0.2500。 同样一层,tanh 能让梯度多保留四倍。这就是为什么早期深层网络爱用 tanh。 ReLU 那一列:负数区全是 0.0,正数区原样通过,导数不是 0 就是 1。 「要么全过要么全挡」,简单粗暴,但正是这种不衰减让深层能训。 把这张表和 4.7 节连起来看:反向传播里「穿过激励函数」那一步,乘的就是这一列的导数。 导数小,梯度就小;导数等于 0,梯度就断。

30 秒实验

  1. 算一下 sigmoid 在 z=10 时的导数,和 z=5 比,小了多少倍?
  2. 把 ReLU 换成 max(0.01*z, z)(Leaky ReLU),负数区的导数变成多少?
  3. 三层全用 sigmoid,每层导数最大 0.25,梯度传回第一层时最多被乘了多少倍?

常见误区

  1. 以为激励函数可有可无。去掉它,整个网络在数学上就是一个线性变换,层数完全白搭。
  2. 以为 sigmoid 已经过时了。输出层做二分类还在用它,因为输出要解释成概率。 过时的是「隐层用 sigmoid」。
  3. 以为 ReLU 不会出问题。学习率设大了会死一片,训练时看到损失突然不动、准确率卡住, 先怀疑这个。
自测三问(点开对答案) 1. 为什么没有非线性的多层网络等价于一层? —— 因为两个线性变换的复合还是线性变换:W₂(W₁x) = (W₂W₁)x,括号里可以先乘成一个矩阵。 2. sigmoid 的导数最大值是多少?这意味着什么? —— 0.25,在 z=0 处取到。 意味着每穿过一层 sigmoid,梯度最多只剩四分之一, 十层之后就是百万分之一量级——这是梯度消失的直接原因。 3. ReLU 的「死亡」是怎么发生的? —— 某个神经元的输入加权和长期为负,ReLU 输出恒为 0,导数恒为 0,梯度传不回来,权重永远不更新, 这个神经元就废了。

结构(神经元)和零件(激励函数)都齐了,缺的是「怎么调权重」。 下一节看历史上最先出现的两种学习规则。

相关笔记