Pytorch学习:Task4 PyTorch激活函数原理和使用
1.torch.nn.ELU Sigmoid和ReLU结合体,具有左侧软饱和性
数学表达式:
图像:
右侧线性部分使得ELU可以缓解梯度消失问题,而左侧软饱和性能让ELU对输入变化或噪声更鲁棒。
而且ELU的输出均值接近于0,所以没有严重的偏移现象,所以收敛速度更快
2.torch.nn.LeakyReLU
数学表达式:
negative_slop是一个超参数,控制x为负数时斜率的角度,默认1e-2
图像:
3.torch.nn.PReLU() ReLU和LReLU改进版本
数学表达式:
图像
针对x<0的硬饱和问题,我们对ReLU作出改进,提出Leaky-ReLU,即在x<0部分添加一个参数α,如上图所示。
P-ReLU则认为α也应当作为一个参数来学习,一般建议α初始化为0.25。
4.torch.nn.ReLU() CNN中最常用的
数学表达式:
图像
优缺点
优点:
(1)收敛速度比 sigmoid 和 tanh 快;(梯度不会饱和,解决了梯度消失问题)
(2)计算复杂度低,不需要进行指数运算
缺点:
(1)ReLu的输出不是zero-centered;
(2)Dead ReLU Problem(神经元坏死现象):某些神经元可能永远不会被激活,导致相应参数不会被更新(在负数部分,梯度为0)。产生这种现象的两个原因:参数初始化问题;learning rate太高导致在训练过程中参数更新太大。解决办法:采用Xavier初始化方法;以及避免将learning rate设置太大或使用adagrad等自动调节learning rate的算法。
(3)ReLu不会对数据做幅度压缩,所以数据的幅度会随着模型层数的增加不断扩张。
5.torch.nn.ReLU6()
数学表达式
图像
6.torch.nn.Sigmoid()
数学表达式
图像
优缺点
优点:
(1)便于求导的平滑函数
(2)能压缩数据,保证数据幅度不会有问题
(3)适合用于前向传播
缺点:【梯度消失/幂运算耗时】
(1)容易出现梯度消失(gradient vanishing)的现象:当激活函数接近饱和区时,变化太缓慢,导数接近0,根据后向传递的数学依据是微积分求导的链式法则,当前导数需要之前各层导数的乘积,几个比较小的数相乘,导数结果很接近0,从而无法完成深层网络的训练。
(2)Sigmoid的输出不是0均值的:这会导致后层的神经元的输入是非0均值的信号,这会对梯度产生影响。以 f=sigmoid(wx+b)为例, 假设输入均为正数(或负数),那么对w的导数总是正数(或负数),这样在反向传播过程中要么都往正方向更新,要么都往负方向更新,导致有一种捆绑效果,使得收敛缓慢。
(3)幂运算相对耗时
7.torch.nn.Tanh
本质是sigmoid的变型,tanh(x)=2sigmoid(2x)-1
数学公式:
或
图像
优缺点
改善:将输出值映射到了-1到1之间,因此它是0均值的了
缺点:梯度消失和幂运算耗时长
激活函数的选择
最好不要用sigmoid,tanh也是不适用的,其会导致梯度消失问题。使用relu函数,要小心设置learning rate。还有其他的激活函数,如leaky relu、prelu和maxout等等,可以优先选择relu,如果出现Dead ReLU Problem,应该使用leaky relu、prelu和maxout。
小练习
在pytorch中手动实现上述激活函数
class ActivateFunction():
def __init__(self):
pass
def relu(self,x):
return max(0,x)
def relu6(self,x):
return min(max(0,x),6)
def sigmoid(self,x):
return 1/(1+math.exp(-x))
def celu(self,x):
return max(0,x) + min(0,a*(math.exp(x/a)-1))
def logsigmoid(self,x):
return math.log(1/(1+math.exp(-x)))
def tanh(self,x):
return (math.exp(x) - math.exp(-x))/(math.exp(x)+math.exp(-x))
def prelu(self,x,a):
return max(0,x)+a*min(0,x)
def leakyrelu(self,x,negative_slope=1e-2):
return max(0,x)+negative_slope*min(0,x)
def elu(self,x,a):
return max(0,x) + min(0,a*(math.exp(x)-1))
def softshrink(x,l):
if x>l:
return x-l
elif x<l:
return x+l
else:
return 0