**函数的“3W”

学习神经网络,必然会遇到**函数,那么:

  • 什么是**函数?What
  • 为什么要用**函数?Why
  • 应该选择哪个**函数?Which

本文尝试对此进行探讨。

神经网络的基本思想

人工神经网络是仿照了大脑的神经网络系统来处理数据的,它由节点组成了层,通常一个网络又有多个层(除了输入层和输出层之外,有多个隐藏层),每个节点就是一个神经元。信息从输入层进入,传到隐藏层(如图所示),按照简化的模型,输入数据乘以权重(weight)加上一个偏置(bias),然后应用**函数得到该神经元的输出,再将此输出传给下一层的神经元。

**函数的“3W”

此流程在各个层的神经元中不断重复,直到最后一层输出层。寻找隐藏层的权重参数和偏置的过程,就是常说的“学习”过程,其遵循的基本原则就是使得网络最终的输出误差最小化。

**函数

可以将**函数理解为控制当前层的神经元与下一层的神经元之间的信息传递的“门”,它决定当前的神经元是否被**,可以用下图帮助理解。

**函数的“3W”

为什么要用**函数

参考上面的图示,如果没有**函数,该神经元的输入和输出之间就是线性变换。线性函数虽然容易求解,但是它所能解决的问题有限,特别是针对复杂问题的时候。由此推广,如果神经网络没有**函数,它也就变成了线性回归模型。所以,需要一个**函数。

那么,需要什么样的**函数呢?

**函数的类型

**函数可以分为两种类型:

  • 线性**函数
  • 非线性**函数

线性**函数

图示的是一个线性**函数和一个常函数,通过线性**函数所得到的输出,相对于输入而言,只是比例的变化。

**函数的“3W”

  • 函数式: f ( x ) = x f(x) = x f(x)=x
  • 导数: f ′ ( x ) = 1 f'(x) = 1 f(x)=1
  • 值域: ( − ∞ , + ∞ ) (-\infty, +\infty) (,+)

从上面的函数示例可知,线性函数求导数之后得到了常数,也就是与输入数据无关,这样就无法通过反向传播算法更新权重参数。另外,如果用线性函数作为**函数,不论网络有多少层,最后的输出与第一层的输入都是线性关系。

非线性**函数

现代神经网络使用的都是非线性**函数,这样可以创建输入与输出键的复杂映射关系,网络也能通过“学习”来更新参数。并且,因为非线性函数的导数与输入有关,从而可以通过向后传播算法计算梯度,也可以构建多层神经网络,以处理复杂问题。

常用的非线性**函数

Sigmoid函数/Logistic函数

Sigmoid函数是S形函数,当以概率形式表示预测值时,我们使用这个函数。

**函数的“3W”

  • 函数式: f ( x ) = σ = 1 1 + e − x f(x)=\sigma = \frac{1}{1+e^{-x}} f(x)=σ=1+ex1
  • 导数: f ′ ( x ) = σ ( 1 − σ ) f'(x) = \sigma(1-\sigma) f(x)=σ(1σ)
  • 值域: ( 0 , 1 ) (0, 1) (0,1)

Sigmoid函数的优点在于它可导,并且值域在0到1之间,使得神经元的输出标准化。也正是这些优点,让它成为了神经网络最早采用的**函数。它的不足也很明显,首先就是在 x x x 增加或减少到一定程度时,函数值变化很小,这就是所谓的“梯度消失”,致使网络的收敛速度变慢,进而耗费更多的计算资源。另外,输出值不是以 0 0 0 为中心,而是 0.5 0.5 0.5

Tanh/双曲正切函数

Tanh函数,即双曲正切函数,也是“S”形,但是Sigmoid函数仅冠名给了上面的那个函数。

**函数的“3W”

  • 函数式: f ( x ) = a = t a n h ( x ) = e x − e − x e x + e − x f(x) = a =tanh(x) = \frac{e^x-e^{-x}}{e^x+e^{-x}} f(x)=a=tanh(x)=ex+exexex
  • 导数: 1 − a 2 1-a^2 1a2
  • 值域: ( − 1 , 1 ) (-1, 1) (1,1)

Tanh函数的最大优点是输出值以 0 0 0 为中心,分属为正数和负数两大类别,另外此函数及其导数都是单调的,这使得它具有了Sigmoid函数的优势,又克服了某些不足。当然,Tanh的不足与Sigmoid一样,“梯度消失”的问题都还存在,进而导致收敛速度变慢。

ReLU ( Rectified Linear Unit)

Rectified Linear Unit,译为“线性整流函数”或者“修正线性单元”,通常我们就直接称为 ReLU 函数。

