7、神经网络一: 建立网络架构

目录

7.1简介

7.2单个神经元建模

7.2.1生物学动机与联系

7.2.2单神经元作为线性分类器

7.2.3常用**函数

7.3神经网络体系结构

7.3.1分层组织

7.3.2前馈计算实例

7.3.3代表权

7.3.4设置层数及其大小

7.4总结

7.5参考文献


7.1简介

在不诉诸大脑的类比的情况下,依然是可以对神经网络算法进行介绍的。在线性分类的部分中,我们使用公式S=Wx计算图像的不同视觉类别的得分,其中W是矩阵,x是包含图像的所有像素数据的输入列向量。在CIFAR-10的情况下,X是[3072x1]列向量,W是[10x3072]矩阵,因此输出分数是10类分数的向量。

神经网络算法则不同,它的计算公式是S=W2MAX(0,W1X)。这里,W1可以是例如[100x3072]的矩阵,将图像转换为100维的过渡矢量。函数max(0,ω)是一个应用于元素的非线性函数。对于非线性(我们将在下面进行研究)有几种选择,但这是一种常见的选择,只需将零下的所有**阈值设为零。最后,矩阵W2的大小为[10x100],因此我们再次得到10个数字,我们将其解释为类分数。请注意,非线性是至关重要的计算-如果没有它,那么两个矩阵将会合二为一,对于分类的评分计算将重新变成关于输入的线性函数。这个非线性函数就是改变的关键点。参数W2、W1用随机梯度下降法学习,并用链式法则推导出它们的梯度(用反向传播计算)。

三层神经网络可以类似地看起来像S=W3MAX(0,W2MAX(0,W1X)),其中所有W3、W2、W1都是要学习的参数。中间隐藏向量的大小是网络的超参数,后续课程会介绍如何设置它们。现在让我们来看看如何从神经元/网络的角度解释这些计算。

7.2单个神经元建模

神经网络的领域最初主要是由生物神经系统建模的目标启发的,但此后已经偏离并成为工程问题,并在机器学习任务中取得良好的结果。尽管如此,我们从一个非常简短和高层次的生物系统的描述开始讨论,因为神经网络的大部分都是从这里被启发的。

7.2.1生物学动机与联系

大脑的基本计算单元是神经元。在人类神经系统中可以发现大约860亿个神经元,它们与大约10 ^ 14 - 10 ^ 15突触(synapses)相连。下面的图表显示了一个生物神经元(左)和一个常见的数学模型(右)的示意图。每个神经元接收来自其树突(dendrites )的输入信号,并沿其(单个)轴突(axon)产生输出信号。轴突最终分支并通过突触连接到其他神经元的树突。在神经元的计算模型中,沿着轴突(例如X0)传播的信号基于突触的突触强度(例如W0)与其他神经元的树突相互乘以(例如W0x0)。这个想法是,突触强度(权重W)是可学习的,并且控制一个神经元在另一个神经元上的影响强度(及其方向:兴奋(正权重)或抑制(负权重))。在基本模型中,树突将信号传送到细胞体,在那里它们都被求和。如果最终的总和超过某一阈值,神经元可以着火,沿其轴突发出一个尖峰。在计算模型中,我们假设尖峰的精确定时并不重要,并且只有着火的频率传达信息。基于这个速率码解释,我们用**函数F来模拟神经元的着火率,它代表沿轴突的尖峰频率。从历史上看,**函数的一个共同选择是S形函数,因为它取一个实值输入(总和之后的信号强度),并将其压制在0到1之间。稍后我们将在本节中看到这些**函数的细节。

7、神经网络一: 建立网络架构7、神经网络一: 建立网络架构

生物神经元(左)的卡通画及其数学模型(右)。

