神经网络激活函数解析



  • 概述

    最近各种调试网络,激活函数作为神经网络的一个重要部分,肯定是需要考虑在内的。虽然之前的网络架构里面借鉴了别人无脑用ReLU的思路,但是还是想自己尝试下,激活函数之间的差异,并且这里对激活函数的含义和要求做一个简短的解析。

    关于异或

    这里盗了NG课程的图,我们首先来思考一个问题,给两个变量x1,x2,是否存在f(x1,x2) = x1 xor x2。xor就是这里所说的异或,真值表如下。对于线性函数,我们无法做到满足上述公式。那么答案肯定要借助非线性公式了,神经网络中,我们通过多层感知机,并在层与层之前加入非线性激活函数,通过这种非线性叠加的方式来模拟复杂函数

    XOR truth table
    Input Output
    A B
    0 0 0
    0 1 1
    1 0 1
    1 1 00_1525498187183_7fc7eb00-4d30-43ab-a75e-c40ce9af77f1-image.png
    下图可以看到,非线性的函数很轻松可以完成xor操作啦。

    0_1525498197623_52bc270d-a1b1-4fb4-8b0d-82b06b3ca796-image.png

    是否这样可以模拟任何函数呐?

    我想答案应该是否定的!
    论文解答:
    This paper rigorously establishes that standard multilayer feedforward networks with as few as one hidden layer using using arbitrary squashing functions are capable of approximating any Borel measurable function from one finite dimensional space to another to any desired degree of accuracy, provided sufficiently many hidden units are available.
    人话解释:上述做法可以拟合任意的博雷尔可测(Borel measurable)函数,至于啥是Borel可测,我就不知道了,反正就是可以模拟大多数我们需要的函数。
    知乎链接:https://www.zhihu.com/question/58304333/answer/311054863

    激活函数要求

    上述说明,已经明白了,激活函数的意义就在于让网络具备更强的拟合能力,如果没有非线性层,多层的网络也会退化成线性函数。同时,我们的网络利用反向传播的方式进行计算,我们激活函数也需要结合这一特性。

    常见激活函数相关话题:

    • 梯度消散
    • 梯度爆炸
    • 节点死了(ReLU)

    我们先来看看反向传播,这里随便贴了一张图
    0_1525498439311_d7344ebf-2aec-4605-a2b0-63fd7e89a891-image.png

    0_1525498489197_9e135030-327d-4925-89c4-f0addfd34862-image.png
    我们使用链式法则可以看到,梯度的计算合激活函数的输出,激活函数的梯度都有着密切的关系,那么多层网络中这些因子会乘起来,如果这个值大于1,或者始终小于1,那么梯度就会传播过程中累计超出控制范围,变成梯度爆炸或者梯度消失。这里我们就要求激活函数的值域和导数域有一定的范围。

    激活函数特性总结:(https://www.zhihu.com/question/67366051)

    1. 非线性:即导数不是常数。这个条件前面很多答主都提到了,是多层神经网络的基础,保证多层网络不退化成单层线性网络。这也是激活函数的意义所在,这里ReLU虽然是常数,但是分段了,也具有非线性特征。
    2. 几乎处处可微:可微性保证了在优化中梯度的可计算性。传统的激活函数如sigmoid等满足处处可微。对于分段线性函数比如ReLU,只满足几乎处处可微(即仅在有限个点处不可微)。对于SGD算法来说,由于几乎不可能收敛到梯度接近零的位置,有限的不可微点对于优化结果不会有很大影响[1]。
    3. 计算简单:正如题主所说,非线性函数有很多。极端的说,一个多层神经网络也可以作为一个非线性函数,类似于Network In Network[2]中把它当做卷积操作的做法。但激活函数在神经网络前向的计算次数与神经元的个数成正比,因此简单的非线性函数自然更适合用作激活函数。这也是ReLU之流比其它使用Exp等操作的激活函数更受欢迎的其中一个原因。
    4. 非饱和性(saturation):饱和指的是在某些区间梯度接近于零(即梯度消失),使得参数无法继续更新的问题。最经典的例子是Sigmoid,它的导数在x为比较大的正值和比较小的负值时都会接近于0。更极端的例子是阶跃函数,由于它在几乎所有位置的梯度都为0,因此处处饱和,无法作为激活函数。ReLU在x>0时导数恒为1,因此对于再大的正值也不会饱和。但同时对于x<0,其梯度恒为0,这时候它也会出现饱和的现象(在这种情况下通常称为dying ReLU)。Leaky ReLU[3]和PReLU[4]的提出正是为了解决这一问题。
    5. 单调性(monotonic):即导数符号不变。这个性质大部分激活函数都有,除了诸如sin、cos等。个人理解,单调性使得在激活函数处的梯度方向不会经常改变,从而让训练更容易收敛。
    6. 输出范围有限:有限的输出范围使得网络对于一些比较大的输入也会比较稳定,这也是为什么早期的激活函数都以此类函数为主,如Sigmoid、TanH。但这导致了前面提到的梯度消失问题,而且强行让每一层的输出限制到固定范围会限制其表达能力。因此现在这类函数仅用于某些需要特定输出范围的场合,比如概率输出(此时loss函数中的log操作能够抵消其梯度消失的影响[1])、LSTM里的gate函数。
    7. 接近恒等变换(identity):即约等于x。这样的好处是使得输出的幅值不会随着深度的增加而发生显著的增加,从而使网络更为稳定,同时梯度也能够更容易地回传。这个与非线性是有点矛盾的,因此激活函数基本只是部分满足这个条件,比如TanH只在原点附近有线性区(在原点为0且在原点的导数为1),而ReLU只在x>0时为线性。这个性质也让初始化参数范围的推导更为简单[5][4]。额外提一句,这种恒等变换的性质也被其他一些网络结构设计所借鉴,比如CNN中的ResNet[6]和RNN中的LSTM。
    8. 参数少:大部分激活函数都是没有参数的。像PReLU带单个参数会略微增加网络的大小。还有一个例外是Maxout[7],尽管本身没有参数,但在同样输出通道数下k路Maxout需要的输入通道数是其它函数的k倍,这意味着神经元数目也需要变为k倍;但如果不考虑维持输出通道数的情况下,该激活函数又能将参数个数减少为原来的k倍。
    9. 归一化(normalization):这个是最近才出来的概念,对应的激活函数是SELU[8],主要思想是使样本分布自动归一化到零均值、单位方差的分布,从而稳定训练。在这之前,这种归一化的思想也被用于网络结构的设计,比如Batch Normalization[9]。

    如何看待ReLU的非线性

    ReLU作为一种常见的激活函数,真的是再简单不过了,其优点简单,导数为1等吧,缺点在于学习率过大,或者梯度过大容易造成节点死亡。但是这里很多同学可能不太理解,为什么ReLU可以作为激活函数,这明明就很线性啊~
    0_1525499006553_45d6b1cb-4808-4b04-9835-fa1ffe442a2a-image.png

    首先扯一扯生物学的角度,人脑的信号是很稀疏的,类比神经网络,我们网络1w个节点,可能就是1k个在起作用,那么我们干脆让ReLU把那些用不上的给“搞死”好了,这样网络可以根据任务自动的选择网络需要多少节点,自动稀疏化网络结构,听起来非常棒的。

    以上可以看到,部分的稀疏化网络就引入了非线性的因素了,应该max(0,λ)本身就不是个线性操作。类比最开始提到的异或,ReLU可以很容易的完成XOR操作,所以ReLU的非线性是稳稳没毛病的。

    一点点心得

    • ReLU网络不深的时候,常见的激活函数差异不大。
    • ReLU死了很多的时候,需要注意换成其他的激活函数,或者ReLU的变种。
    • 网络深的时候,Sigmoid,tanh这种需要注意梯度消散,可以适当引入Bn。


  • 前排顶fy大大


 

Copyright © 2018 bbs.dian.org.cn All rights reserved.

与 Dian 的连接断开,我们正在尝试重连,请耐心等待