**函数的“3W”

  • 函数式: f ( x ) = a = m a x ( 0 , x ) f(x)=a=max(0, x) f(x)=a=max(0,x)
  • 导数: f ′ ( x ) = { 1 , ( x ≥ 0 ) 0 , ( x < 0 ) f'(x)=\begin{cases}1,\quad&(x \ge 0)\\0, \quad&(x \lt0)\end{cases} f(x)={1,0,(x0)(x<0)
  • 值域: ( 0 , + ∞ ) (0, +\infty) (0,+)

ReLU函数的明显优点在于收敛速度快,当然,不要觉得它看起来是线性的(在大于 0 0 0 的部分),这个函数其实是非线性函数,它可导,因此可以用于反向传播算法。它的不足在于当输入趋近于零或为负时,函数的梯度变为零,网络无法执行反向传播,无法学习。

Leaky ReLU

Leaky ReLU函数式 ReLU函数的特殊化,就如同名称中的 Leaky(漏水)那样,如图所示,当 x < 0 x \lt 0 x<0 时,其函数值不再等于 0 0 0,而是有一个小小的坡度(水可以沿着斜坡流下去)。

**函数的“3W”

  • 函数式: f ( x ) = a = m a x ( 0.01 x , x ) f(x)=a=max(0.01x, x) f(x)=a=max(0.01x,x)
  • 导数: f ′ ( x ) = { 0.01 , ( x < 0 ) 1 , ( x ≥ 0 ) f'(x)=\begin{cases}0.01,\quad &(x\lt 0)\\1, \quad &(x\ge 0)\end{cases} f(x)={0.01,1,(x<0)(x0)
  • 值域: ( 0.01 , + ∞ ) (0.01, +\infty) (0.01,+)

Leaky ReLU函数相对于ReLU函数而言,变化的主要是 x < 0 x \lt 0 x<0 区域,其值不再是一个固定数值,导数也不为0了,于是就可以应用于反向传播算法。也是因为这个修正,使得Leaky ReLU函数不再针对输入值小于零的时候有固定的值了,从而会导致正向传播的时候,如果学习率设置的比较大,会出现较大数量的神经元未**现象,真乃“成也萧何败萧何”。

Leaky ReLU函数的这种思想,还可以进一步扩展,比如不将 x x x 与常数项相乘,可以将其与超参数相乘,所得到的的函数称为“参数ReLU”函数。

Softmax

Softmax函数比较适合作为多分类模型的**函数,一般会与交叉熵损失函数相配。

**函数的“3W”

  • 函数式: f ( y i ) = e y i ∑ i = 0 n e y i f(y_i)=\frac{e^{y_i}}{\sum_{i=0}^n e^{y_i}} f(yi)=i=0neyieyi
  • 概率解释: S j = P ( y = j ∣ x ) S_j = P(y=j|x) Sj=P(y=jx)
  • 值域: ( 0 , 1 ) (0, 1) (0,1)

Softmax函数的输出结果是0到1之间的概率值,对应着输入数据属于某个类别的概率,因此适合于多分类模型。通常,Softmax函数只应用于输出层。

选用**函数

以上介绍的几个不同的**函数,各有优缺点,那么,在神经网络中,应该选择哪个函数作为**函数呢?

首先要建立一个观念:不存在普遍适用各种神经网络的万能的**函数。在选择**函数的时候,要考虑很多条件限制:

  • 如果函数可导,求导数的计算难度如何?

  • 网络的收敛速度如何?

  • 函数光滑程度如何?

  • 是否满足通用的逼近定理条件?

  • 输出是否保持标准化?

    等等,不一而足。

所以,要结合具体问题以及**函数的特点,恰当地选择。下面是一些经验,供参考:

  • Sigmoid函数比较适合于分类模型。
  • 使用Sigmoid函数和tanh函数,要注意梯度消失问题。
  • ReLU函数是应用比较广泛的**函数,可以作为你的默认选项。
  • 如果网络中存在大量未**神经元,可以考虑leaky ReLU函数。
  • ReLU函数应该只用于隐藏层。
  • 如果是回归模型,在输出层上可以使用线性**函数。

本文讨论了**函数的问题,在神经网络中,上述讨论都不是唯一确定的,比如**函数的类型,这里罗列出来的是目前常见的,是不是在未来针对某个问题,研究者还会找到新的函数呢?完全有可能。至于如何选择**函数,更是仁者见仁智者见智的了。

参考链接:https://medium.com/@snaily16/what-why-and-which-activation-functions-b2bf748c0441