一直以来自己对于 ML 模型中激活函数的概念和作用都比较模糊。

今天阅读了一篇 知乎文章,文章主要介绍了 ReLU 函数能够取代 Sigmoid 作为层与层之间的激活函数的几个原因,大致可总结为以下 2 点:

  • ReLU 能够防止 Sigmoid 由于其梯度被限制在一个很小的区域((0,0.25))而导致的参数更新多层模型之间传播的梯度消失现象,以及
  • ReLU 函数具有「单向饱和」的特点。

「单向饱和」,也是 ReLU 比 Sigmoid 更适合作为层与层之间的激活函数的原因之一。

Sigmoid 函数是双向饱和的,意思是朝着正负两个方向,函数值都会饱和;但 ReLU 函数是单侧饱和的,意思是只有朝着负方向,函数值才会饱和。严格意义上来说,将 ReLU 函数值为 0 的部分称作饱和是不正确的 (饱和应该是取值趋近于0),但效果和饱和是一样的。

单侧饱和有什么好处?让我们把神经元想象为检测某种特定特征的开关,高层神经元负责检测高级的/抽象的特征 (有着更丰富的语义信息),例如眼睛或者轮胎;低层神经元负责检测低级的/具象的特征,例如曲线或者边缘。

当开关处于开启状态,说明在输入范围内检测到了对应的特征,且正值越大代表特征越明显。假如某个神经元负责检测边缘,则(学习到的特征的)正值越大代表边缘区分越明显 (sharp)。

那么负值越小代表什么意思呢?直觉上来说,用负值代表检测特征的缺失是合理的,但用负值的大小代表缺失的程度就不太合理,难道缺失也有程度吗?

此外,虽然 ReLU 具有「单向饱和」的特点,它却容易产生「神经元死亡」的问题 —— 也就是 ReLU 的梯度决定了 ReLU 所作用的这一层神经元的参数的更新方向,在一次更新中,是朝着统一方向更新的(同时变大/变小)。

这使得有些不该变大/变小的参数在某次更新中被迫变大/变小,最终的结果是由于锯齿化的训练轨迹导致模型收敛变得缓慢。

要解决「神经元死亡」,就必须让整个激活函数定义域内不能有某个方向趋向于 0。ReLU 的升级版 —— LeakyReLU 能够满足这一点。

ELU 激活函数属于「集大成者」,它不但具有输出零均值分布(可以加快训练速度)的特点,而且是单向饱和的。