🐋损失函数和激活函数的选择
2021-11-15
| 2023-8-6
0  |  阅读时长 0 分钟
type
status
date
slug
summary
tags
category
icon
password
Property
 
DNN可以使用的损失函数和激活函数不少。这些损失函数和激活函数如何选择呢?
首先我们来看看均方差+Sigmoid的组合有什么问题。
Sigmoid激活函数的表达式为:
图像如下:
notion image
对于Sigmoid,当的取值越来越大后,函数曲线变得越来越平缓,意味着此时的导数也越来越小。同样的,当的取值越来越小时,也有这个问题。仅仅在 取值为0附近时,导数 的取值较大。
均方差+Sigmoid的反向传播算法中,每一层向前递推都要乘以 ,得到梯度变化值。Sigmoid的这个曲线意味着在大多数时候梯度变化值很小,导致 更新到极值的速度较慢,也就是算法收敛速度较慢。那么有什么什么办法可以改进呢?
 

使用交叉熵损失函数+Sigmoid激活函数改进DNN算法收敛速度

换掉Sigmoid?这当然是一种选择。另一种常见的选择是用交叉熵损失函数来代替均方差损失函数。
二分类时每个样本的交叉熵损失函数的形式:
这个形式其实很熟悉,在逻辑回归中其实就用到了类似的形式,只是当时是用最大似然估计推导出来的,而这个损失函数的学名叫交叉熵。对数似然损失和交叉熵的形式是统一的
 
使用了交叉熵损失函数,就能解决Sigmoid函数导数变化大多数时候反向传播算法慢的问题吗?
当使用交叉熵时,我们输出层的梯度情况:
可见此时我们的 梯度表达式里面已经没有了 ,回顾一下均方差损失函数时在 梯度:
对比两者在第层的 梯度表达式,就可以看出,使用交叉熵到的的梯度表达式没有了,梯度为预测值和真实值的差距,这样求得的 的地图也不包含,因此避免了反向传播收敛速度慢的问题。
通常情况下,如果使用了sigmoid激活函数,交叉熵损失函数肯定比均方差损失函数好用。分类问题选择交叉熵损失函数,回归问题选择均方差损失函数
注:实交叉熵损失函数只能在输出层L不需要激活函数的导数,在后面的层层反向传播计算时还是需要的
根据下面这个BP的式子即可知道:,所以说这个方法可以一定程度减小梯度消失的问题,并不能完全消除。使用交叉熵损失函数只是在输出这一层的反向传播避免导数,即优化了输出层这一块,进而可以部分减少反向传播的梯度消失程度,所以也只是部分加快收敛速度。
 

使用对数似然损失函数和softmax激活函数进行DNN分类输出

前面的所有DNN相关知识中都假设输出是连续可导的值。但是如果是分类问题,那么输出是一个个的类别,那怎么用DNN来解决这个问题呢?
比如假设有一个三个类别的分类问题,这样我们的DNN输出层应该有三个神经元,假设第一个神经元对应类别一,第二个对应类别二,第三个对应类别三,这样我们期望的输出应该是(1,0,0),(0,1,0)和(0,0,1)这三种。即样本真实类别对应的神经元输出应该无限接近或者等于1,而非该样本真实输出对应的神经元的输出应该无限接近或者等于0。或者说,我们希望输出层的神经元对应的输出是若干个概率值,这若干个概率值即我们DNN模型对于输入值对于各类别的输出预测,同时为满足概率模型,这若干个概率值之和应该等于1。
DNN分类模型要求是输出层神经元输出的值在0到1之间,同时所有输出值之和为1。很明显,现有的普通DNN是无法满足这个要求的。但是我们只需要对现有的全连接DNN稍作改良,即可用于解决分类问题。在现有的DNN模型中,我们可以将输出层第 个神经元的激活函数定义为如下形式:
其中, 是输出层第层的神经元个数(分类问题的类别数)。
很容易看出,所有的 都是在(0,1) 之间的数字,而 作为归一化因子保证了所有的之和为1
这个方法很简洁漂亮,仅仅只需要将输出层的激活函数从Sigmoid之类的函数转变为上式的激活函数即可。上式这个激活函数就是我们的softmax激活函数。它在分类问题中有广泛的应用。
 