单个神经元前向传播的示例代码如下:

  1. class Neuron(object):

  2. # ...

  3. def forward(inputs):

  4. """ 假设输入和权重是1-D的numpy数组,偏差是一个数字 """

  5.     cell_body_sum = np.sum(inputs * self.weights) + self.bias

  6.     firing_rate = 1.0 / (1.0 + math.exp(-cell_body_sum)) # sigmoid**函数

  7.     return firing_rate

换言之,每个神经元用输入和它的权重来执行点积,添加偏置并应用非线性(或称为**函数),这里是S形函数σ(x)=1/(1+e−x)。我们将在本节结束时详细介绍不同的**函数。

粗糙模型。重要的是强调这种生物神经元的模型非常粗糙:例如,有许多不同类型的神经元,每个神经元具有不同的特性。生物神经元中的树突进行复杂的非线性计算。突触不仅仅是单一的权重,它们是一个复杂的非线性动力系统。已知在许多系统中输出尖峰的精确定时是重要的,这表明速率码近似可能不成立。由于所有这些和许多其他简化,准备听取任何神经科学背景的人起哄的声音,如果你在神经网络和真实大脑之间画类比。如果你感兴趣的话,可以看看这个评论(PDF),或者最近的这个评论

7.2.2单神经元作为线性分类器

模型神经元向前计算的数学形式对你来说可能很熟悉。正如我们看到的线性分类器,神经元有能力“喜欢”(接近于1)或“厌恶”(接近于零)的某些线性区域的输入空间。因此,只要在神经元的输出端有一个合适的损失函数,我们就可以将单个神经元转换成线性分类器:

二分类Softmax分类器。例如,我们可以将7、神经网络一: 建立网络架构解释为某一类的概率P(Yi=1 | Xi;W),另一类的概率是P(Yi=0 | Xi;w)=1-P(Y= 1 | Xi;W),它们的和必须为1。有了这种解释,我们可以制定交叉熵损失,我们已经在线性分类部分做了阐述。然后将它最优化为二分类的Softmax分类器(也就是逻辑回归)。因为sigmoid函数输出限定在0-1之间,所以分类器做出预测是基于神经元的输出是否大于0.5。

二分类SVM分类器。或者,我们可以将最大边界折页损失(max-margin hinge loss)附加到神经元的输出,并训练它成为二分类支持向量机。

正则化的解释。在SVM/Softmax的例子中,正则化损失从生物学角度可以看做渐进遗忘,因为它的效果是让所有突触权重7、神经网络一: 建立网络架构在参数更新过程中逐渐趋近于0。

可以使用单个神经元来实现二分类分类器(例如二分类Softmax分类器、二分类SVM分类器)。

 

7.2.3常用**函数

每一个**函数(或非线性函数)都取一个单一的数,并对其执行一定的固定数学运算。在实践中可能会遇到以下几个**函数:


7、神经网络一: 建立网络架构7、神经网络一: 建立网络架构

左:S形(Sigmoid )非线性,将实数压扁到[0,1]之间        右:双曲正切函数(tanh)非线性将实数压扁到[-1,1]之间


