您的位置:首页 > 其它

CS231n笔记2--Fully Connected Neural Network与Activation Function

2016-05-14 01:15 323 查看

Fully Connected Neural Network与Activation Function

Fully Connected Neural Network与Activation Function
神经网络Fully Connect Neural Network
一个最简单的神经网络

让网络更复杂些

激活函数-Activation Function
Sigmoid

tanh

ReLU

总结

神经网络–Fully Connect Neural Network

一个最简单的神经网络



hw,b=f(x1w1+x2w2+x3w3+b)=f(XW+b)h_{w,b}=f(x_1w_1+x_2w_2+x_3w_3+b)=f(XW+b)

向量化的python代码

def f(z):
return ReLu(z)

h = f(X.dot(W)+b)


这里ff是激活函数(Activation Function),我们稍后会讲,这里我们先用ReLu作为激活函数。

让网络更复杂些



这是一个三层的神经网络,第一层称为输入层,最后一层称为输出层,其他层(这里只剩第二层)则为隐藏层,别看好像突然复杂了很多,但是事实并非如此

定义Wli,jW_{i,j}^l为第ll层的第i个元素的值到第l+1l+1层第j个元素的值的权重,因此al+1j=f(∑ialiWli,j+blj)=f(alWlj+blj)a_j^{l+1}=f(\sum_i{a_i^lW_{i,j}^l}+b_j^l)=f(a^lW_j^l+b_j^l)

向量化的表示我们可以得到al+1=f(alWl+bl)a^{l+1}=f(a^lW^l+b^l),发现跟最简单的神经网络的公式没什么区别。

向量化的python代码

def fc_layer(X, W, b):
return f(X.dot(W)+b)

def three_layer_fc(X, W1, b1, W2, b2):
"""一个三层的神经网络的代码例子
"""
layer1 = X
layer2 = f(X.dot(W1)+b1)
layer3 = f(layer2.dot(W2)+b2)
return layer3


至此,全连接的神经网络(Fully Connected Neural Network)我们可以说已经掌握了,现在让我们来看看刚刚遗留的激活函数的类型与选择问题。

激活函数-Activation Function

在深度学习中,比较常见的有Sigmoid、tanh、ReLU这些激活函数,然后还有些是ReLU的改进,比如说Leaky ReLU(PReLU的特例)、ELU以及Maxout等。这里我们只关注三个主要的激活函数,即

Sigmoid:f(z)=11+e−ztanh:f(z)=ez−e−zez+e−zReLU:f(z)=max(0,z)Sigmoid: f(z) = \dfrac{1}{1+e^{-z}} \\
tanh:f(z) = \dfrac{e^z-e^{-z}}{e^z+e^{-z}} \\
ReLU:f(z) = max(0, z)

Sigmoid

f(z)=11+e−zf(z) = \dfrac{1}{1+e^{-z}}



优势:

将整个实数域压缩到[0,1]区间内

历史角度上,Sigmoid对神经元的工作有较好的对应

缺点:

饱和区将扼杀梯度

输出并非以零为中心的

自然指数的运算开销大

下面的讨论将会很大程度依赖对神经网络后向传播求梯度的知识背景,现在不了解也没关系,我们很快就会学习有关后向传播求梯度的内容,到时候再回过头来看吧~

饱和区将扼杀梯度:从图上可以看出,当z取值在(-4,4)以内是,梯度明显,但是一旦z超出了范围,梯度基本等于0,因此,很恐怖地,如果z的取值稍微大了些,比如5,那么梯度将被扼杀。为什么说是扼杀而不是消失呢?那是因为扼杀比消失更严重,因为在神经网络的学习过程中,我们会使用Backward Propagation来求网络的梯度,然而,在一个网络中,如果出现了某处的z取值处在饱和区,那么由后面层传来的梯度即使再大,再优秀,都会因为需要和该处梯度(此时为0)相乘而变为0,从而导致后续的后向传播越来越异常。

输出并非以零为中心的:从图上还可以看出,Sigmoid的输出一直是正的,那么对于下一层来说,它的输入也就一直是正的,这样会导致在下一层的梯度要不全都是正的,要不全都是负的(因为Sigmoid梯度只可能是正的,再由于每层的X都是正的,所以该层的局部梯度一直为正,那么该层的全局梯度的正负只有它的下一层的梯度决定了,因此,如果下一层传递过来的梯度是负的,那么该层全局梯度全为负,否则全为正)。这样就导致了一个非常奇怪的现象,称为“Zig zag path”见下图。



因为梯度要不全为正要不全为负,因此,如果权重如果想往右下角走,那么要求在x轴的梯度为负,y轴的梯度为正(因为W-=dW),而这是不可能做到的,因此,梯度只能先全都往y轴负方向走,然后再全都往x周正方向走,从而达到往右下角走的等价效果。然而此时,我们就可以发现,这样的收敛速度将会慢很多。因此,我们才希望激活函数输出能够尽量满足以零为中心。

自然指数的运算开销大:很明显的,计算exe^x的复杂度是很大的,更何况当x还是实数的情况,对于小型网络似乎就没什么问题,但是一当网络大起来,效率将会大大折扣。

tanh

f(z)=ez−e−zez+e−zf(z) = \dfrac{e^z-e^{-z}}{e^z+e^{-z}}



与Sigmoid相比,tanh好在其输出是以零为中心的,然而缺点也十分明显,即使计算复杂度很大。并且也存在饱和区扼杀梯度的情况。因此也不是很理想。

ReLU

f(z)=max(0,z)f(z) = max(0, z)



作为目前最流行的深度学习的激活函数,ReLU的优势十分明显:

ReLU在正半轴不存在饱和区扼杀梯度的问题

ReLU的计算复杂度非常的低

在实践中,ReLU的收敛速度比其他的两种要快将近6倍的速度

然而也存在缺点:

输出并非以零为中心的

当z<0时,梯度将被扼杀

当z<0时,梯度将被扼杀:我们称z<0为死区,因为在这个区间内梯度将恒为0,因此,使用ReLU通常要注意在初始化权重时,让偏移权重的均值向正偏(例如0.01)

针对ReLU的不足,后续有了很多ReLu的改良版:比如Leaky ReLU:f(z)=max(0.01z,z)f(z) = max(0.01z, z), PReLU:f(z)=max(αz,z)f(z) = max(\alpha z, z)(注意z≠1z \neq 1)等等。这些都比较好地缓和了ReLU输出不以零为中心以及z<0时梯度被扼杀的情况。还有一种比较特别的方法称为Maxout:f(z)=max(XW1+b1,XW2+b2)f(z) = max(XW_1+b_1, XW_2+b_2),这个方法不存在饱和区问题,并且计算复杂度也不算高,但是有个缺点就是对于每组输入都要用两倍数量的权重去计算,导致网络参数特别多。

总结

在实际操作中:

默认使用ReLU,但是要注意竟可能避免陷入死区

可以尝试使用ReLU的改良版

可以尝试tanh,但不要抱太大期望

不要使用Sigmoid!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: