为什么要引入激活函数?
如果不用激活函数(其实相当于激励函数是f(x)=x),在这种情况下你每一层输出都是上层输入的线性函数,很容易验证,无论你神经网络有多少层,输出都是输入的线性组合,与没有隐藏层效果相当,这种情况就是最原始的感知机了。
正因为上面的原因,我们决定引入非线性函数作为激励函数,这样深层神经网络就有意义了(不再是是输入的线性组合,可以逼近任意函数)。最早的想法是sigmoid函数或者tanh函数,输出有界,很容易充当下一层输入。激活函数的作用是为了增加神经网络模型的非线性。否则你想想,没有激活函数的每层都相当于矩阵相乘,就算你叠加了若干曾之后,无非还是个矩阵相乘罢了。所以你没有非线性结构的话,根本就算不上什么神经网络。
它能够把输入的连续实值“压缩”到0和1之间,特别的,如果是非常大的负数,那么输出就是0;如果是非常大的正数,输出就是1.
signoid函数曾经被使用的很多,不过近年来,用它的人越来越少了。主要是因为他的一些缺点:
当输入非常大或者非常小的时候,这些神经元的梯度是接近于0的,从图中可以看出梯度的趋势;
sigmoid的输出不是0均值,这回导致后一层的神经元将得到上一层输出的非0均值信号将作为输入(为什么不能是非0均值的???)
Tanh是Sigmoid的变形,与sigmoid不同的是,tanh是0均值的,因此,实际应用中,tanh会比sigmoid更好。
ReLU函数
从图中可以看出,输入负信号时,输出都是0,非负的情况下,输出就等于输入。
解决了gradient vanishing问题(在正区间)
计算速度非常快,只需要判断输入是否大于0
收敛速度远快于sigmoid和tanh
ReLU也有几个需要特别注意的问题:
1、ReLU的输出不是0均值的
2、Dead ReLU Problem,指的是某些神经元可能永远不会被激活,导致相应的参数永远不能被更新。有两个主要原因可能导致这种情况产生:(1)非常不幸的参数初始化,这种情况比较少见(2)learning rate太高导致在训练过程中参数更新太大,不幸使网络进入这种状态。解决方法是可以采用Xavier初始化方法,以及避免learning rate设置他打或者使用adagrad等自动调节learning rate的算法
为什么会引入Relu呢?
第一,采用Sigmoid等函数,算激活函数时(指数运算),计算量大,反向传播求误差梯度时,求导涉及除法,计算量相对大,而采用Relu激活函数,整个过程的计算量节省很多。
第二:对于深层网络,sigmoid函数反向传播时,很容易就会出现梯度消失的情况(在sigmoid接近饱和区时,变换太缓慢,导致趋于0,这种情况会造成信息丢失,从而无法完成深层网络的训练)
第三:ReLU会使一部分神经元的输出为0,这样就造成了网络的稀疏性,并且减少了参数的相互依存关系,缓解了过拟合问题的发生。
当然现在也有一些对ReLU的改进,比如prelu。random relu等,在不同的数据集上会有一些训练速度上或者准确率上的改进
现在主流的做法,会多做一些batch normalization,尽可能保证每一层网络的输入具有相同的分布。而最新的论文中,有加入bypass connection之后,发现改变batch normalization的位置会有更好的效果。
深度学习的基本原理是基于人工神经网络,信号从一个神经元进入,经过非线性的activation function,传入到下一层神经元;再经过该层神经元的activate,继续往下传递,如此循环往复,直到输出层。正是由于这些非线性函数的反复叠加,才使得神经网络有足够的capacity来抓取复杂的pattern,在各个领域取得state-of-the-art的结果。显而易见,activation function在深度学习中非常重要,也是很活跃的研究领域之一。