目录
前言
论文地址: https://proceedings.mlr.press/v15/glorot11a/glorot11a.pdf.
贡献:根据生物神经元工作原理说明了激活函数稀疏性的好处,并根据稀疏性原理提出一种新型线性激活函数(广泛使用):ReLU(Rectified Linear Uint) 也叫线性修正单元(含有稀疏性)。
ReLU相比之前的 Sigmoid/tanh 的优点有:
- 不会发生梯度消失问题。Sigmoid函数在 x>0 会发生梯度消失问题,造成信息损失,从而无法完成深度网络的训练。而 ReLU 函数当 x>0 为线性结构,有固定的梯度,不会消失。
- ReLU激活函数在 x<0 时会输出为0(失活),这可以造成网络的稀疏性。这样可以很好的模拟人脑神经元工作的原理,且可以减少参数间的相互依赖,缓解了过拟合问题的发生。
- Sigmoid函数复杂,计算量大(前向传播+反向传播求导),速度慢;而ReLU函数简单,计算量小,速度快。
一、背景
1.1、为什么需要激活函数?
我们都知道卷积神经网络的每一层都是一个线性操作,如果在层与层之间不加上激活函数,那么无论网络有多少层,输出值都是输入值的线性组合,这样的模型的表达能力是不够的。看下面的两种情况:
当数据是线性可分时:
这个时候可以找到一条直线将数据进行分类,我们的模型在不加任何的激活函数时完全就可以做到。
但是这种只是简单的情况,现实中的数据大多数都是线性不可分的,如下图:
我们的模型如果不加任何的激活函数的话,是无法找到一条直线将数据分出来,因为我们的模型的表达能力不够(只有线性表达能力,没有非线性表达能力),无法做到复杂的任务。所以我们需要在层与层之间加入激活函数,以增加模型的非线性表达能力,以完成更加复杂的任务。
1.2、大脑工作原理:稀疏性原理
论文花费了大量的篇幅描述人类大脑的工作原理,通过研究人类大脑能量消耗表明神经元是以一种稀疏和分布式的方式编码信息:人类大脑神经元大约只有 1% - 4% 是在同一时间工作的。从信号方面来看,即神经元同时只对输入信号的少部分选择性响应,大量信号被刻意的屏蔽了,这样可以提高学习的精度,更好更快地提取稀疏特征。
这个原理的进一步可以由这个公式表达:
可视化后:
可以看到这个函数当输入信号 x<0 的时候直接失活不工作。
1.3、稀疏性优点
这块我看的不是很懂,大家最好自己回去看下原论文。
Machine Learning中的颠覆性研究是稀疏特征。近年来,稀疏性研究不仅在计算神经科学、机器学习领域活跃,甚至信号处理、统计学也在借鉴。
总结起来稀疏性大概有以下四个方面的优点:
- 信息分离(Information disentangling)。当前,深度学习一个明确的目标是从数据变量中解离出关键因子。原始数据(以自然数据为主)中通常缠绕着高度密集的特征。原因是这些特征向量是相互关联的,一个小小的关键因子可能牵扰着一堆特征,有点像蝴蝶效应,牵一发而动全身。基于数学原理的传统机器学习手段在解离这些关联特征方面具有致命弱点。然而,如果能够解开特征间缠绕的复杂关系,转换为稀疏特征,那么特征就有了鲁棒性(去掉了无关的噪声)。
- 有效的可变大小的表达(Efficient variable-size representation):不同的输入蕴含的信息不同,如果我们想用一个数据结构去表示信息,则这种数据结构的大小应该是可变的,否则对于某些输入就无法进行表示,如果一个神经网络是稀疏的,我们就可以通过激活的神经元数量来表示不同大小的信息
- 线性可分性(Linear separability)。稀疏特征有更大可能线性可分,或者对非线性映射机制有更小的依赖。因为稀疏特征处于高维的特征空间上(被自动映射了)从流形学习观点来看(参见降噪自动编码器),稀疏特征被移到了一个较为纯净的低维流形面上。线性可分性亦可参照天然稀疏的文本型数据,即便没有隐层结构,仍然可以被分离的很好。
- 稠密分布但是稀疏(Distributed but sparse)。稠密分布着的特征是信息最富集的特征,从潜在性角度,往往比局部少数点携带的特征成倍的有效。而稀疏特征,正是从稠密缠绕区解离出来的,潜在价值巨大。对于神经网络而言,不论是稀疏亦或是稠密,模型都具有一定的复杂度,仍然可以拟合复杂的数据,但过分稀疏会导致模型的复杂度下降,模型的拟合能力大大下降。
二、ReLU定义
如下图左边所示,是我们根据人脑神经元工作方式(激活机制)绘制出来的图,可以看到当输入信息 <0 时,神经元直接失活不工作。而右图是人工神经网络中目前使用最多的两种非线性激活函数。可以发现左图和右图相差还是很大的,最明显的一个差异就是右图的两个激活函数都没有用到我们上面说的稀疏性特征。
上节我们也对稀疏性特征做了很系统的一个分析,那么我们现在希望设计一个函数,让它也具有稀疏性的特征。于是我们的 ReLU 激活函数就被设计了出来:
R
e
L
U
=
m
a
x
(
0
,
x
)
=
{
0
,
if x<0
x
,
if x
≥
0
ReLU = max(0, x) = \begin{cases} 0, & \text {if x<0} \\ x, & \text{if x$\geq$0} \end{cases}
ReLU=max(0,x)={0,x,if x<0if x≥0
函数图像和导函数图像如下:
可以看到ReLU函数的图像和上面的神经元激活函数的图像非常的相似,x<0 都失活了(稀疏化)。
三、ReLU函数优缺点
3.1、优点
- 不会发生梯度消失问题。Sigmoid函数在 x>0 会发生梯度消失问题,造成信息损失,从而无法完成深度网络的训练。而 ReLU 函数当 x>0 为线性结构,有固定的梯度,不会消失。
- ReLU激活函数在 x<0 时会输出为0(失活),这可以造成网络的稀疏性。这样可以很好的模拟人脑神经元工作的原理,且可以减少参数间的相互依赖,缓解了过拟合问题的发生。
- Sigmoid函数复杂,计算量大(前向传播+反向传播求导),速度慢;而ReLU函数简单,计算量小,速度快。
3.2、缺点
- 由于激活函数是没有上界的,有可能出现神经网络输出为NaN的情况
- (重要)ReLU在训练的时候很”脆弱”,很可能产生 Dead ReLU Problem(神经元坏死现象):某些神经元可能永远不会被激活,导致相应参数永远不会被更新(在负数部分,梯度为0)。举个例子:由于ReLU在x<0时梯度为0,这样就导致负的梯度在这个ReLU被置零,而且这个神经元有可能再也不会被任何数据激活。如果这个情况发生了,那么这个神经元之后的梯度就永远是0了,也就是ReLU神经元坏死了,不再对任何数据有所响应。
- ReLU不会对数据做幅度压缩,所以数据的幅度会随着模型层数的增加不断扩张。
- ReLU的输出不是zero-centered;
四、PyTorch 实现
import matplotlib.pyplot as plt
import numpy as np
class ActivateFunc():
def __init__(self, x, b=None, lamb=None, alpha=None, a=None):
super(ActivateFunc, self).__init__()
self.x = x
self.b = b
self.lamb = lamb
self.alpha = alpha
self.a = a
def ReLU(self):
y = np.where(self.x < 0, 0, self.x)
y_grad = np.where(self.x < 0, 0, 1)
return [y, y_grad]