Sigmoid。S形非线性函数的数学形式为σ(x)=1/(1+e−x),如上图所示。如前一节所提到的,它取一个实数值,并将它“挤压”成0到1之间的范围。特别地,大负数变为0,大正数变成1。S形函数在历史上被频繁使用,因为它很好的模拟了神经元的启动率:从根本不启动(0)到完全饱和的启动在假定的最大频率(1)。在实践中,S形函数非线性最近很少用了。它有两个主要缺点:

 

  • 饱和**和梯度消失。S形函数神经元的一个非常不理想的特性是,当神经元的**在0或1的尾部饱和时,这些区域的梯度几乎为零。回想一下,在反向传播期间,这个(局部)梯度将被乘以这个节点的输出的梯度作为整个目标。因此,如果局部梯度很小,它将有效地“杀死”梯度,并且几乎没有信号会流过神经元到其权重并递归地返回到它的数据。另外,当初始化S形函数神经元的权重以防止饱和时,必须格外小心。例如,如果初始权值太大,那么大多数神经元将变得饱和,网络将几乎不学习。
  • S形函数输出不是零中心。这是不可取的,因为神经网络中稍后的处理层中的神经元将接收到非零中心的数据。这对梯度下降过程中的动力学有影响,因为如果进入神经元的数据总是正的(比如在f=W.T * x+b中每个元素都x>0),那么在反向传播过程中,权重w的梯度将变得全部为正,或者全部为负(取决于整个表达式的梯度f)。这可能导致权重的梯度更新呈z字型摇摆。然而,注意,一旦这些梯度在一批数据上加起来,权重的最终更新可以具有可变的标志,这样就从一定程度上减轻了这个问题。因此,相比上面的饱和**问题还不算很严重,只是不太方便。

 Tanh(双曲正切函数)。Tanh非线性函数如上图(右)所示。它将实值数字压制到范围[-1, 1 ]。与S形函数神经元一样,它也有**饱和问题,但不像S形函数神经元,其输出为零中心。因此,在实践中,Tanh非线性总是优于S形非线性。还注意到,Tanh神经元仅仅是一个缩放的S形神经元,具体形式是:tanh(x)=2σ(2x)−1 。


7、神经网络一: 建立网络架构7、神经网络一: 建立网络架构

左:整流线性单位(Relu)**函数,当x<0时为零,当x>0时,线性函数为斜率1。右:相比与tanh,ReLU 收敛有6倍的改进。详见Krizhevsky等人文章


ReLU. 整流线性单位在过去的几年里变得非常流行。它计算函数f(x)=max(0,x)。换句话说,**只是在零处阈值(见左上方的图像)。使用ReLUs有几个利弊:

  • (+) 实践发现,与Sigmoid /Tanh函数相比,随机加速下降的收敛速度更快(如Krizhevsky等人说的6倍)。有人认为这是由于它的线性、非饱和形式。
  • (+) 与涉及昂贵操作(指数等)的 tanh/sigmoid神经元相比,可以通过简单地在0处**矩阵来实现Relu。
  • (-) 不幸的是,Relu单元在训练过程中可能是脆弱的,并且可以“死亡”。例如,流过Relu神经元的大梯度会导致权重更新,这样神经元就不会再次**任何数据点。如果发生这种情况,那么流过该单元的梯度将从此点永远变为零。也就是说,Relu单元可以在训练期间不可逆地死亡,因为它们可以从数据歧管中被击穿。例如,您可能发现,如果学习速率设置得太高,多达40%的网络可以是“死的”(在整个训练集中这些神经元都不会被**)。通过合理设置学习率,能够降低这种情况的发生概率。

Leaky Relu 尝试解决 “ReLU死亡”的 问题。当x<0时,函数不是零,而是 会有一个小的负斜率(0.01左右)。也就是说,函数计算f(x)=1(x<0)(αx)+1(x>=0)(x),其中α是一个小的常数。有些人用这种形式的**函数报告成功,但结果并不总是一致的。在负区域中的斜率也可以被制成每个神经元的参数,如在PReLU 神经元,见 Delving Deep into Rectifiers, by Kaiming He et al., 2015。然而该**函数在不同任务中均有益处的一致性并没有特别清晰。

Maxout。还有一些其他类型的**函数,它们对于权重和数据的内积结果不再使用 f(w.T * X + b)这种形式。一个比较流行的选择是Maxout神经元(Goodfellow 等)。Maxout是对ReLU和leaky ReLU的一般化归纳,它的函数是:max(w1.T * X+b1,w2.T * X+b2)。ReLU和Leaky ReLU都是这个公式的特殊情况(比如ReLU就是当7、神经网络一: 建立网络架构的时候)。这样Maxout神经元就拥有ReLU单元的所有优点(线性操作和不饱和),而没有它的缺点(死亡的ReLU单元)。然而和ReLU对比,它每个神经元的参数数量增加了一倍,这就导致整体参数的数量激增。

