一、激活函数的意义: 先简单介绍一下什么是激活函数~
单一神经元模型如下图所示:
文章图片
神经网络中的每个神经元节点接受上一层神经元的输出值作为本神经元的输入值,并将输入值传递给下一层,输入层神经元节点会将输入属性值直接传递给下一层(隐层或输出层)。在多层神经网络中,上层节点的输出和下层节点的输入之间具有一个函数关系,这个函数称为激活函数(又称激励函数)。
下面进入正题,激活函数存在的意义是什么呢,为什么不直接将神经元的输入输出直接进行连接呢?
如果不用激励函数(其实相当于激励函数是f(x) = x),在这种情况下你每一层节点的输入都是上层输出的线性函数,很容易验证,无论你神经网络有多少层,输出都是输入的线性组合,与没有隐藏层效果相当,这种情况就是最原始的感知机(Perceptron)了,那么网络的逼近能力就相当有限。正因为上面的原因,我们决定引入非线性函数作为激励函数,使用激活函数是为了让中间输出多样化,能够处理更复杂的问题,这样深层神经网络表达能力就更加强大(不再是输入的线性组合,而是几乎可以逼近任意函数)。有论文中把激活函数定义为一个几乎处处可微的函数f: R->R
那么,激活函数是为了让网络能够能够有更强的表现能力,为什么有这么多激活函数呢?
随着神经网络不断地发展,人们逐渐发现早期的激活函数会导致模型的收敛变慢,甚至造成不收敛现象。下面简单介绍一下常用的激活函数以及其中的优缺点,在介绍之前先介绍一下基本的概念:
饱和:
当函数f(x)满足:
lim ? x → + ∞ f ′ ( x ) = 0 \lim_{x\rightarrow+\infty}f^{'}(x)=0 limx→+∞?f′(x)=0
时,称为右饱和;
当函数f(x)满足:
lim ? x → ? ∞ f ′ ( x ) = 0 \lim_{x\rightarrow-\infty}f^{'}(x)=0 limx→?∞?f′(x)=0
时,称为左饱和。
当f(x)同时满足左饱和及右饱和时,称为饱和。
软包和与硬包和:
在饱和定义的基础上,如果存在常数c1,当x>c1时候恒满足 f ′ ( x ) = 0 f^{'}(x)=0 f′(x)=0称之为右硬饱和;同样的,如果存在c2,当x
函数公式如下:
f ( x ) = 1 1 + e ? x f(x)=\frac{1}{1+e^{-x}} f(x)=1+e?x1?,
其导数为:
f ′ ( x ) = f ( x ) ( 1 ? f ( x ) ) f^{'}(x)=f(x)(1-f(x)) f′(x)=f(x)(1?f(x))
文章图片
def sigmoid(x):
y = 1/(1+np.exp(-x))
return y
优点:
<1> Sigmoid的取值范围在(0, 1),而且是单调递增,比较容易优化
<2> Sigmoid求导比较容易,可以直接推导得出。
缺点:
<1> Sigmoid函数收敛比较缓慢
<2> 由于Sigmoid是软饱和,容易产生梯度消失,对于深度网络训练不太适合(从图上sigmoid的导数可以看出当x趋于无穷大的时候,也会使导数趋于0)
<3> Sigmoid函数并不是以(0,0)为中心点
2. Tanh函数
函数公式:
f ( x ) = s i n h ( x ) c o s h ( x ) = 1 ? e ? 2 x 1 + e ? 2 x = e x ? e ? x e x + e ? x = e 2 x ? 1 e 2 x + 1 = 2 s i g m o i d ( 2 x ) ? 1 f(x)=\frac{sinh(x)}{cosh(x)}=\frac{1-e^{-2x}}{1+e^{-2x}}=\frac{e^{x}-e^{-x}}{e^{x}+e^{-x}}=\frac{e^{2x}-1}{e^{2x}+1}=2sigmoid(2x)-1 f(x)=cosh(x)sinh(x)?=1+e?2x1?e?2x?=ex+e?xex?e?x?=e2x+1e2x?1?=2sigmoid(2x)?1
其导数为:
f ′ ( x ) = t a n h ′ ( x ) = s e c h 2 ( x ) = 1 ? t a n h 2 ( x ) f^{'}(x)=tanh{'}(x)=sech^{2}(x)=1-tanh^{2}(x) f′(x)=tanh′(x)=sech2(x)=1?tanh2(x)
文章图片
def tanh(x):
y = (np.exp(x) - np.exp(-x))/(np.exp(x) + np.exp(-x))
return y
优点:
<1> 函数输出以(0,0)为中心
<2> 收敛速度相对于Sigmoid更快
缺点:
<1> tanh并没有解决sigmoid梯度消失的问题
3. ReLU函数
公式如下:
f ( x ) = m a x ( 0 , x ) = { 0 ( x ? 0 ) x ( x > 0 ) f(x)=max(0, x)=\left\{\begin{matrix} 0 & (x \leqslant 0)& \\ x & (x > 0) & \end{matrix}\right. f(x)=max(0,x)={0x?(x?0)(x>0)??
文章图片
def ReLU(x):
y = []
for i in x:
if i >= 0:
y.append(i)
else:
y.append(0)
return y
优点:
<1> 在SGD中收敛速度要比Sigmoid和tanh快很多
<2> 有效的缓解了梯度消失问题
<3> 对神经网络可以使用稀疏表达
<4> 对于无监督学习,也能获得很好的效果
缺点:
<1> 在训练过程中容易杀死神经元,造成梯度消失0的情况。比如一个特别大的梯度经过神经元之后,我们调整权重参数,就会造成这个ReLU神经元对后来来的输入永远都不会被激活,这个神经元的梯度永远都会是0。
4.LReLU函数
公式:
LReLU
文章图片
LRelu的优点:缓解了Relu神经元死亡的问题。
文章图片
def LReLU(x):
y = []
for i in x:
if i >= 0:
y.append(i)
else:
y.append(0.01*i)
return y
LRelu/PReLU的优点:
优点:
<1> .解决了正区间梯度消失问题;
<2> .易于计算;
<3> .收敛速度快;
<4> .解决了某些神经元不能被激活
缺点:
<1> 输出不是以零为中心
4.PReLU函数
文章图片
公式:
PReLU
f ( x ) = m a x ( a x , x ) f(x) = max(ax, x) f(x)=max(ax,x)
其中 a a a是可以学习的。如果 a = 0 a=0 a=0,那么 PReLU 退化为ReLU;如果 a a a是一个很小的固定值(如 a = 0.01 a=0.01 a=0.01),则 PReLU 退化为 Leaky ReLU(LReLU)。
PReLU 只增加了极少量的参数,也就意味着网络的计算量以及过拟合的危险性都只增加了一点点。特别的,当不同 channels 使用相同的a时,参数就更少了。BP 更新a时,采用的是带动量的更新方式(momentum)
【机器学习基础|深度学习中的激活函数(一)】函数太多了,后期继续补充!
推荐阅读
- 深度学习|深度学习中的激活函数
- CV|Swin-Unet阅读笔记
- 深度学习|从0开始的深度学习——【tensorflow】如何生成一个基本张量
- 深度学习|十、卷积神经网络
- 计算机视觉|超越PVT!南大提出ResT(高效多尺度的视觉Transformer)
- pytorch|图像分类篇(实现pytorch官网demo(LeNet))
- Pytorch进阶|【Pytorch进阶一】基于LeNet的CIFAR10图像分类
- 动手学深度学习PyTorch版|《动手学深度学习PyTorch版》打卡_Task3,过拟合,欠拟合,梯度消失,梯度爆炸
- 分类|LeNet网络模型——CIFAR-10数据集进行分类