机器学习之神经网络算法

来源:互联网 发布:邪恶漫画软件大全 编辑:程序博客网 时间:2024/06/05 17:18

机器学习之神经网络算法

在机器学习和认知科学领域,人工神经网络(英文:artificial neural network,缩写ANN),简称神经网络(英文:neural network,缩写NN)或类神经网络,是一种模仿生物神经网络(动物的中枢神经系统,特别是大脑)的结构和功能的数学模型或计算模型,用于对函数进行估计或近似。神经网络由大量的人工神经元联结进行计算。大多数情况下人工神经网络能在外界信息的基础上改变内部结构,是一种自适应系统。[来源请求]现代神经网络是一种非线性统计性数据建模工具。

神经网络(Neural Network)概述

神经网络算法能够提供一种复杂且非线性的假设模型hW,b(x),它具有参数W,b,可以以此参数来拟合我们的数据。

为了描述神经网络,我们先从最简单的神经网络讲起,这个神经网络仅由一个“神经元”构成,以下即是这个“神经元”的图示:

singleneuron

这个“神经元”是一个以x1,x2,x3及截距+1为输入值的运算单元,其输出为hW,b(x)=f(WTx)=f(3i=1Wixi+b),其中函数f:RR被称为“激活函数”。在本教程中,我们选用sigmoid函数作为激活函数f()

f(z)=11+exp(z)

可以看出,这个单一“神经元”的输入-输出映射关系其实就是一个逻辑回归(logistic regression)。

虽然本系列教程采用sigmoid函数,但你也可以选择双曲正切函数(tanh):

f(z)=tanh(z)=ezezez+ez

以下分别是sigmoid及tanh的函数图像

sigmoid function tanh

tanh(z)函数是sigmoid函数的一种变体,它的取值范围为[1,1],而不是sigmoid函数的[0,1]

注意,与其它地方不同的是,这里我们不再令x0=1。取而代之,我们用单独的参数b来表示截距。