以上就是一些常用的神经元及其**函数。最后需要注意一点:在同一个网络中混合使用不同类型的神经元是非常少见的,虽然没有什么根本性问题来禁止这样做。

一句话:“我应该使用什么类型的神经元?”用ReLU非线性函数,注意设置好学习率,可能的话监控你的网络中死亡的神经元占的比例。如果单元死亡问题困扰你,就试试Leaky ReLU或者Maxout,不要再用sigmoid了。也可以试试tanh,但是其效果应该不如ReLU或者Maxout。

 

7.3神经网络体系结构

7.3.1分层组织

神经网络细胞图。神经网络被建模成神经元的集合,神经元之间以无环图的形式进行连接。也就是说,一些神经元的输出可以成为其他一些神经元的输入。循环是不允许的,因为这样会导致前向传播的无限循环。通常神经网络模型中神经元是分层的,而不是像生物神经元一样聚合成大小不一的团状。最普通的层的类型是全连接层(fully-connected layer)。全连接层中的神经元与其前后两层的神经元是完全成对连接的,但是在同一个全连接层内的神经元之间没有连接。下面是两个神经网络的图例,都使用的全连接层:


7、神经网络一: 建立网络架构7、神经网络一: 建立网络架构

左:一个2层神经网络(一个4个神经元(或单位)隐藏层和一个2个神经元输出层),和三个输入。

右:一个3层神经网络,有三个输入,两个4个神经元的隐藏层和一个输出层。注意,在这两种情况下,都是跨层神经元之间有连接(突触),但层内没有。


名称约定。请注意,当我们说N层神经网络时,我们不计算输入层。因此,单层神经网络描述了一个没有隐藏层(直接映射到输出的输入)的网络。在这个意义上,逻辑回归或支持向量机只是单层神经网络的特例。这些网络可互换地称为“人工神经网络”(ANN)或“多层感知器”(MLP)。许多人不喜欢神经网络和真实大脑之间的类比,更喜欢把神经元称为单位。

输出层。与神经网络中的所有层不同,输出层神经元没有有**函数(或者您可以认为它们具有线性身份**函数)。这是因为最后的输出层通常被用来表示类分数(例如在分类中),它们是任意实数值,或某种实值目标(例如在回归中)。

确定网络尺寸。人们通常用来测量神经网络大小的两个度量是神经元的数量,或者更常见的是参数的数量。

用上面图示的两个网络举例:

  • 第一个网络有4+2=6个神经元(输入层不算),[3×4]+[4×2]=20个权重,还有4+2=6个偏置,共26个需要学习的参数。
  • 第二个网络有4+4+1=9个神经元,[3×4]+[4×4]+[4×1]=32个权重,4+4+1=9个偏置,共41个需要学习的参数。

现代卷积网络能包含约1亿个参数,并且通常由大约10-20层组成(所以称为深入学习)。参数共享会导致有效连接的数量显著增加。在卷积神经网络模块中对此有更多的阐述。

7.3.2 前馈计算实例

与**函数交织的重复矩阵乘法。神经网络被组织成层的主要原因之一是,这种结构使得使用矩阵向量运算来评估神经网络是非常简单和有效的。在上面的图中使用示例三层神经网络,输入将是[3x1]向量。一层的所有连接强度可以存储在一个矩阵中。例如,第一隐藏层的权重W1将是大小[4x3],并且对于所有单元的偏置将在向量B1中,大小为[4x1]。这里,每一个神经元在W1行中都有它的权重,因此矩阵向量乘积np.dot(W1,x)评估了该层中所有神经元的**。类似地,W2将是存储第二隐藏层的连接的a[4x4]矩阵和最后一个(输出)层的W3 a [1x4]矩阵。这3层神经网络的全正向传递只需要简单地用三个矩阵乘法,与**函数的应用交织在一起:

  1. # 一个3层神经网络的前向传播:

  2. f = lambda x: 1.0/(1.0 + np.exp(-x)) # **函数(用的sigmoid)

  3. x = np.random.randn(3, 1) # 含3个数字的随机输入向量(3x1)

  4. h1 = f(np.dot(W1, x) + b1) # 计算第一个隐层的**数据(4x1)

  5. h2 = f(np.dot(W2, h1) + b2) # 计算第二个隐层的**数据(4x1)

  6. out = np.dot(W3, h2) + b3 # 神经元输出(1x1)

