激活函数层
神经网络如果仅仅是由线性的卷积运算堆叠组成,则其无法形成复杂的表达空间,也就很难提取出高语义的信息,因此还需要加入非线性映射,又称激活函数,可以逼近任意的非线性函数,以提升整个神经网络的表达能力,在物体检测任务中,常用的就好函数有Sigmoid、ReLU及Softmax函数
1. Sigmoid函数
Sigmoid函数又称Logistic函数,模拟了生物的神经元特征,即当神经元获得的输入信号累计超过一定阈值后,神经元被激活而处于兴奋状态,否则处于抑制状态,表达式如下:
Sigmoid函数曲线与梯度如下图所示。可以看到,Sigmoid函数将特征压缩到了(0,1)区间,0端对应抑制状态,1端对应激活状态,中间部分梯度较大
PyTorch实现Sigmoid函数很简单:
>>> import torch
>>> from torch import nn
>>> input = torch.ones(1,1,2,2)
>>> input
tensor([[[[1., 1.],
[1., 1.]]]])
>>> sigmoid = nn.Sigmoid() #使用nn.Sigmoid()实例化sigmoid
>>> sigmoid(input)
tensor([[[[0.7311, 0.7311],
[0.7311, 0.7311]]]])
2. ReLU函数
为了缓解梯度消失现象,修正线性单位(Rectified Linear Unit,ReLU)被引入到神经网络中。由于其优越的性能与简单优雅的实现,ReLU已经成为目前卷积神经网络中最为常用的激活函数之一,表达式如下:
ReLU函数及其梯度曲线如下图所示。可以看出,在小于0的部分,值与梯度皆为0,而在大于0的部分中导数保持为1,避免了Sigmoid函数中梯度接近于0导致的梯度消失问题
PyTorch实现ReLU激活函数示例:
>>> import torch
>>> from torch import mm
>>> import torch
>>> from torch import nn
>>> input = torch.randn(1,1,2,2)
>>> input
tensor([[[[-1.4048, -1.4899],
[-0.2723, 0.0399]]]])
>>> #nn.ReLU()可以实现inplace操作,即可以直接将运算结果覆盖到输入中,以节省内存
>>> relu = nn.ReLU(inplace=True)
>>> relu(input) #可以看出大于0的值保持不变,小于0的值被置为0
tensor([[[[0.0000, 0.0000],
[0.0000, 0.0399]]]])
3.Leaky ReLU函数
ReLU激活函数虽然高效,但是其将负区间所有的输入都强行置为0,Leaky ReLU函数优化了这一点,在负区间内避免了直接置0,而是赋予很小的权重,其函数表达式如下:
以上公式中的a_i代表权重,即小于0的值被缩小的比例。Leaky ReLU的函数曲线如下图:
下面使用PyTorch来实现简单的Leaky ReLU激活函数过程:
>>> import torch
>>> from torch import nn
>>> input = torch.randn(1,1,2,2)
>>> input
tensor([[[[ 1.1159, 0.7548],
[ 1.9184, -0.3778]]]])
>>> #利用nn.LeakyReLU()构建激活函数,并且其为1/a_i为0.04,即a_I
>>> #利用nn.LeakyReLU()构建激活函数,并且其为1/a_i为0.04,即a_i为25,True代表in-place操作
>>> leakyrelu = nn.LeakyReLU(0.04,True)
>>> leakyrelu(input) #从结果来看大于0的值保持不变,小于0的值被以0.04的比例缩小
tensor([[[[ 1.1159, 0.7548],
[ 1.9184, -0.0151]]]])
4. Softmax函数
在物体检测中,通常需要面对多物体分类问题,虽然可以使用Sigmoid函数来构造多个二分类器,但比较麻烦,多物体类别较为常用的分类器是Softmax函数
在具体的分类任务,Softmax函数的输入往往是多个类别的得分,输出则是每一个类别对应的概率,所有类别的概率值都在0~1之间,且和为1。Softmax函数的表达如下所示,其中V_i表示第i个类别的得分,C代表分类的类别总数,输出S_i为第i个类别的概率:
在PyTorch中,Softmax函数在torch.nn.functional库中,使用方法如下:
>>> import torch.nn.functional as F
>>> score = torch.randn(1,4)
>>> score
tensor([[-0.7885, 0.1150, 0.1483, -0.6228]])
>>> #利用torch.nn.functional.softmax()函数,第二个参数表示按照第几个维度进行softmax计算
>>> F.softmax(score,1)
tensor([[0.1389, 0.3428, 0.3544, 0.1639]])