激活函数是向神经网络中引入非线性因素,通过激活函数神经网络就可以拟合各种曲线。激活函数是神经网络中一个至关重要的概念,决定了某个神经元是否被激活,判断该神经元获得的信息是否有用,并决定该保留还是该去掉此神经元。
一、激活函数是什么?
简单地说,激活函数就是加入到人工神经网络中的一个函数,目的在于帮助神经网络从数据中学习复杂模式。
相比于人类大脑中基于神经元的模型,激活函数是决定向下一个神经元传递何种信息的单元,这也正是激活函数在人工神经网络中的作用。激活函数接收前一个单元输出的信号,并将其转换成某种可以被下一个单元接收的形式。
下图总结了两者的区别:
二、为什么需要激活函数?
在神经网络中使用非线性激活函数的原因有很多。
1. 除了前面讨论过的生物学方面的相似性外,激活函数还有助于我们根据要求将神经元的输出值限定在一定的范围内。这一点很重要,因为激活函数的输入是 W*x+b,其中 W 是单元的权重,x 是输入值,然后加上偏置 b。如果输出值不被限定在某个范围内,它可能会变得非常大,特别是在具有数百万个参数的深层神经网络中,从而导致计算量过大。例如,有一些激活函数(如 softmax)对于不同的输入值(0 或 1)会输出特定的值。
2. 激活函数最重要的特点是它具有在神经网络中加入非线性的能力。为了便于理解,我们不妨考虑一下多维数据,如下图所示:
线性函数有三个属性(在这个图中分别是体重,收缩压和年龄),它使我们得到一条贯穿三维空间的直线,但它永远也无法学会一种模式来将一个人准确地区分为吸烟者和不吸烟者(以手头上现有的分类问题为例)。原因很简单,定义这个分类的模式根本不是线性的。
那在人工神经网络中,如果我们使用只有一个单元而没有激活函数的神经网络会怎样?这种情况下我们所得到的输出基本上还是 W*x+b,这并不好,因为 W*x 也是 x 的一次方,因此函数仍然是线性的,基本等同于线性函数。
如果我们叠加多层呢?假如我们用一个函数 f(x)来表示 nᵗʰ层,那么可以得出:
然而,这还不够复杂,特别是在计算机视觉或自然语言处理等有着复杂模式的问题中。
为了使模型能够学习非线性模式(或者说具有更高的复杂度),特定的非线性层(激活函数)被加入其中。
三、理想的激活函数具有的特点
1. 梯度消失问题:神经网络是利用梯度下降过程来训练的。
梯度下降由基于链式规则的反向传播组成,链式规则用于获取权值变化以减少每次训练后的损失。考虑一个两层网络,第一层表示为 f₁(x),第二层表示为 f₂(x)。整个网络为 o(x)= f₂(f₁(x))。
如果我们反过来计算权重,可以得到 o`(x)= f₂(x)*f₁`(x)。这里 f₁(x)本身是由 Act(W₁*x₁+b₁)组成的复合函数,其中 Act 是第 1 层之后的激活函数。再次应用链式规则,可以得到 f₁`(x)=Act(W₁*x₁+b₁)*x₁,这意味着此结果也直接依赖于激活值。现在可以看到, 这样一个链式规则在反向传播时会经过很多个层。
如果 Act()的值介于 0 和 1 之间,那么它会乘以几个这样的值来计算初始层的梯度。这个过程会降低初始层的梯度值,并且这些层也无法正确学习。
换言之,因为网络的深度和激活过程将值转变为趋近于 0,它们的梯度逐渐消失,这就是所谓的梯度消失问题。所以我们希望理想的激活函数不要使梯度逐渐变为零。
2. 以零为中心:激活函数的输出应对称于零,这样梯度就不会向特定方向移动。
3. 计算成本:网络的每一层都会应用激活函数,它在深层网络中需要计算数百万次。因此,激活函数的计算成本应该很低。
4. 可微性:如前所述,神经网络使用梯度下降过程进行训练,因此模型中的层需要可微或至少部分可微。这是一个函数可以作为激活函数层的必要条件。
四、目前使用的各种非线性函数
1、Sigmoid 函数
函数如下图所示:
这种激活函数从未在实际模型中使用,仅由于历史原因罗列在此。Sigmoid 函数计算量大,会导致梯度消失问题且不以零为中心,通常在二进制分类问题中才会使用。
Softmax 逻辑回归模型: softmax 逻辑回归模型是 Sigmoid 函数在多分类问题上的一种推广形式。与 Sigmoid 函数相似,它也产生 0-1 范围内的值,因此被用作分类模型的最后一层。
2、双曲正切函数 tanh
如图所示:
相比于 Sigmoid 函数,它仅仅解决了以零为中心这个问题。
3、线性整流函数(Rectified Linear Unit, ReLU)
该函数又称修正线性单元,定义为 f(x)=max(0,x):
这是一个使用十分广泛的激活函数,尤其是在卷积神经网络中。它计算简单,不会饱和,不产生梯度消失问题,但不以零为中心。它也存在「dying ReLU」问题,即当输入的是负数时,输出都会变成零,这样就导致一些节点完全「死掉」,神经元也不会进行学习。
ReLU 的另一个问题是激活爆炸,因为它的上限是 inf,有时会产生不可用的节点。
4、Leaky ReLU 和 Parametric ReLU 函数
函数的定义为 f(x)=max(αx,x),如下图所示:
当α为0.1时
这里α是一个通常设置为 0.01 的超参数。显然,Leaky ReLU 在一定程度上解决了「dying ReLU」这一问题。请注意,如果我们将α设为 1,那么 Leaky ReLU 将成为线性函数 f(x)=x,并且没有任何用处。
因此,α的值永远不会设置为趋近于 1 的值。如果我们分别将α设为每个神经元的超参数,则得到 Parametric ReLU 或 PReLU。
5、ReLU6 函数
ReLU6 在 x>0 的区域基本上等同于 ReLU,定义为 f(x)=min(max(0,x),6)
这有助于阻止激活增长,从而防止梯度爆炸(趋近无限时)以及正常 ReLUs 发生的其他小问题。
我们通常的想法是,为什么不把 ReLU6 和 Leaky ReLU 结合起来,以解决现在的激活函数的所有已知的问题。流行的 DL 框架没有提供现成的这样的激活函数,但我认为这是一个很好的想法。
五、在最新研究中涌现的值得关注的非线性激活函数
1、Swish 函数
Swish 由 Ramachandran 等人在 2017 年提出,定义为 f(x)=x*sigmoid(x)。
与 ReLU 相比,尽管图形非常相似,Swish 的性能却要稍好一些。然而,ReLU 在 x=0 时会突然发生改变,而 Swish 与此不同,它不会在某个点上突然改变,这使得训练时 Swish 更容易收敛。
但是,Swish 的缺点是它的计算成本很高,为了解决这个问题,我们来看看下一个版本的 Swish。
2、Hard-Swish 或 H-Swish函数
函数定义如下:
它最大的优点是几乎类似于 swish 函数,但计算成本却比 swish 更低,因为它用线性类型的 ReLU 函数取代了指数类型的 sigmoid 函数。
六、在深层神经网络中如何使用这些激活函数?
首先,Tanh 和 sigmoid 函数会引起巨大的梯度消失问题,因此一般不推荐使用。
神经网络中一开始尝试引入 ReLU 函数。如上文所述,在权重层(诸如 CNN、RNN、LSTM 或线性感知层)之后添加激活层。如果你认为模型已经停止学习,那么可以用 Leaky ReLU 替换它,以避免「Dying ReLU」问题。但 Leaky ReLU 会稍微增加计算时间。
如果网络中也有 Batch-Norm 层(批标准化层),则需要在执行激活函数之前添加该层,顺序是先进行 CNN-Batch(卷积神经网络批处理),再进行 Norm-Act(标准化动作)。虽然 Batch-Norm(批标准化)和激活函数的运行顺序是一个备受争议的话题,也有人说顺序其实无关紧要,为了与 Batch-Norm 的原论文保持一致,使用的是以上提到的这种顺序。
激活函数的默认超参数如果是在如 Tensorflow 和 Pytorch等框架中使用,则效果最好。然而,你可以调整 Leaky ReLU 中的负斜率并将其设置为 0.02 以加快学习速度。