下面这个例子清晰的描述了softmax激活函数在前向传播算法时的使用。假设我们的输出层为三个神经元,而未激活的输出为3,1和-3,我们求出各自的指数表达式为:20,2.7和0.05,我们的归一化因子即为22.75,这样我们就求出了三个类别的概率输出分布为0.88,0.12和0:
notion image
从上面可以看出,将softmax用于前向传播算法是也很简单的。那么在反向传播算法时还简单吗?反向传播的梯度好计算吗?答案是Yes!
对于用于分类的softmax激活函数,对应的损失函数一般都是用对数似然函数取反,即:
其中 的取值为0或者1,如果某一训练样本的输出为第i类。则 ,其余的 都有 。由于每个样本只属于一个类别,所以这个对数似然函数可以简化为: 其中 即为训练样本真实的类别序号。
可见损失函数只和真实类别对应的输出有关,这样假设真实类别是第 类,对于真实类别第 类,他对应的第 链接对应的梯度计算为:
同样的可以得到 的梯度表达式为:
 
完整些的softmax推导:
损失函数:
softmax函数:
时,也就是分子对应的那个i的时候,导数为:
时, 导数为:
 
所以对于真实类别位置,反向传播的梯度是要-1,而不是真实类别的位置,反向传播的梯度为-0,即不变。
可见,梯度计算也很简洁,也没有训练速度慢的问题。举个例子,假如对于第2类的训练样本,通过前向算法计算的未激活输出为 ,则我们得到softmax激活后的概率输出为: 。由于类别是第二类,则反向传播的梯度应该为:
softmax输出层的反向传播计算完以后,后面的普通DNN层的反向传播计算和之前讲的普通DNN没有区别
 
 

梯度爆炸梯度消失与ReLU激活函数

什么是梯度爆炸和梯度消失呢?从理论上说都可以写一篇论文出来。不过简单理解,就是在反向传播的算法过程中,由于我们使用了是矩阵求导的链式法则,有一大串连乘,如果连乘的数字在每层都是小于1的,则梯度越往前乘越小,导致梯度消失,而如果连乘的数字在每层都是大于1的,则梯度越往前乘越大,导致梯度爆炸。
比如在反向传播算法里面的计算,可以表示为:
如果不巧我们的样本导致每一层 的都小于1,则随着反向传播算法的进行, 会随着层数越来越小,甚至接近越0,导致梯度几乎消失,进而导致前面的隐藏层的 参数随着迭代的进行,几乎没有大的改变,更谈不上收敛了。这个问题目前没有完美的解决办法。
notion image
notion image
 
对于梯度爆炸,则一般可以通过调整DNN模型中的初始化参数得以解决
对于无法完美解决的梯度消失问题,目前有很多研究,一个可能部分解决梯度消失问题的办法是使用ReLU(Rectified Linear Unit)激活函数,ReLU在卷积神经网络CNN中得到了广泛的应用,在CNN中梯度消失似乎不再是问题。
 
除了上面提到了激活函数,DNN常用的激活函数还有:
  • tanh:这个是sigmoid的变种,表达式为:
    • tanh激活函数和sigmoid激活函数的关系为:
      tanh和sigmoid对比主要的特点是它的输出落在了 ,这样输出可以进行标准化。同时tanh的曲线在较大时变得平坦的幅度没有sigmoid那么大,这样求梯度变化值有一些优势。当然,要说tanh一定比sigmoid好倒不一定,还是要具体问题具体分析。sigmoid不是中心对称的,会出现zigzag现象
  • softplus:这个其实就是sigmoid函数的原函数,表达式为:
    • 它的导数就是sigmoid函数,softplus的函数图像和ReLU有些类似,它出现的比ReLU早,可以视为ReLU的鼻祖
notion image
  • PReLU:从名字就可以看出它是ReLU的变种,特点是如果未激活值小于0,不是简单粗暴的直接变为0,而是进行一定幅度的缩小。如下图。当然,由于ReLU的成功,有很多的跟风者,有其他各种变种ReLU,这里就不多提了
notion image
  • PyTorch
  • 反向传播算法(BP) 参数初始化
    目录