在上述代码中,W1,W2,W3,b1,b2,b3 是网络的可学习参数。注意x不一定是一个单独的列向量,而可以是一个批量的训练数据(其中每个输入样本将会是x中的一列),所有的样本将会被并行化的高效计算出来。注意,最后的神经网络层通常不使用**函数(例如,它代表在分类设置中的(实值)类分数)。

全连接层的前向传播一般就是先进行一个矩阵乘法,然后加上偏置并应用**函数。

7.3.3 表达能力

理解全连接神经网络的一种方法是,它们定义了一个由一系列函数组成的函数族,网络的权重就是每个函数的参数。如此产生的问题是:该函数族的表达能力如何?存在不能被神经网络表达的函数吗?

研究表明,具有至少一个隐层的神经网络是通用逼近器。也就是说,可以看到(见 Approximation by Superpositions of Sigmoidal Function ,1989 , 或者 intuitive explanation ,Michael Nielsen),对于任何连续函数f(x)和一些ϵ>0,存在一个隐层的神经网络g(x)(合理选择**函数,比如sigmoid),使得∀x,∣f(x)−g(x)∣<ϵ,换言之,神经网络可以逼近任何连续函数。

如果一个隐藏层足以逼近任何函数,为什么要使用更多的层并深入?答案是,虽然一个2层网络在数学理论上能完美地近似所有连续函数,但在实际操作中效果相对较弱和无用。在一维中,“指标凸点和”函数 g(x)=∑ici1(ai<x<bi),其中a,b,c为参数向量,也是通用的近似器,但是谁也不会建议在机器学习中使用这个函数公式。神经网络在实践中很好用,因为它们表达出的函数对于数据的统计特性拟合得很好很平滑,也容易使用我们的优化算法(例如梯度下降)来学习。类似地,更深的网络(具有多个隐藏层)可以比单个隐藏层网络工作得更好,这是一个经验的观察,尽管事实上它们的表达能力是相等的

另一方面,在实践中,通常情况下,3层神经网络将优于2层网络,但若更深(4,5,6层)却不见得更加有益。这与卷积神经网络形成了鲜明的对比,深度在卷积网络中是一个很好的识别系统的一个非常重要的组成部分(例如,10层)。这种发现的一个论点是图像包含层次结构(例如,脸部是由眼睛组成的,由边缘组成,等等),因此处理的层数对该数据域具有直观意义。

当然,整个故事涉及更多,也是最近研究的主题。如果您对这些主题感兴趣,我们建议进一步阅读:

7.3.4 设置层数及其大小

当面对实际问题时,我们如何决定使用什么架构?我们应该不使用隐藏层吗?一个隐藏层?两个隐藏层?每层应该有多大?首先,注意,当我们增加神经网络中的层的大小和数量时,就能增加网络的能力。也就是说,可表示函数的空间增长,因为神经元可以协作来表达许多不同的功能。例如,假设我们在二维上有一个二分类问题。我们可以训练三个独立的神经网络,每一个都有一个隐藏的大小,得到以下分类器:


7、神经网络一: 建立网络架构

更大的神经网络可以表示更复杂的函数。数据被显示为由他们的类着色的圆点,并且由训练的神经网络决定区域被显示在下面。动态展示: ConvNetsJS demo.