最后要说明的是,有一个等式我们以后会经常用到:如果选择f(z)=1/(1+exp(z)),也就是sigmoid函数,那么它的导数就是f(z)=f(z)(1f(z))(如果选择tanh函数,那它的导数就是f(z)=1(f(z))2,你可以根据sigmoid(或tanh)函数的定义自行推导这个等式。

神经网络模型

所谓神经网络就是将许多个单一“神经元”联结在一起,这样,一个“神经元”的输出就可以是另一个“神经元”的输入。例如,下图就是一个简单的神经网络:

network331

我们使用圆圈来表示神经网络的输入,标上“+1”的圆圈被称为偏置节点,也就是截距项。神经网络最左边的一层叫做输入层,最右的一层叫做输出层(本例中,输出层只有一个节点)。中间所有节点组成的一层叫做隐藏层,因为我们不能在训练样本集中观测到它们的值。同时可以看到,以上神经网络的例子中有3个输入单元(偏置单元不计在内),3个隐藏单元及一个输出单元。

我们用nl来表示网络的层数,本例中 nl=3,我们将第l层记为Ll,于是L1是输入层,输出层是Lnl。本例神经网络有参数(W,b)=(W(1),b(1),W(2),b(2)),其中W(l)ij(下面的式子中用到)是第l层第j单元与第l+1层第i单元之间的联接参数(其实就是连接线上的权重,注意标号顺序),b(l)i是第l+1层第i单元的偏置项。因此在本例中,W(1)R3×3W(2)R1×3。注意,没有其他单元连向偏置单元(即偏置单元没有输入),因为它们总是输出+1。同时,我们用sl表示第l层的节点数(偏置单元不计在内)。

我们用a(l)i表示第l层第i单元的激活值(输出值)。当l=1时,a(1)i=xi,也就是第i个输入值(输入值的第i个特征)。对于给定参数集合W,b,我们的神经网络就可以按照函数hW,b(x)来计算输出结果。本例神经网络的计算步骤如下:

a(2)1a(2)2a(2)3hW,b(x)=f(W(1)11x1+W(1)12x2+W(1)13x3+b(1)1)=f(W(1)21x1+W(1)22x2+W(1)23x3+b(1)2)=f(W(1)31x1+W(1)32x2+W(1)33x3+b(1)3)=a(3)1=f(W(2)11a(2)1+W(2)12a(2)2+W(2)13a(2)3+b(2)1)

我们用z(l)i表示第l层第i单元输入加权和(包括偏置单元),比如,z(2)i=nj=1W(1)ijxj+b(1)i,则a(l)i=f(z(l)i)

这样我们就可以得到一种更简洁的表示法。这里我们将激活函数f()扩展为用向量(分量的形式)来表示,即f([z1,z2,z3])=[f(z1),f(z2),f(z3)],那么,上面的等式可以更简洁地表示为:

z(2)a(2)z(3)hW,b(x)=W(1)x+b(1)=f(z(2))=W(2)a(2)+b(2)=a(3)=f(z(3))

我们将上面的计算步骤叫作前向传播。回想一下,之前我们用a(1)=x表示输入层的激活值,那么给定第l层的激活值a(l)后,第l+1层的激活值a(l+1)就可以按照下面步骤计算得到:

z(l+1)a(l+1)=W(l)a(l)+b(l)=f(z(l+1))

将参数矩阵化,使用矩阵-向量运算方式,我们就可以利用线性代数的优势对神经网络进行快速求解。

目前为止,我们讨论了一种神经网络,我们也可以构建另一种结构的神经网络(这里结构指的是神经元之间的联接模式),也就是包含多个隐藏层的神经网络。最常见的一个例子是nl层的神经网络,第1层是输入层,第nl层是输出层,中间的每个层l与层l+1紧密相联。这种模式下,要计算神经网络的输出结果,我们可以按照之前描述的等式,按部就班,进行前向传播,逐一计算第L2层的所有激活值,然后是第L3层的激活值,以此类推,直到第Lnl层。这是一个前馈神经网络的例子,因为这种联接图没有闭环或回路。

神经网络也可以有多个输出单元。比如,下面的神经网络有两层隐藏层:L2L3,输出层L4有两个输出单元。
network3322

要求解这样的神经网络,需要样本集(x(i),y(i)),其中y(i)R2。如果你想预测的输出是多个的,那这种神经网络很适用。(比如,在医疗诊断应用中,患者的体征指标就可以作为向量的输入值,而不同的输出值yi可以表示不同的疾病存在与否。)

Backpropagation算法

假设我们有一个固定样本集(x(1),y(1)),,(x(m),y(m)),它包含m个样例。我们可以用批量梯度下降法来求解神经网络。具体来讲,对于单个样例(x,y),其代价函数为:

J(W,b;x,y)=12hW,b(x)y2.

这是一个(二分之一的)方差代价函数。给定一个包含m个样例的数据集,我们可以定义整体代价函数为:
J(W,b)=[1mi=1mJ(W,b;x(i),y(i))]+λ2l=1nl1i=1slj=1sl+1(W(l)ji)2=[1mi=1m(12hW,b(x(i))y(i)2)]+λ2l=1nl1i=1slj=1sl+1(W(l)ji)2

以上关于J(W,b)定义是一个均方差项。以上的代价函数经常被用于分类和回归问题。在分类问题中,我们用y=01,来代表两种类型的标签(回想一下,这是因为 sigmoid激活函数的值域为[0,1];如果我们使用双曲正切型激活函数,那么应该选用1+1作为标签)。对于回归问题,我们首先要变换输出值域(译者注:也就是y,以保证其范围为[0,1](同样地,如果我们使用双曲正切型激活函数,要使输出值域为[1,1]

我们的目标是针对参数Wb来求其函数J(W,b)的最小值。为了求解神经网络,我们需要将每一个参数W(l)ijb(l)i初始化为一个很小的、接近零的随机值(比如说,使用正态分布Normal(0,ϵ2)生成的随机值,其中ϵ设置为0.01,之后对目标函数使用诸如批量梯度下降法的最优化算法。因为J(W,b)是一个非凸函数,梯度下降法很可能会收敛到局部最优解;但是在实际应用中,梯度下降法通常能得到令人满意的结果。最后,需要再次强调的是,要将参数进行随机初始化,而不是全部置为0。如果所有参数都用相同的值作为初始值,那么所有隐藏层单元最终会得到与输入值有关的、相同的函数(也就是说,对于所有iW(1)ij都会取相同的值,那么对于任何输入x都会有:a(2)1=a(2)2=a(2)3=。随机初始化的目的是使对称失效。

梯度下降法中每一次迭代都按照如下公式对参数Wb 进行更新:

W(l)ijb(l)i=W(l)ijαW(l)ijJ(W,b)=b(l)iαb(l)iJ(W,b)

其中α是学习速率。其中关键步骤是计算偏导数。我们现在来讲一下反向传播算法,它是计算偏导数的一种有效方法。

我们首先来讲一下如何使用反向传播算法来计算W(l)ijJ(W,b;x,y)b(l)iJ(W,b;x,y),这两项是单个样例(x,y)的代价函数J(W,b;x,y)的偏导数。一旦我们求出该偏导数,就可以推导出整体代价函数J(W,b)的偏导数:

W(l)ijJ(W,b)b(l)iJ(W,b)=1mi=1mW(l)ijJ(W,b;x(i),y(i))=1mi=1mb(l)iJ(W,b;x(i),y(i))

反向传播算法的思路如下:给定一个样例(x,y),我们首先进行“前向传导”运算,计算出网络中所有的激活值,包括hW,b(x)的输出值。之后,针对第l层的每一个节点i,我们计算出其“残差”δ(l)i,该残差表明了该节点对最终输出值的残差产生了多少影响。对于最终的输出节点,我们可以直接算出网络产生的激活值与实际值之间的差距,我们将这个差距定义为δ(nl)i(第nl层表示输出层)。对于隐藏单元我们如何处理呢?我们将基于节点(译者注:第l+1层节点)残差的加权平均值计算δ(l)i,这些节点以a(l)i作为输入。下面将给出反向传导算法的细节:

进行前馈传导计算,利用前向传导公式,得到L2,L3,直到输出层Lnl的激活值。
对于第nl层(输出层)的每个输出单元i,我们根据以下公式计算残差:

δ(nl)i=z(nl)i12yhW,b(x)2=(yia(nl)i)f(z(nl)i)

[译者注:

δ(nl)i=znliJ(W,b;x,y)=znli12yhW,b(x)2=znli12j=1Snl(yja(nl)j)2=znli12j=1Snl(yjf(z(nl)j))2=(yif(z(nl)i))f(z(nl)i)=(yia(nl)i)f(z(nl)i)]

l=nl1,nl2,nl3,,2的各个层,第l层的第i个节点的残差计算方法如下:
δ(l)i=j=1Sl+1W(l)jiδ(l+1)jf(z(l)i)

{译者注:

δ(nl1)i=znl1iJ(W,b;x,y)=znl1i12yhW,b(x)2=znl1i12j=1Snl(yja(nl)j)2=12j=1Snlznl1i(yja(nl)j)2=12j=1Snlznl1i(yjf(z(nl)j))2=j=1Snl(yjf(z(nl)j))z(nl1)if(z(nl)j)=j=1Snl(yjf(z(nl)j))f(z(nl)j)z(nl)jz(nl1)i=j=1Snlδ(nl)jz(nl)jznl1i=j=1Snlδ(nl)jznl1ik=1Snl1f(znl1k)Wnl1jk=j=1Snlδ(nl)jWnl1jif(znl1i)=j=1SnlWnl1jiδ(nl)jf(znl1i)

将上式中的nl1nl的关系替换为ll+1的关系,就可以得到:δ(l)i=(sl+1j=1W(l)jiδ(l+1)j)f(z(l)i)
以上逐次从后向前求导的过程即为“反向传导”的本意所在。
计算我们需要的偏导数,计算方法如下:

W(l)ijJ(W,b;x,y)b(l)iJ(W,b;x,y)=a(l)jδ(l+1)i=δ(l+1)i.

最后,我们用矩阵-向量表示法重写以上算法。我们使用“” 表示向量乘积运算符,也称作阿达马乘积。若a=bc,则ai=bici。在上一个教程中我们扩展了f()的定义,使其包含向量运算,这里我们也对偏导数f()也做了同样的处理(于是又有f([z1,z2,z3])=[f(z1),f(z2),f(z3)]

那么,反向传播算法可表示为以下几个步骤:
进行前馈传导计算,利用前向传导公式,得到L2,L3,直到输出层Lnl的激活值。
对输出层(第nl层),计算:

δ(nl)=(ya(nl))f(z(nl))

对于l=nl1,nl2,nl3,,2的各层,计算:
δ(l)=((W(l))Tδ(l+1))f(z(l))

计算最终需要的偏导数值:
W(l)J(W,b;x,y)b(l)J(W,b;x,y)=δ(l+1)(a(l))T,=δ(l+1).

实现中应注意:在以上的第2步和第3步中,我们需要为每一个i值计算其f(z(l)i)。假设f(z)是sigmoid函数,并且我们已经在前向传导运算中得到了a(l)i。那么,使用我们早先推导出的f(z)表达式,就可以计算得到f(z(l)i)=a(l)i(1a(l)i)

最后,我们将对梯度下降算法做个全面总结。在下面的伪代码中,ΔW(l)是一个与矩阵W(l)维度相同的矩阵,Δb(l)是一个与b(l)维度相同的向量。注意这里“ΔW(l)”是一个矩阵,而不是“ΔW(l)相乘”。下面,我们实现批量梯度下降法中的一次迭代:

  1. 对于所有l,令ΔW(l):=0,Δb(l):=0(设置为全零矩阵或全零向量)

  2. 对于i=1m

    a. 使用反向传播算法计算W(l)J(W,b;x,y)b(l)J(W,b;x,y)

    b. 计算ΔW(l):=ΔW(l)+W(l)J(W,b;x,y)

    c. 计算Δb(l):=Δb(l)+b(l)J(W,b;x,y)

  3. 更新权重参数:

    W(l)b(l)=W(l)α[(1mΔW(l))]=b(l)α[1mΔb(l)]

    现在,我们可以重复梯度下降法的迭代步骤来减小代价函数J(W,b)的值,进而求解我们的神经网络。

神经网络优化

柔性最大值(softmax)

另外一种解决学习缓慢问题的方法。

柔性最大值的想法其实就是为神经网络定义一种新式的输出层。

  1. 基本原理

    (1). 首先计算带权输入

    ZLj=kwLjkaL1k+bLj

    (2). 不在带权输入z上使用S型函数来获得输出,而是使用softmax函数来获得输出。

    aLj=ezLjkezLk(1)

    其中,分母中的求和是在所有的输出神经元上进行的。另外一个特性:根据定义,输出的激活值加起来正好为1。

    jaLj=jezLjkezLk(2)

    由公式(1)(2),我们看到柔性最大值层的输出是一些相加为1正数的集合。换言之,柔性最大值层的输出可以被看做是一个概率分布。在很多问题中,使用softmax是很方便的。比如在MNIST分类问题中,我们可以将输出层第j个神经元的激活值解释成网络估计正确数字分类为j的概率。

  2. softmax如何解决学习缓慢的问题?
    先定义一个对数似然(log-likelihood)代价函数。对数似然函数满足我们期待的代价函数的条件。对数似然代价函数关于权重和偏置的偏导数分别是:这些方程其实和之前的交叉熵得到的类似。只是之前的是平均值。正如前面的分析,这些表达式确保我们不会遇到学习缓慢的问题。事实上,把一个具有对数似然代价的柔性最大值输出层,看作与一个具有交叉熵代价的S型输出层非常相似,这是很有用的。

  3. 应该使用一个具有交叉熵代价的S 型输出层,还是一个具有对数似然代价的柔性最大值输出层呢?
    实际上,在很多应用场景中,这两种方式的效果都不错。
    柔性最大值加上对数似然的组合更加适用于那些需要将输出激活值解释为概率的场景。

交叉熵代价函数(The cross-entropy cost function

在采用softmax为神经网络定义了输出层后,其对应的代价函数为交叉熵代价函数也称为对数似然代价函数(The log-likelihood cost function)。令a=σ(z),z=jwjxj+b,对于单个样例(x,y),其代价函数为:

J(W,b;x,y)=(lna(1y)ln(1a))

对于一个包含m个样例的数据集,我们可以定义整体交叉熵代价函数为:
J(W,b)=1mi=1my(i)lna(1y(i))ln(1a)

将交叉熵看作代价函数,是基于它的以下两个特性:

(1). 它是非负的。

(2). 如果对于所有的训练输入x,神经元实际的输出接近目标值,那么交叉熵将接近0。
相比于二次代价函数,交叉熵还有一个特性可以避免学习速度下降的问题。

  1. 为什么交叉熵代价函数代价函数可以解决学习慢的问题?

    因为交叉熵函数关于权重和偏置的偏导数的表达式中不存在σ'(z)这样的项,从而避免了学习缓慢。具体分析如下:
    二次函数关于权重和偏置的偏导数分别是:

    J(W,b)wJ(W,b)b=(ay)σ(z)x=(ay)σ(z)

    σ函数(sigmoid函数)的图像在神经元的输出接近1的时候,曲线变得相当平,所以σ'(z)就很小了。上述公式也告诉我们J(W,b)/wJ(W,b)/b值会非常小。这其实就是学习缓慢的原因所在。

    交叉熵函数关于权重和偏置的偏导数分别是:

    J(W,b)wjJ(W,b)b=1mi=1mxj(σ(z)y)=1mi=1m(σ(z)y)

    上述公式表明权重学习的速度受到σ(z)y,也就是输出中的误差的控制。同时交叉熵函数还避免了像在二次代价函数中类似σ(z)导致的学习缓慢。

  2. 学习率的选择

    不同的代价函数应该搭配不同的学习率。

  3. 在什么时候用交叉熵来替换二次代价函数?

    如果在输出神经元是S 型神经元时,交叉熵一般都是更好的选择。
    如果输出神经元是线性的那么二次代价函数不再会导致学习速度下降的问题。在此情形下,二次代价函数就是一种合适的选择。

过度拟合(Overfitting)

  1. 检测过度拟合

    我们在每个迭代期的最后都计算在validation_data 上的分类准确率。一旦分类准确率已经饱和,就停止训练。这个策略被称为提前停止。

  2. 降低过度拟合

    (1). 一般来说,最好的降低过度拟合的方式之一就是增加训练样本的量。有了足够的训练数据,就算是一个规模非常大的网络也不大容易过度拟合。不幸的是,训练数据其实是很难或者很昂贵的资源,所以这不是一种太切实际的选择。

    (2). 降低网络规模。但是更深层更大的网络潜在有更强的学习能力。

    (3). 规范化。即使对于固定的神经网络和固定的训练集, 仍然可以减少overfitting。

正则化/规范化(regularization)

  1. 基本原理

    规范化有很多技术,这里给出一种最为常用的规范化手段—— 有时候被称为权重衰减(weight decay)或者L2 规范化。
    L2 规范化的想法是增加一个额外的项到代价函数上,这个项叫做规范化项。

    J(W,b)=[1mi=1m(12hW,b(x(i))y(i)2)]+λ2l=1nl1i=1slj=1sl+1(W(l)ji)2

    以上关于J(W,b)定义中的第一项是一个均方差项。第二项是一个规则化项(也叫权重衰减项),其目的是减小权重的幅度,防止过度拟合。

    [注:通常权重衰减的计算并不使用偏置项b(l)i,比如我们在J(W,b)的定义中就没有使用。一般来说,将偏置项包含在权重衰减项中只会对最终的神经网络产生很小的影响。如果你在斯坦福选修过CS229(机器学习)课程,或者在YouTube上看过课程视频,你会发现这个权重衰减实际上是课上提到的贝叶斯规则化方法的变种。在贝叶斯规则化方法中,我们将高斯先验概率引入到参数中计算MAP(极大后验)估计(而不是极大似然估计)。]

    权重衰减参数λ用于控制公式中两项的相对重要性。在此重申一下这两个复杂函数的含义:J(W,b;x,y)是针对单个样例计算得到的方差代价函数;J(W,b)是整体样本代价函数,它包含权重衰减项。

    含有权重衰减项的出整体代价函数J(W,b)的偏导数:

    W(l)ijJ(W,b)b(l)iJ(W,b)=1mi=1mW(l)ijJ(W,b;x(i),y(i))+λW(l)ij=1mi=1mb(l)iJ(W,b;x(i),y(i))

    以上两行公式稍有不同,第一行比第二行多出一项,是因为权重衰减是作用于W而不是b

    含有权重衰减项的权重参数更新:

    W(l)b(l)=W(l)α[(1mΔW(l))+λW(l)]=b(l)α[1mΔb(l)]

    规范化的效果是让网络倾向于学习小一点的权重。
    规范化可以当做一种寻找小的权重和最小化原始的代价函数之间的折中。由λ的取值决定,λ越小,就偏向于最小化原始代价函数,反之,倾向于小的权重。

  2. 好处

    (1)减轻过度拟合和提高分类准确率。

    (2)规范化的网络能够提供更容易复制的结果。无规范化的网络会偶然被限制住,不同的运行会给出相差很大的结果。

  3. 为何规范化可以帮助减轻过度拟合?

    规范化的神经网络常常能够比非规范化的泛化能力更强,这只是一种实验事实(empirical fact)。目前还没有一整套具有说服力的理论解释。仅仅是一些不完备的启发式规则或者经验。

  4. 正则化的其他技术

    (1)L1 规范化:是在未规范化的代价函数上加上一个权重绝对值的和。

    (2)弃权(Dropout):从随机(临时)地删除网络中的一半的隐藏神经元开始,同时让输入层和输出层的神经元保持不变。

    (3)人为增加训练样本

权重初始化(Weight initialization)

理解这部分需要先弄明白正态分布(高斯分布)、均值、标准差、方差的意义。

结论:假设我们有一个有n个输入权重的神经元,我们会使用均值u=0,标准差ϵ=1/sqrt(n)的正态随机分布初始化这些权重。

原因:若这样初始化的话,那么大部分带权输入z的取值都在1和-1之间,隐藏神经元的输出σ(z)就不太会接近1或者0。也就是神经元没有饱和,学习过程不会被减慢。

参考资料

UFLDL教程-神经网络

UFLDL教程-反向传导算法

Improving the way neural networks learn

神经网络与深度学习(4):改进神经网络的学习方法

原创粉丝点击