激活函数简单原理及使用:
原文链接:https://zhuanlan.zhihu.com/p/172254089
目前用到的几个激活函数的发展及简单使用:
1 Sigmoid:
Sigmoid 的函数图像如上所示,从图像可以看出,函数两个边缘的梯度约为0,梯度的取值范围为(0, 0.25)。
使用 Sigmoid 作为激活函数时,在多层神经元的网络中浅层和深层网络参数的更新速率相差巨大。该现象就称为 “梯度消失(Vanishing Gradients)”。
Pytorch 中的用法:
import torch.nn as nn
import torch
t1 = torch.randn(3,3)
m = nn.Sigmoid()
t2 = m(t1)
print(t1)
print(t2)
torch.nn.Sigmoid()
没有什么参数,可直接调用。
2 Relu:
ReLU 激活函数的提出就是为了解决梯度消失问题,ReLU 的梯度只可以取两个值:0或1,当输入小于0时,梯度为0;当输入大于0时,梯度为1。好处就是:ReLU 的梯度的连乘不会收敛到0 ,连乘的结果也只可以取两个值:0或1 ,如果值为1 ,梯度保持值不变进行前向传播;如果值为0 ,梯度从该位置停止前向传播。 Sigmoid 和 ReLU 函数对比如下:
Pytorch 中的用法:
torch.nn.ReLU(inplace: bool = False) # inplace 为 True,将会改变输入的数据,否则不会改变原输入,只会产生新的输出.
# 例子如下:
import torch
import torch.nn as nn
input1 = torch.tensor([50,-2,6,5,3])
input2 = torch.tensor([50,-2,6,5,3])
x1 = nn.ReLU(inplace = True)(input1)
x2 = nn.ReLU(inplace = False)(input2)
print(x1, input1)
print(x2, input2)
Output:
tensor([50, 0, 6, 5, 3]) tensor([50, 0, 6, 5, 3])
tensor([50, 0, 6, 5, 3]) tensor([50, -2, 6, 5, 3])
若 inplace=True,则对于上层网络传递下来的tensor直接进行修改,可以少存储变量y,节省运算内存。
3 Leakyrelu:
LeakyReLU的提出是为了解决神经元 ”死亡“ 问题(输入激活函数的值总为-,传播梯度恒为0,神经元无法继续学习),LeakyReLU 与 ReLU 很相似,仅在输入小于0的部分有差别,ReLU 输入小于0的部分值都为0,而 LeakyReLU 输入小于0的部分,值为负,且有微小的梯度。函数图像如下图:
Pytorch 中的用法:
torch.nn.LeakyReLU(negative_slope=0.01, inplace=False)
# 例子
import torch
import torch.nn as nn
m = nn.LeakyReLU(0.1)
input = torch.tensor([-0.9, 3064])
print(input)
print(m(input))
Output:
tensor([-9.0000e-01, 3.0640e+03])
tensor([-9.0000e-02, 3.0640e+03])
4 Elu:
理想的激活函数应满足两个条件:
-
输出的分布是零均值的,可以加快训练速度。
-
激活函数是单侧饱和的,可以更好的收敛。
输入大于0部分的梯度为1,输入小于0的部分无限趋近于-α,超参数取值一般为 1 。
Pytorch 中的用法:
torch.nn.ELU(alpha=1.0, inplace=False)
# 例子
import torch
import torch.nn as nn
m = nn.ELU()
input = torch.tensor([-0.9, 3064])
print(input)
print(m(input))
Output:
tensor([-9.0000e-01, 3.0640e+03])
tensor([-5.9343e-01, 3.0640e+03])