上图中,我们可以看到,具有更多神经元的神经网络可以表达更复杂的功能。然而,这既是福(因为我们可以学会对更复杂的数据进行分类)也是祸诅咒(因为更容易导致过拟合训练数据)。当高容量的模型适合于数据中的噪声而不是(假定的)潜在关系时,会出现过拟合。例如,具有20个隐藏神经元的模型适合于所有的训练数据,但代价是将空间分割成许多不相交的红色和绿色决策区域。具有3个隐神经元的模型仅具有在宽笔划中对数据进行分类的代表性。它将数据建模为两个斑点,并将绿色集群内的几个红色点解释为离群点(噪声)。在实践中,这可以获得在测试集上更好的泛化能力

基于以上论述,如果数据不够复杂,较小的神经网络有利于防止过拟合。然而,这是不正确的-还有许多其他的方法来防止神经网络中的过拟合,我们稍后将讨论(例如L2正则化、dropout、输入噪声)。在实践中,最好使用这些方法来控制过拟合而不是控制神经元数目。

这背后的一个微妙的原因是较小的网络更难用局部方法来训练,例如梯度下降:很明显,它们的损失函数具有相对较少的局部极小值,但是事实证明,这些极小值中的许多更容易收敛,并且它们是坏的(即具有更高的损失)。相反,更大的神经网络包含明显更多的局部极小值,但这些最小值在实际损失方面是更好的。由于神经网络是非凸的,所以很难在数学上研究这些性质,但是已经做了一些尝试来理解这些目标函数,例如The Loss Surfaces of Multilayer Networks这篇论文。在实践中,如果你训练一个小的网络,最终的损失可以显示出大量的差异-在某些情况下,你很幸运,收敛到一个好的地方,但在某些情况下,你陷入了一个坏的极小值。另一方面,如果你训练一个大的网络,你会发现很多不同的解决方案,但是最终实现的损失的差异会小得多。换句话说,所有的解决方案都是同样好的,并且较少依赖于随机初始化参数的好坏。

重申,正则化强度是控制神经网络过拟合的首选方法。我们可以看看由三种不同的设置所获得的结果:


7、神经网络一: 建立网络架构

正则化强度的影响:上面的每个神经网络有20个隐藏的神经元,但是改变正则化强度,具有更高的正则化使得其最终决策区域更平滑。动态演示: ConvNetsJS demo.


若害怕过度拟合,不应该使用较小的网络。相反,在计算预算允许的情况下使用大的神经网络,并使用其他正则化技术来控制过度拟合。

 

7.4总结

  • 首先我们介绍了一个非常粗糙的生物神经元模型
  • 我们讨论了在实践中使用的数种类型的**函数,其中Relu是最常用的选择。
  • 我们引入了神经网络,其中神经元与全连接层连接,其中相邻层中的神经元具有全成对连接,但是层内的神经元没有连接。
  • 我们看到,分层的结构能够让神经网络高效地进行矩阵乘法和**函数运算
  • 我们发现神经网络是通用函数逼近器,但我们也讨论了这个性质与它们无处不在的使用无关。它们之所以被使用,是因为它们对实践中出现的函数的函数形式做出了“正确”的假设
  • 我们讨论了这样一个事实,即较大的网络总是比更小的网络工作得更好,但是它们的更高的模型容量必须用更强的正则化(例如更高的重量衰减)来适当地解决,否则会出现过拟合。后续章节我们将阐述更多形式的正规化(特别是dropout)

7.5参考文献

 

斯坦福大学计算机视图课程,青星大学 翻译整理

1、数据驱动的图像分类方法

2、最近邻分类器

3、k - 最近邻分类器及使用验证集取得超参数

4、线性分类: SVM, Softmax

5、优化方法:随机梯度下降法

6、反向传播

7、神经网络一: 建立网络架构

8、神经网络二:设置数据和损失

9、神经网络 三:学习与评价

10、神经网络案例学习

11、卷积神经网络:结构、卷积/汇集层

12、理解与可视化卷积神经网络

13、传承学习与卷积神经网络调谐

 

原文地址 http://cs231n.github.io/