大模型--ReLU激活函数--31

1 参考

“死亡”ReLUs
邱锡鹏老师的《神经网络与深度学习》

2. 基础

Sigmoid型函数的两端饱和,
ReLU函数为左饱和函数,且在x > 0时导数为1,在一定程度上缓解了神经网络的梯度消失问题,加速梯度下降的收敛速度。



ReLU也是非线性函数,它将低于或等于 0 的神经元输入都计算成 0。

z = np.maximum(0, np.dot(W, x))  # forward pass
dz_dW = np.outer(z > 0, x)  # backward pass: local gradient for W

反向传播比较难理解:

  • z > 0:这部分创建了一个布尔掩码,
    其大小与 z 相同。对于 z 中每一个元素,如果该元素大于零,则相应位置的布尔值为 True(或等效地转换为1),否则为 False(或0)。
  • np.outer(..., x),这里我们用的是布尔掩码(经过隐式转换成1s和0s)和输入向量 x 的外积。结果是一个形状为 (len(z), len(x)) 的矩阵,也就是权重矩阵 W 的梯度。
    当 z[i] > 0 时,dz_dW[i, :] 等于 x;
    当 z[i] <= 0 时,dz_dW[i, :] 全部为零。
    ReLU 的导数在正区域是1,在非正区域是0。
>>> import numpy
>>> x = [1, 2, 0, -6]
>>> z = np.maximum(0, np.dot(W, x))
>>> z
array([0, 5])
>>> z > 0
array([False,  True])
>>> dz_dW = np.outer(z > 0, x)
array([[ 0,  0,  0,  0],
       [ 1,  2,  0, -6]])
>>> x
[1, 2, 0, -6]
>>> W
[[1, 2, 1, 1], [1, 2, 3, 0]]

观察上述代码你会发现,当前向传递中一个神经元的值恒等于 0(即zi=0表示该神经元未被激活),该神经元对应的权重的梯度将为0,这时权重得不到更新。这就会导致所谓的“死亡”ReLU问题。


w用什么参数来更新 看z 如果z>0 则用输入x更新 如果z<0 则不用更新

如果一个ReLU 神经元由于被不恰当地初始化等于 0或是其对应的参数在训练过程中由于大幅度的更新而接近于 0(这时在下一样本的计算中该神经元的值就会趋于为 0,随着而来的是权重的梯度为 0,权重无法更新,导致该神经元的值恒为 0),那么这个神经元将永远处于死亡状态。这就是“死亡” ReLU。这就像是永恒的,无法恢复的大脑损伤。有时,你将整个训练数据集放入一个训练过的网络中进行前向计算,你可能会发现大部分(如 40% )的神经元的值一直恒为零。

所以,在使用 ReLUs 时,要警惕死亡ReLUs,这些神经元在整个训练数据集中任一样本中都不会被激活,而是处于死亡状态。神经元在训练过程中的“死亡”,通常是学习率过大造成的。

np.dot

np.dot(a, b) 得出的是一个标量
np.dot(A, v) 等价于 A @ v (@ 是 矩阵乘法运算符)
np.dot(A, B) 等价于 A @ B

np.outer

np.outer 函数用于计算两个向量的外积(outer product)。外积是两个向量之间的一种乘法,其结果是一个矩阵,而不是一个标量。

两个向量的叉乘,又叫向量积、外积、叉积,叉乘的运算结果是一个向量而不是一个标量。并且两个向量的叉积与这两个向量组成的坐标平面垂直。

定义:如果 a 和 b 分别是长度为 m 和 n 的两个一维数组,那么 np.outer(a, b) 的结果是一个形状为 (m, n) 的矩阵 C,其中每个元素 C[i, j] = a[i] * b[j]。

如果 a = [1, 2] 和 b = [3, 4, 5],那么 np.outer(a, b) 将产生如下矩阵
[[3, 4, 5],
[6, 8, 10]]
np.outer 是 NumPy 提供的一个强大工具,特别适合用来创建基于两个向量的所有可能配对的product矩阵

posted @ 2024-12-11 12:00  jack-chen666  阅读(30)  评论(0编辑  收藏  举报