概述
无需类比大脑的机制我们也能介绍神经网络。本节我们通过线性分类器,通过公式
计算分数时,采用
一个三层的神经网络类似于
神经元模型
与生物学的联系
神经网络这个领域最初的主要灵感来源于如何为生物神经系统建模。但此后神经网络分支成为工程问题,并在机器学习任务中取得了良好的结果。 所以,在我们开始讨论前,对这个让神经网络领域产生很大启发的生物系统,进行个非常简短和宏观的描述。
大脑的基本计算单位是一个神经元。人类神经系统中可发现大约860亿个神经元,并且它们与大约
图1 神经元模型
图2 数学模型
单个神经元的前向传播代码如下所示:
class Neuron(object): # ... def forward(self, inputs): """ assume inputs and weights are 1-D numpy arrays and bias is a number """ cell_body_sum = np.sum(inputs * self.weights) + self.bias firing_rate = 1.0 / (1.0 + math.exp(-cell_body_sum)) # sigmoid activation function return firing_rate1234567
换句话说,每个神经元对输入和权重进行点积操作,加上偏差后并采用非线性函数(或者叫激活函数)转换数据,上面代码采用的是
粗糙模型 需要强调的是,这种生物神经元模型非常粗糙:例如,有许多不同类型的神经元,每种神经元都具有不同的属性。 生物神经元中的树突执行复杂的非线性计算。 突触不仅仅有一个单一的权重,他们是一个复杂的非线性动力系统。 已知许多系统中输出尖峰的确切时间非常重要,这表明速率编码近似可能不成立。 由于采用了很多简化,因此当您在神经网络和真正的大脑之间进行类比,请准备好听取来自具有神经科学背景的任何人的不屑。
单神经元作为线性分类器
神经元前向计算的数学形式看起来很熟悉。 正如我们用线性分类器所看到的那样,神经元可以在输入空间的某些线性区域“喜欢”(激活值接近1)或“不喜欢”(激活值接近0)。因此,通过对神经元的输出采用适当的损失函数,我们可以将单个神经元变成线性分类器:
二元Softmax分类器。 例如,我们可以将
二元SVM分类器。 我们可以在神经元的输出上附加一个max-margin hinge loss,并将其训练成二元支持向量机。
正则化。 从在这个生物学的角度看,
常用的激活函数
每个激活函数(或非线性函数)都输入一个数字并对其执行某种固定的数学运算。 在实际中可能会遇到几种激活函数:
图3 sigmoid函数,将输入压缩到(0,1)范围内
图4 tanh函数,将输入压缩到(-1,1)范围内
sigmoid(图3所示)。 S型函数具有数学形式
Sigmoid函数饱和时会”杀死”梯度。 S形神经元非常不好的特性是,当神经元的激活在0或1的尾部饱和时,这些区域的梯度几乎为零。 回想一下,在反向传播过程中,这个(局部)梯度将乘以该神经元的输出对于整个目标的梯度。 因此,如果局部梯度非常小,它将有效地“杀死”梯度,几乎没有信号会通过神经元流向其权重并递归到其数据。因此,在初始化S形神经元的权重时,为防止饱和时,必须格外小心。例如,如果初始权重太大,那么大多数神经元会变得饱和,网络几乎不能进行学习。
Sigmoid输出不是以零为中心的。 这是我们不希望的特性,因为在神经网络的后续层中的神经元将接收不是以零为中心的数据。 这对梯度下降过程中的动力有影响,因为如果进入神经元的数据总是正的(例如,在
f=wTx+b 中所有x>0 )),则反向传播期间权重w 的梯度将全部为正或全部负(取决于整个表达式f的梯度)。 这会在权重的梯度更新中引入不希望的锯齿形动态更新。但是,请注意,处理完一批数据后(batch data),权重最终的更新可能会有可变的符号,这略微缓解了这个问题。因此,这是一个不便之处,但与上面的饱和激活问题相比,其后果不那么严重。
RELU(图5所示)。RELU(The Rectified Linear Unit)在过去几年中变得非常流行。它计算函数
(优点)与S形tanh函数相比,随机梯度下降的收敛速度显着加快(Krizhevsky等人文献中提到为6倍,图6显示为其对比)。有人认为,这是因为其线性非饱和形式的原因。
(优点)与涉及复杂操作(指数等)的tanh / sigmoid神经元相比,ReLU可以通过将激活矩阵简单地设置阈值为零来实现。
(缺点)不幸的是,在训练过程中,ReLU单元可能会变得脆弱,并可能“死亡”。例如,流经ReLU神经元的大梯度可能导致权重更新,使得神经元不会再在任何数据上激活。如果发生这种情况,那么从该点开始流经该单元的梯度将永远为零。也就是说,ReLU单元在训练期间可能会不可逆转地死亡。例如,如果学习率设置得太高,您可能会发现多达40%的网络可能“死亡”(即从未在整个训练数据集中激活的神经元)。通过设置合适的学习率,可以缓解这个问题。
图5 RELU函数
图6 ReLU收敛速度大约为tanh的6倍
leak ReLU。leak ReLUs是解决ReLU 单元”死亡”问题的一种尝试。当x <0时,leak ReLU将具有小的负斜率(大约为0.01左右)。也就是说,函数计算
MAXOUT。也有一些函数形式不是
这就结束了我们对最常见类型的神经元及其激活函数的讨论。 作为最后的评论,在同一网络中混合使用不同类型的神经元是非常罕见的,尽管这样做没有根本性的问题。
如果文:“我应该使用哪种神经元类型?”那么答案是:使用ReLU非线性,小心你的学习速率,并尽可能监测网络中“死亡”单元的比例。 如果出现了问题,请尝试使用Leaky ReLU或Maxout。 切勿使用sigmoid。 试试tanh,但一般情况下它比ReLU / Maxout更糟糕。
神经网络架构
分层组织
神经网络是作神经元组成的图。 神经网络模型是一个非循环图中连接的神经元集合。 换句话说,一些神经元的输出可以成为其他神经元的输入。 环是不允许的,因为这意味着在网络的正向传递中有无限循环。 神经网络模型通常组织成不同层次的神经元,而不是无组织的连接。 对于规则的神经网络,最常见的层类型是完全连接层,其中两个相邻层之间的神经元完全成对连接,但是单个层内的神经元不共享连接。 图7和图8是两个使用完全连接层的示例神经网络拓扑:
图7 2层神经网络(4个神经元的隐藏层和2个神经元的输出层)和三个输入。
图8 具有三个输入的三层神经网络,两个四个神经元的隐藏层和一个输出层。 请注意,在这两种情况下,跨层的神经元之间都存在连接(突触),但层内没有连接。
命名约定。请注意,当我们说N层神经网络时,我们不计入输入层。因此,单层神经网络描述了一个没有隐藏层的网络(输入直接映射到输出)。从这个意义上讲,你有时会听到人们说逻辑回归或支持向量机只是单层神经网络的特例。 您也可能会听到这些网络也会被称为“人工神经网络”(ANN)或“多层感知器”(MLP)。许多人不喜欢神经网络和真实大脑之间的类比,而更喜欢将神经元作为单元。
输出层。与神经网络中的其他层不同,输出层神经元通常不具有激活函数(或者可以将它们视为有线性激活函数)。这是因为最后的输出层通常被用来表示类别分数(例如在分类中),可能是任意的实数值,或者某种类型的实值目标(例如在回归中)。
衡量神经网络的大小。人们通常用来衡量神经网络大小的两个指标是神经元的数量,或者更常见的是参数的数量。在前文中使用两个示例网络:
第一个网络(图7)具有4 + 2 = 6个神经元(不包括输入),[3×4] + [4×2] = 20个权重和4 + 2 = 6个偏差,总共26个可学习参数。
第二个网络(图8)具有4 + 4 + 1 = 9个神经元,[3×4] + [4×4] + [4×1] = 12 + 16 + 4 = 32个权重和4 + 4 + 1 = 9偏差,总共41个可学习参数。
为了给你一些背景知识,现代卷积网络包含大约1亿个参数,通常由大约10-20层构成(因此深度学习)。但是,由于参数共享,我们将看到有效连接的数量显着增加。更多内容我们会在卷积神经网络章节中学习。
前馈计算示例
前馈计算实际上就是重复的矩阵乘法与激活函数的计算交织在一起。神经网络为层组织的主要原因之一就是这种结构进行矩阵向量操作计算神经网络非常简单高效。在上图中使用示例三层神经网络,输入是[3x1]向量。一个层的所有连接权重都可以存储在一个矩阵中。例如,第一个隐藏层的权重
# forward-pass of a 3-layer neural network:f = lambda x: 1.0/(1.0 + np.exp(-x)) #activation function (use sigmoid)x = np.random.randn(3, 1) # random input vector of three numbers (3x1)h1 = f(np.dot(W1, x) + b1) # calculate first hidden layer activations (4x1)h2 = f(np.dot(W2, h1) + b2) # calculate second hidden layer activations (4x1)out = np.dot(W3, h2) + b3 # output neuron (1x1)123456
在上面的代码中,W1,W2,W3,b1,b2,b3
是网络的可学习参数。 还要注意,变量x可以保存所有训练数据(其中每个输入样本将是x的一列),而不是只有单个输入列向量,这样所有样本将并行地进行计算。 此外,最后的神经网络层通常不具有激活功能(例如,它表示分类问题中的(实值)类分数)。
神经网络的表示能力
全连接层的神经网络实际上是定义了一系列由网络权重参数化的函数。一个很自然的问题是:这个函数族能表示能力如何?是否有不能用神经网络建模的函数?
事实证明,有一个以上隐藏层的神经网络是通用逼近器。也就是说,它可以表示出来(参见1989年Sigmoidal函数叠加的逼近(pdf),或Michael Nielsen的这个直观的解释),给定任意连续函数
如果一个隐藏层就足以近似任何函数,那为什么要使用更多的隐藏层呢?答案是,双层神经网络是一个通用逼近器,尽管在数学上很简便,但在实践中却是相对较弱且无用的。在一个维度中,函数
顺便说一下,在实践中,3层神经网络通常会比2层网络性能好很多,但更深层(4,5,6层)的性能提高不明显。这与卷积网络形成鲜明对比,现在发现卷积神经网络深度是良好识别系统(例如,按照10个可学习层的顺序)是非常重要的组成部分。支撑这种现象的一个观点是:图像包含分层结构(例如,面部由眼睛组成,其由边缘等组成),因此多层处理对于该数据域而言是直观的。
当然,整个问题涉及更多知识,也是最近研究的主题。如果您对这些主题感兴趣,我们建议您进一步阅读:
Deep Learning ,尤其是第6.4节。
Do Deep Nets Really Need to be Deep?
FitNets: Hints for Thin Deep Nets
设置图层数量及其大小
在实际问题中,我们如何选择架构?我们应该使用隐藏层吗?一个隐藏层?或两个隐藏层?每层应该有多少单元?首先,随着我们增加神经网络中的层大小和数量,网络的容量也会增大。也就是说,可表示函数的空间会增加,因为神经元可以合作表达许多不同的函数。例如,假设我们在二维中存在二元分类问题。我们可以训练三个独立的神经网络,每个神经网络都有一个大小不等的隐藏层,并获得以下分类器:
图9 越大的神经网络可以代表越复杂的函数。圆圈代表数据点,不同颜色代表不同类别。并且由训练的神经网络决定的区域显示在下方。你可以在这个ConvNetsJS中演示这些例子。
在图9中,我们可以看到具有更多神经元的网络可以表达更复杂的函数。然而,这既有好处(因为我们可以学习分类更复杂的数据)也有坏处(因为它更容易过度训练数据)。当具有高复杂度的模型拟合数据中的噪音而不是(假定的)数据之间的潜在关系时,过拟合就会发生。例如,具有20个隐藏神经元的模型拟合了所有训练数据,但是它将空间分割成许多不相交的红色和绿色决策区域。3个隐藏神经元的模型具有的表示能力只能将数据粗笔画地分类。它将数据建模为两块,并将绿色簇内的少数红色点解释为异常值(噪声)。在实践中,这可能会使模型对测试集有更好的泛化能力。
基于我们上面的讨论,如果数据不够多,为防止过拟合似乎较小的神经网络是更优选的。然而,这是不正确的,有许多其他的方法可以防止过度拟合(例如L2正则化(regularization) ,丢失(DropOut),输入噪声(input noise))。在实践中,使用这些方法来控制过度拟合比控制神经元数量的效果要好。
这背后的一个微妙的原因是,梯度下降等局部方法在较小的网络中更难进行:很显然,它们的损失函数具有相对较少的局部最小值,但事实证明,局部最小值越多越容易收敛,而且较小网络的局部最小值是不好的(即高损失)。相反,更大的神经网络包含更多的局部最小值,但是这些最小值在实际损失方面要比较小的网络好得多。由于神经网络是非凸的,所以很难从数学上研究这些性质,但是为了理解这些目标函数研究者已经做了一些尝试,例如,在最近的论文The Loss Surfaces of Multilayer Networks。在实践中,你发现如果你训练一个小型网络,最终的损失可能会表现出很大的差异 - 在某些情况下,你很幸运收敛到一个低损失的局部最小值,但有时,你又会陷入一个高损失的局部最小值。另一方面,如果你训练一个大型网络,你会发现许多不同的解决方案,但最终实现的损失差异会小得多。换句话说,所有的解决方案都大致相同,并且不依赖于随机初始化的运气。
重申一下,正则化强度是控制神经网络过度拟合的首选方法。我们可以看看三种不同正则化的结果:
图10 正则化强度的影响:每个神经网络有20个隐藏的神经元,提高正则化参数使其最终决策区域更平滑。你可以在这个ConvNetsJS中演示这个例子
结论是你不应该因为害怕而使用较小的网络。相反,您应该根据计算预算允许的限制来设置神经网络的大小,并使用其他正则化手段来控制过拟合。
概要
综上所述:
我们介绍了一个非常粗糙的生物神经元模型
我们讨论了在实践中使用的几种类型的激活函数,其中ReLU是最常用的
我们介绍了神经网络,神经元与完全连接的层连接时,相邻层中的神经元具有完全的成对连接,但层内的神经元没有连接
我们看到,这种分层架构能够交织使用激活函数和矩阵乘法,对神经网络进行高效评估
我们看到,神经网络是通用函数逼近器,但这个属性与它们被广泛使用无关。它们的使用是因为它们对实践中出现函数的形式做出了某些“正确”的假设
大型网络总是比小型网络工作得更好,但是它们更大的复杂度必须通过更强的正则化(比如更大的权重衰减)来解决,否则它们可能会过拟合。在后面的章节中我们会看到更多的正则化形式(特别是Droout)。
引用
deeplearning.net tutorial with Theano
ConvNetJS直观的演示
Michael Nielsen’s tutorials
共同学习,写下你的评论
评论加载中...
作者其他优质文章