深度学习基础(2)

1.激活函数和损失函数

在神经网络中,除了基本的矩阵运算外,还会涉及两个函数的操作。

1.1 激活函数

激活函数的主要作用是提供网络的非线性建模能力。如果没有激活函数,网络只能表示特征的线性映射,即便有再多隐藏层,其整个网络也和单层网络是等价的。激活函数应该具有的性质:

  • 可微性:后向传播寻优,需要这个性质。
  • 单调性:保证单层网路是凸函数。
  • 输出值的范围:有限范围时,基于梯度的优化方法更加稳定,因为特征的表示受有限权值得影响更显著;无限时,模型训练更高效,不过此时一般需要更小的learning rate。

常见的激活函数多是分段线性和具有指数形状的非线性函数。

sigmoid函数

\[f(x)=\frac{1}{1+e^x} \]

sigmoid函数是应用范围最广的一类激活函数,它在物理意义上接近生物神经元,此外(0,1)的输出区间也可以用来表示概率。然而,sigmoid也有其自身的缺陷,最明显的是饱和性,其两侧导数值逐渐趋近于0。

\[\lim_{x->\infty}f'(x)=0 \]

具有这种性质的称为软饱和激活函数,饱和又分为左饱和与右饱和。与软饱和相对的是硬饱和,即:

\[f'(x)=0, |x|>c ,c为常数 \]

sigmoid的软饱和性,使得深度神经网络在二三十年里一直难以有效的训练,是阻碍神经网络发展的重要原因。

具体来说,后向传播中,sigmoid的传导因子中包含\(f'(x)\)因子,因此一旦落入饱和区,\(f'(x)\)就变得接近于0,导致向底层传递的梯度非常小。此时网络参数很难得到有效的训练,称这种现象为梯度消失,一般来说,sigmoid网络在5层内就会产生梯度消失现象。

此外,sigmoid函数的输出大于0,均值不为0,称之为偏移现象,在前向传播中,后层神经元得到上一层的输出始终是非0的信号。

tanh函数

\[f(x)=\frac{1-e^{-2x}}{1+e^{-2x}} \]

tanh函数也是一种常见的激活函数,与sigmoid相比,其均值为0,使得其收敛速度比sigmoid要快。然而由于tanh也具有软饱和性,从而会带来梯度消失。

ReLU,P_ReLU,Leaky-ReLU

\[f(x)= \begin{cases} x, \; if \; x\geq 0\\ 0, \; if \; x<0 \end{cases}\\ f(x)=max(0,x) \]

ReLU的全称是Rectified Linear Units,是一种后来才出现的激活函数。可以看到,当x<0时,ReLU硬饱和,而当x>0时,则不存在饱和问题。所以ReLU在x>0时保持梯度不衰减,从而缓解了梯度消失的问题,这让我们可以直接以监督的方式训练深层神经网络,而无需依赖逐层的预训练。

然而,随着训练的推进,部分输入落入硬饱和区,导致对应权重无法更新,形成“死亡神经元”。且与sigmoid类似,ReLU的输出均值>0,偏移现象和死亡神经元会影响网络的收敛性。改进得:

\[f(x)= \begin{cases} x, \; if \; x \geq 0 \\ ax, \; if \; x <0 \end{cases} \]

这就是Leaky-ReLU,而P-ReLU认为,α也可以作为一个参数来学习,原文献建议初始化a为0.25,不采用正则。

ELU

\[f(x)= \begin{cases} x, \;\;\;\;\;\;\;\;\;\;\;if x\geq 0\\ \alpha (e^x-1), \;if x<0 \end{cases} \]

融合了sigmoid和ReLU,左侧具有软饱和性,右侧无饱和性。右侧线性部分可以缓解梯度消失,而左侧的软饱和能让ELU对输入的变化和噪声更加鲁棒。ELU的均值接近于0。在ImageNet上,不加BN30层以上的ReLU网络无法收敛,而ELU网络可以收敛。

MaxOut

\[f(x)=max(w_1^Tx+b_1, w_2^Tx+b_2,\cdots,w_n^T+b_n) \]

maxout可以近似任意连续函数,且当\(w_2,b_2,w_3,b_3...=0\)时,退化成了ReLU。Maxout可以缓解梯度下降,同时又避免了ReLU神经元死亡的缺点,但增加了参数和计算量。

1.2 损失函数

前面,我们使用的是平方差函数

\[C=\frac{1}{2}(a-y)^2 \]

当神经元的输出和我们的期望差距越大,损失越严重。
但是在实际中,我们知道:

\[\frac{\partial C}{\partial W}=(a-y)\sigma'(a)x^T \\ \frac{\partial C}{\partial b}=(a-y)\sigma'(a) \]

其中都有\(\sigma'(a)\)这一项,因为sigmoid函数的性质,导致\(\sigma'(z)\)在z的大部分情况下都会造成饱和现象,从而导致参数的更新很慢,所以我们想到了交叉熵,交叉熵的计算公式为:

\[H(y,a)=-\sum_i{y_{i}*log(a_i)} \]

如果有多个样本,整体的平均交叉熵为

\[H(y,a)=-\frac{1}{n}\sum_n\sum_i{y_{i,n}*log(a_{i,n})} \]

其中,n为样本编号,i为类别编号。

以logistic分类为例:\(H(y,a)=-\frac{1}{n}\sum_n{ylog(a) + (1-y)log(1-a)}\)

与平方损失函数相比,交叉熵具有非常好的性质:

\[\frac{\partial{H}}{\partial{z}} = \frac{1}{n} \sum_n{\frac{y}{a}*a*(1-a) - \frac{1-y}{1-a}*a(1-a)} = \frac{1}{n}\sum{(\sigma(z_n)-y_n)} \]

可见,消除了\(\sigma'\)这一项,这样便不会受最后一个激活函数的影响,误差大时更新大,误差小时跟新小。

激活函数比较:http://www.jianshu.com/p/22d9720dbf1a

softmax激活函数

softmax也是我们常见的激活函数主要用于多分类神经元的输出。

\[y_j = f(z_j) = \frac{e^{z_j}}{\sum_k{e^{z_k}}} \]

直接输出各个类别的概率:

  • 1 >\(y_i\) > 0
  • \(\sum_k{y_k}\) = 0

如果某个\(z_j\)大于其他z,那么它的映射分量就会逼近1,其他逼近0。取对数,模拟max的行为,让大的更大,且保证可导。

sigmoid用于二分类,softmax可用于多分类。在二分类问题时,softmax和sigmoid是一样的(\(z'=z_2-z_1\)):

\[h(x) = \frac{e^{z_1}}{e^{z_1} + e^{z_2}} = \frac{1}{1+e^{z_2-z_1}} = \frac{1}{1+e^{z'}} \]

softmax的求导见:https://zhuanlan.zhihu.com/p/25723112

2.优化方法

主要介绍一阶的梯度法,包括SGD, Momentum, Nesterov Momentum, AdaGrad, RMSProp, Adam。其中SGD,Momentum,Nesterov Momentum是手动指定学习速率的,而后面的AdaGrad, RMSProp, Adam,就能够自动调节学习速率

BGD

即batch gradient descent,在训练中,利用现有参数对训练集中的每一个输入生成一个估计输出\(\hat{y_i}\),然后跟实际输出\(y_i\)比较,统计所有误差,求平均以后得到平均误差,以此来作为更新参数的依据。

具体实现:
需要:学习速率 ϵ, 初始参数θ
每步迭代过程:

  1. 提取训练集中的所有内容\(\{x_1,...x_n\}\),以及相关的输出\(y_i\)
  2. 计算梯度和误差并更新参数:

\[\begin{align*} &\hat g \leftarrow +\frac{1}{n}\nabla_\theta \sum_i L(f(x_i;\theta),y_i) \\ &\theta \leftarrow \theta-\epsilon\hat g \end{align*} \]

优点:
由于每一步都利用了训练集中的所有数据,因此当损失函数达到最小值以后,能够保证此时计算出的梯度为0。换句话说,就是能够收敛。因此,使用BGD时不需要逐渐减小学习速率 ϵ。
缺点:
由于每一步都要使用所有数据,因此随着数据集的增大,运行速度会越来越慢。

SGD

SGD全名stochastic gradient descent,即随机梯度下降。不过这里的SGD其实跟MBGD(minibatch gradient descent)是一个意思,即随机抽取一批样本,以此为根据来更新参数。
具体实现:
需要:学习速率 ϵ, 初始参数 θ
每步迭代过程:

  1. 从训练集中的随机抽取一批容量为m的样本\(\{x_1,…,x_m\}\),以及相关的输出\(y_i\)
  2. 计算梯度和误差并更新参数:

\[\begin{align*} & \hat g \leftarrow +\frac{1}{m}\nabla_\theta \sum_i L(f(x_i;\theta),y_i)\\ & \theta \leftarrow \theta-\epsilon\hat g \end{align*} \]

优点:
训练速度快,对于很大的数据集,也能够以较快的速度收敛。

缺点:
由于是抽取,因此不可避免的,得到的梯度肯定有误差。因此学习速率需要逐渐减小,否则模型无法收敛。因为误差,所以每一次迭代的梯度受抽样的影响比较大,也就是说梯度含有比较大的噪声,不能很好的反映真实梯度。

这样一来,ϵ如何衰减就成了问题,如果要保证SGD收敛,应该满足如下两个要求:

\[\begin{align*} &\sum_{k=1}^\infty \epsilon_k = \infty \\ &\sum_{k=1}^\infty \epsilon_k^2 <\infty \end{align*} \]

而在实际操作中,一般是进行线性衰减:

\[\begin{align*} &\epsilon_k=(1-\alpha)\epsilon_0+\alpha\epsilon_\tau\\ &\alpha = \frac{k}{\tau} \end{align*} \]

其中\(\epsilon_0\)是初始学习率,\(\epsilon_\tau\)是最后一次迭代的学习率。\(\tau\)自然代表迭代次数。
一般来说,\(\epsilon_\tau\)设为\(\epsilon_0\)的1%比较合适。而\(\tau\)一般设为让训练集中的每个数据都输入模型上百次比较合适。
那么初始学习率\(\epsilon_0\)怎么设置呢?书上说,你先用固定的学习速率迭代100次,找出效果最好的学习速率,然后\(\epsilon_0\)设为比它大一点就可以了。

Momentum

上面的SGD在每次迭代中都包含较大的噪音,而Momentum可以较好地解决这个问题,尤其是面对小而连续的梯度但含有很多噪声的时候。Momentum借用了物理中动量的概念,将前几次的梯度也参与到运算中。

具体实现:
需要:学习速率 ϵ,初始参数 θ,初始速率v,动量衰减参数α
每步迭代过程:

  1. 从训练集中的随机抽取一批容量为m的样本\(\{x_1,…,x_m\}\),以及相关的输出\(y_i\)
  2. 计算梯度和误差,并更新速度v和参数θ:

\[\begin{align*} & \hat g \leftarrow +\frac{1}{m}\nabla_\theta \sum_i L(f(x_i;\theta),y_i)\\ & v\leftarrow\alpha v-\epsilon\hat g \\ & \theta\leftarrow\theta+v \end{align*} \]

其中,\(\alpha\)表示动量的衰减程度,如果每次迭代得到的梯度都是g,那么最终得到的\(v=\frac{\epsilon||g||}{1-\alpha}\)

也就是说,Monentum最好的情况下可以将学习率加速\(\frac{1}{1-\alpha}\)倍。一般α的取值有0.5,0.9,0.99这几种,当然也可以让α的值随着时间而变化,开始小一点,后来再加大。

特点:
前后梯度方向一致时,能够加速学习。前后梯度方向不一致时,能够抑制震荡。

Nesterov Momentum

先对参数进行估计,然后使用估计后的参数进行误差计算

具体实现:
需要:学习速率 ϵ,初始参数 θ,初始速率v,动量衰减参数α
每步迭代过程:

  1. 从训练集中的随机抽取一批容量为m的样本\(\{x_1,…,x_m\}\),以及相关的输出\(y_i\)
  2. 计算梯度和误差,并更新速度v和参数θ:

\[\begin{align*} & \hat g \leftarrow +\frac{1}{m}\nabla_\theta \sum_i L(f(x_i;\theta+\alpha v),y_i)\\ & v\leftarrow\alpha v-\epsilon\hat g \\ & \theta\leftarrow\theta+v \end{align*} \]

注意在估算\(\hat{g}\)的时候,参数变成了\(\theta+\alpha v\)而不是之前的θ。

AdaGrad

AdaGrad可以自动变更学习速率,只是需要设定一个全局的学习速率ϵ,但是这并非是实际学习速率,实际的速率是与以往参数的模之和的开方成反比的。

\[\epsilon_n=\frac{\epsilon}{\delta+\sqrt{\sum_{i=1}^{n-1}g_i\odot g_i}} \]

其中\(\delta\)是一个很小的常亮,大概在\(10^{−7}\),防止出现除以0的情况。

具体实现:
需要:全局学习速率 ϵ,初始参数 θ,数值稳定量δ
中间变量: 梯度累计量r(初始化为0)
每步迭代过程:

  1. 从训练集中的随机抽取一批容量为m的样本\(\{x_1,…,x_m\}\),以及相关的输出\(y_i\)
  2. 计算梯度和误差,更新r,再根据r和梯度计算参数更新量

\[\begin{align*} & \hat g \leftarrow +\frac{1}{m}\nabla_\theta \sum_i L(f(x_i;\theta),y_i)\\ & r\leftarrow r+\hat g\odot \hat g \\ & \triangle \theta = -\frac{\epsilon}{\delta+\sqrt{r}}\odot \hat g \\ & \theta\leftarrow\theta+\triangle \theta \end{align*} \]

优点:
能够实现学习率的自动更改。如果这次梯度大,那么学习速率衰减的就快一些;如果这次梯度小,那么学习速率衰减的就满一些。

缺点:
任然要设置一个变量ϵ
经验表明,在普通算法中也许效果不错,但在深度学习中,深度过深时会造成训练提前结束。

RMSProp

通过引入一个衰减系数,让r每回合都衰减一定比例,类似于Momentum中的做法。

具体实现:
需要:全局学习速率 ϵ,初始参数 θ,数值稳定量δ,衰减速率ρ
中间变量: 梯度累计量r(初始化为0)
每步迭代过程:

  1. 从训练集中的随机抽取一批容量为m的样本\(\{x_1,…,x_m\}\),以及相关的输出\(y_i\)
  2. 计算梯度和误差,更新r,再根据r和梯度计算参数更新量

\[\begin{align*} & \hat g \leftarrow +\frac{1}{m}\nabla_\theta \sum_i L(f(x_i;\theta),y_i)\\ & r\leftarrow \rho r+(1-\rho)\hat g\odot \hat g \\ & \triangle \theta = -\frac{\epsilon}{\delta+\sqrt{r}}\odot \hat g \\ & \theta\leftarrow\theta+\triangle \theta \end{align*} \]

优点:
相比于AdaGrad,这种方法很好的解决了深度学习中过早结束的问题
适合处理非平稳目标,对于RNN效果很好

缺点:
又引入了新的超参,衰减系数ρ
依然依赖于全局学习速率

RMSProp with Nesterov Momentum

将RMSProp和Nesterov Momentum结合起来的

\[\begin{align*} & \tilde \theta \leftarrow \theta + \alpha v \\ & \hat g \leftarrow +\frac{1}{m}\nabla_{\tilde \theta} \sum_i L(f(x_i;\tilde \theta),y_i)\\ & r\leftarrow \rho r+(1-\rho)\hat g\odot \hat g \\ & v \leftarrow \alpha v-\frac{\epsilon}{\sqrt r}\odot \hat g \\ & \theta\leftarrow\theta+v \end{align*} \]

Adam

Adam(Adaptive Moment Estimation)本质上是带有动量项的RMSprop,它利用梯度的一阶矩估计和二阶矩估计动态调整每个参数的学习率。Adam的优点主要在于经过偏置校正后,每一次迭代学习率都有个确定范围,使得参数比较平稳。

具体实现:
需要:步进值 ϵ, 初始参数 θ, 数值稳定量δ,一阶动量衰减系数\(\rho_1\), 二阶动量衰减系数\(\rho_2\)
其中几个取值一般为:\(\delta=10^{-8},\rho_1=0.9,\rho_2=0.999\)
中间变量:一阶动量s,二阶动量r,都初始化为0
每步迭代过程:

  1. 从训练集中的随机抽取一批容量为m的样本\(\{x_1,…,x_m\}\),以及相关的输出\(y_i\)
  2. 计算梯度和误差,更新r和s,再根据r和s以及梯度计算参数更新量

\[\begin{align*} & g \leftarrow +\frac{1}{m}\nabla_{\theta} \sum_i L(f(x_i;\theta),y_i)\\ & s \leftarrow \rho_1s+(1-\rho_1)g \\ & r\leftarrow \rho_2 r+(1-\rho_2)g\odot g \\ & \hat s \leftarrow \frac{s}{1-\rho_1} \\ & \hat r \leftarrow \frac{r}{1-\rho_2} \\ & \triangle \theta = -\epsilon \frac{\hat s}{\sqrt{\hat r}+\delta} \\ & \theta\leftarrow\theta+\triangle \theta \end{align*} \]

详见:http://blog.csdn.net/heyongluoyao8/article/details/52478715

posted @ 2017-07-04 16:13  侯凯  阅读(1065)  评论(0编辑  收藏  举报