Deep Learning 1.1 深度前馈网络

Deep Learning 1.1 深度前馈网络

深度前馈网络(deep feedforward network),也叫做前馈神经网络(feedforward neural network)或者多层感知机(multilayer perceptionm, MLP),是典型的深度学习模型。前馈网络的目标是近似某个函数f*f^*。例如,对于分类器,将输入映射到一个类别y。前馈网络定义了一个映射,并且学习参数的值,使它能够得到最佳的函数近似

这种模型称为前向的,是因为信息流过x\mathbf{x}的函数,流经用于定义f的中间计算过程,最终到达。在模型的输入和模型本身之间没有反馈连接。当前馈神经网路被扩展成包含反馈连接时,它们被称为循环神经网络(recurrent neural network)

前馈网络之所以被称为网络,是因为它们通常用许多不同函数复合在一起来表示。该模型与一个有向无环图相关联,而图描述了函数是如何复合在一起的。例如,我们有三个函数连接在一条脸上以形成。这些链式结构是神经网络中最常用的结构。在这种情况下,网络被分为多个层,链的全长被称为模型的深度(depth)。前馈网络的最后一层被称为输出层(output layer)。在神经网络训练的过程中,我们让去匹配的值。训练数据为我们提供了在不同训练点上取值的、含有噪声的f*(x)f^*(\mathbf{x})的近似实例。每个样本x\mathbf{x}都伴随着一个标签yf*(x)。训练样本直接指明了输入层在每一点x\mathbf{x}上必须做什么;它必须产生一个接近y的值。但是训练数据并没有直接指明其他层应该怎么做。学习算法必须决定如何使用这些层来产生想要的输出,但是训练数据并没有说每个单独的层应该做什么。相反,学习算法必须决定如何使用这些层来最好地实现f*f^*的近似。因为训练数据并没有给出这些层中的每一层所需的输出,所以这些层被称为隐藏层

网络中的每个隐藏层通常都是向量值的。这些隐藏层的维数决定了模型的宽度(width)。向量的每个元素都可以被视为起到类似一个神经元的作用。除了将层想想成向量到向量的单个函数,我们也可以把层想象成由许多并行操作的单元组成,每个单元表示一个向量到标量的函数。

一种理解前馈网络的方式是从线性模型开始,考虑如何克服它的局限性。线性回归无论是通过闭解形式还是使用凸优化都能高效并且可靠的拟合。线性模型也有明显的缺陷,那就是该模型的能力被局限在线性函数里,无法理解任何两个输入变量之间的相互作用

为了扩展线性模型来表示x\mathbf{x}的非线性函数,我们可以不把线性模型用于x\mathbf{x}本身,而是用在一个变换后的输入ϕ(x)上,这里ϕ是一个非线性变换。同样,我们可以使用核技巧,来得到一个基于隐含地使用ϕ\phi映射的非线性学习算法。我们可以认为ϕ\phi提供了一组描述x\mathbf{x}的特征

剩下的问题就是如何选择映射ϕ\phi

一种选择是使用一个通用的ϕ\phi,例如无限维的ϕ\phi,这样我们总是由足够的能力来拟合训练集,但是对于测试集的泛化往往不佳。非常通用的特征映射通常只基于局部光滑的原则,并且没有将足够的先验信息进行编码来解决高级问题

另一种选择是手动地设计ϕ\phi。这种方法对于每个单独的任务都需要人们数十年地努力,在不同的领域之间很难迁移

深度学习的策略是去学习ϕ\phi。在这种方法中,我们有一个模型y=f(x;θ,w)=ϕ(x;θ)w。我们现在有两种参数:用于从一大类函数中学习ϕ\phi的参数θ,以及用于将ϕ(x)\phi(\mathbf{x})映射到所需的输出的参数w。这是深度前馈网络的一个例子,其中ϕ\phi定义了一个隐藏层。

训练一个前馈网络至少需要做和线性模型同样多的设计决策:选择一个优化模型、代价函数以及输出单元的形式。前馈网络引入了隐藏层的概念,这需要我们去选择计算隐藏层值的激活函数(activation function)。我们还必须设计网络的结构,包括网络应该包含多少层、这些层应该如何连接、以及每一层包含多少单元。在深度神经网络的学习中需要计算复杂函数的梯度。我们给出反向传播(back propagation)算法和它的现代推广来高效的计算这个梯度

学习XOR

XOR函数是两个二进制值x1x2的运算。当这些二进制值中恰好有一个为1时,XOR函数的返回值为1。XOR函数提供了我们想要学习的目标函数y=f*(x)。我们的模型给出了一个函数y=f(x;θ),并且我们的学习算法会不断调整参数θ\mathbf{\theta}来使得f尽可能接近f*f^*

在这个例子中,我们只希望网络在这4个点X={[0,0],[0,1],[1,0],[1,1]}上表现正确

我们可以把这个问题当作回归问题,使用均方误差损失函数,评估整个训练集上表现的MSE代价函数为

J(θ)=14xX(f*(x)f(x;θ))2

假设选择一个线性模型,θ\mathbf{\theta}包含w\mathbf{w}b,那么模型被定义为

f(x;w,b)=xw+b

我们可以使用正规方程关于w\mathbf{w}bb最小化J(θ),来得到一个闭式解

求解正规方程以后,我们得到w=0以及b=12。线性模型仅仅是在任意一点都输出0.5,不能用来表示XOR函数。解决这个问题的其中一种方法是使用一个模型来学习一个不同的特征空间,在这个空间上线性模型能够表示这个解

具体来说,我们引入一个非常简单的前馈神经网络,它有一层隐藏层并且隐藏层中包含两个单元。这个前馈网络有个通过函数计算得到的隐藏单元的向量h,这些隐藏单元的值随后被用作第二层的输入。第二层就是这个网络的输出层。输出层仍然是一个线性回归模型,只不过现在它作用于h\mathbf{h}而不是x\mathbf{x}

如果第一层的函数仍然是线性的,那么前馈网络作为一个整体对于输入仍然是线性的。显然我们必须用非线性函数来描述这些特征。大多数神经网络通过仿射变换之后紧跟着一个被称为激活函数的固定非线性函数来实现这个目标,其中仿射变换由学得的参数控制。我们使用这种策略,定义h=g(Wx+c),其中W是线性变换的权重矩阵,c是偏置。激活函数g通常选择对每个元素分别起作用的函数,有hi=g(xW:,i+ci)。在现代神经网络中,默认的推荐是使用由激活函数g(z)=max{0,z}定义的整流线性单元(rectified linear unit)或者称为ReLU

现在可以指明我们的整个网络是

f(x;W,c,w,b)=wmax{0,Wx+c}+b

我们现在可以给出XOR问题的一个解。令

W=1111

c=01

w=12

b=0

这样神经网络对每个样本都给出了正确的结果

这里给出的XOR问题的解处在损失函数的全局最小点,所以梯度下降算法可以收敛到这一点。梯度下降算法还可以找到XOR问题的一些其他的等价解。梯度下降算法的收敛点取决于参数的初始值

基于梯度的学习

我们到目前为止看到的线性模型和神经网络的最大区别,在于神经网络的非线性导致大多数我们感兴趣的代价函数都变得非凸。这意味着神经网络的训练通常使用迭代的,基于梯度的优化,仅仅使得代价函数达到一个非常小的值,而不是项用于训练线性回归模型的线性方程求解器,或者用于训练逻辑回归或SVM的凸优化算法那样保证全局收敛。用于非凸损失函数的随机梯度下降没有收敛性保证,并且对参数的初始值很敏感。对于前馈神经网络,将所有的权重值初始化为小随机数是很重要的。偏置可以初始化为零或者小的正值。计算梯度对于神经网络会比较复杂,但仍然可以很高效而精确地实现,使用反向传播算法。

为了使用基于梯度地学习方法,我们必须选择一个代价函数,并且必须选择如何表示模型的输出

代价函数

在大多数情况下,参数模型定义了一个分布p(y|x;θ)并且简单地使用最大似然原理。这意味着我们使用训练数据和模型预测间的交叉熵作为代价函数

有时,我们使用一个更简单的方法,不是预测y的完整概率分布,而是仅仅预测在给定x\mathbf{x}条件下y\mathbf{y}的某种统计量。某些专门的损失函数允许我们来训练这些估计量的预测器

用于训练神经网络的完整的代价函数,通常在我们这里描述的基本代价函数的基础上增加一个正则项。用于线性模型的权重衰减方法也直接适用于深度神经网络

使用最大似然学习条件分布

大多数现代的神经网络使用最大似然来训练,这意味着代价函数就是负的对数似然,它于训练数据和模型分布间的交叉熵等价,这个代价函数表示为

J(θ)=EX,Y~p^datalogpmodel(y|x)

代价函数的具体形式随着模型而改变,取决于logpmodel的具体形式。上述方程的展开形式通常会有一些项不依赖于模型的参数,我们就可以舍去

使用最大似然来导出代价函数的方法的一个优势是,它减轻了为每个模型设计代价函数的负担。明确一个模型p(y|x)则自动地确定了一个代价函数logp(y|x)

贯穿神经网络设计的一个反复出现的主题是代价函数的梯度必须足够大和具有足够的预测性,来为学习算法提供一个好的指引。饱和(非常平)的函数破坏了这一目标,因为它们把梯度变得非常小。这在很多情况下都会发生,因为用于产生隐藏单元或者输出单元的输出的激活函数会饱和。负的对数似然帮助我们 在很多模型中避免这个问题。很多输出单元都会包括一个指数函数,这在它的变量取绝对值非常大的负值时会造成饱和。负对数似然代价函数中的对数函数消除了某些输出单元中的指数效果

用于实现最大似然估计的交叉熵函数通常没有最小值。对于离散型输出变量,大多数模型以一种特殊的形式来参数化,即他们不可能表示概率零和一,但是可以无限接近。对于实值的输出变量,如果模型可以控制输出分布的密度,那么它可能对正确的训练集输出赋予极其高的密度,这将导致交叉熵去趋向负无穷,正则化技术可以修正学习问题,使得模型不会通过这种方式来获得无限制的收益

学习条件统计量

有时我们并不想学习一个完整的概率分布p(y|x;θ),而仅仅是想学习在给定x\mathbf{x}y\mathbf{y}的某个条件统计量

例如,我们可能有一个预测器f(x;θ),想用它来预测y\mathbf{y}的均值。如果使用一个足够强大的神经网络,我们可以认为这个神经网络能够表示一大类函数中的任何一个函数f,这个类仅仅被一些特征所限制,例如连续性和有界,而不是具有特殊的参数形式。从这个角度来看,我们可以把代价函数看作一个泛函(functional),即函数到实数的映射。我们可以将学习看作选择函数,而不是仅仅选择一组参数。可以设计代价泛函,使它的最小值处于一个特殊的函数上,这个函数将x\mathbf{x}映射到给定x\mathbf{x}y\mathbf{y}的期望值。对函数求解优化问题需要用到变分法(calculus of variations)

使用变分法导出的第一个结果时解优化问题

f*=argminfEX,Ypdatayf(x)2

得到

f*(x)=EYpdata(y|x)[y]

要求这个函数在我们要优化的类里。换句话说,如果我们能够用无穷多的,来源真实的数据生成分布,最小化均方误差代价函数将得到一个函数,他可以用来对每个x\mathbf{x}值预测出y\mathbf{y}的均值

不同的代价函数给出不同的统计量,第二个使用变分法得到的结果是

f*=argminfEX,Y~pdatayf(x)1

将得到一个函数可以对每个x\mathbf{x}预测y\mathbf{y}取值的中位数,只要这个函数在我们要优化的函数族里。这个代价函数通常被称为平均绝对误差(mean absolute error)

均方误差和平均绝对误差在使用基于梯度的优化方法时往往成效不佳。一些饱和的输出单元当当结合这些代价函数时会产生非常小的梯度,因此交叉熵代价函数更受欢迎

输出单元

代价函数的选择与输出单元的选择紧密相关。大多数时候,我们简单地使用数据分布和模型分布之间的交叉熵,选择如何表示输出决定了交叉熵函数的形式

我们假设前馈网路哦提供了一组定义为h=f(x;θ)的隐藏特征。输出层的作用是随后对这些特征进行一些额外的变换来完成整个网路的任务

用于高斯输出分布的线性单元

一种简单的输出单元是基于仿射变换的输出单元,仿射变换不具有非线性,这些但愿往往被称为线性单元

给定特征h\mathbf{h},线性输出单元层产生一个向量y^=Wh+b

线性输出层经常被用来产生条件高斯分布的均值

p(y|x)=N(y;y^,I)

最大化其对数似然等价于最小化均方误差

最大似然框架也使得学习高斯分布的协方差矩阵更加容易,或更容易地使高斯分布地协方差矩阵作为输入的函数。然而对于所有输入,协方差矩阵必须被限定为一个正定矩阵,线性输出层很难满足这种限定,所以通常要使用其他的输出单元来对协方差参数化

用于Bernoulli输出分布的sigmoid单元

许多任务需要预测二值型变量y的值。二分类问题可以归结为这种形式

此时最大似然的方法使定义yyx\mathbf{x}条件下的Bernoulli分布

Bernoulli分布仅需单个参数来定义,神经网络只需要预测P(y=1|x)即可,为了使这个数是有效的概率,他必须处在区间[0,1]之中

这时应使用sigmoid输出结合最大似然来实现,sigmoid输出单元定义为

y^=σ(wh+b)

这里σ是logistic sigmoid函数

我们可以认为sigmoid输出单元具有两个部分,首先使用一个线性层来计算z=wh+b,然后用sigmoid激活函数将z转化成概率

这种在对数空间里预测概率的方法可以很自然地使用最大似然学习。因为代价函数中的log抵消了sigmoid中的exp,消除了sigmoid的饱和性,使梯度下降算法能够更好地发挥作用

当我们使用其他的损失函数,如均方误差,损失函数就会在σ(z)饱和时饱和。这时,梯度会变得非常小以至于不能用来学习,因此最大似然几乎是训练sigmoid输出单元的优选方法

用于Multinoulli输出分布的softmax单元

任何时候,当我们想要表示一个具有n个可能取值的离散型随机变量的分布时,都可以使用softmax函数。它可以看作sigmoid函数的扩展

softmax函数最常用作分类器的输出,来表示n个不同类上的概率分布

为了将sigmoid函数推广到具有n个值的离散型变量的情况,现在需要创造一个向量y^,它的每个元素使y^i=P(y=i|x)。我们不仅要求每个元素介于0和1之间,还要使得整个向量的和为1,使得它表示一个有效的概率分布。线性层预测了未归一化的对数概率

z=Wh+b

其中zi=logP^(y=i|x)。softmax函数然后可以对z指数化和归一化来获得需要的y^\hat{\mathbf{y}}。最终softmax函数的形式为

softmax(z)i=exp(zi)jexp(zj)

同样,当使用最大化对数似然训练softmax来输出目标值y时,使用指数函数工作地非常好,因为对数似然中的log可以抵消softmax中的exp

logsoftmax(z)i=zilogjexp(zj)

当最大化对数似然时,第一项鼓励zi被推高,第二项鼓励所有的z被压低,其近似等于maxjzj。负对数似然代价函数总是强烈地乘法最活跃地不正确预测。如果正确答案已经具有了softmax的最大输入,那么zj项和logjexp(zj)maxjzj=zj将大致抵消。这个样本对于整体训练代价贡献很小,这个代价将由其他未被正确分类的样本产生

对数似然之外的许多目标函数对softmax函数不起作用。那些不使用对数来抵消softmax中的指数的目标函数,在指数函数的变量取非常小的负值时会造成梯度小时,从而无法学习。对于softmax函数,当输入值之间的差距变得极端时,这些输出值可能饱和,当softmax函数饱和时,基于softmax的许多代价函数也饱和,除非它们能够转化饱和的激活函数

softmax函数的变量z\mathbf{z}可以通过两种方式产生。最常见的是简单地使神经网络较早地层输出z\mathbf{z}的每个元素,就像先前描述的使用线性层z=Wh+b\mathbf{z}=\mathbf{W}^\top\mathbf{h}+\mathbf{b}。虽然很直观,但这种方法是对分布的过度参数化。n个输出总和必须为1的约束意味着只有n-1个参数是必要的,第n个概率值可以通过1减去前面n-1个概率来获得。因此,我们可以强制要求z\mathbf{z}的一个元素是固定的。定义P(y=1|x)=σ(z)等价于用二维的z\mathbf{z}以及z1=0来定义P(y=1|x)=softmax(z)1

从神经科学的角度来看,softmax在参与其中的单元之间形成竞争的方式:softmax输出总是和为1,所以一个单元的值增加必然对应着其他单元值的减小。这与被认为存在于皮质中相邻神经元间的侧抑制类似。在极端情况下,它变成了赢者通吃的形式(其中一个输出接近1,其他的接近0)

softmax更接近于argmax函数。argmax函数的结果表示为一个one-hot向量,不是连续和可微的。softmax函数提供了argmax的软化版本。max函数相对应的软化版本是softmax(z)z

其他的输出类型

一般而言,如果我们定义了一个条件分布p(y|x;θ),最大似然原则建议我们使用logp(y|x;θ)作为代价函数

一般来说,我们可以认为神经网络表示函数f(x;θ)。这个函数的输出不是对y\mathbf{y}值的直接预测。相反,f(x;θ)=ω提供了y分布的参数。我们的损失函数就可以表示成logp(y;ω(x))

例如,我们想要学习在给定X时,Y的条件高斯分布的方差。我们希望模型对不同的X\mathbf{X}值预测出Y\mathbf{Y}不同的方差。这被称为异方差(heteroscedastic)模型。在异方差情况下,我们简单地把方差指定为f(X;θ)其中一个输出值。实现它的典型方法时使用精度而不是方差来表示高斯分布,在多维变量的情况下,最常见的是使用一个对角精度矩阵

diag(Β)

这个公式适用于梯度下降。无论使用的是标准差、方差还是i精度,我们必须确保高斯分布的协方差矩阵式正定的,由于精度矩阵的特征值时协方差矩阵特征值的倒数,所以这等价于确保精度矩阵是正定的。如果我们使用对角矩阵,或者是一个常数乘以单位矩阵,那么需要对模型输出强加的唯一条件是它的元素都为正。如果假设a是用于确定对角矩阵的模型的原始激活,那么可以用softplus函数来获得正的精度向量:β=ς(a)

我们经常想要执行多峰回归,即预测条件分布p(y|x)的实值,该条件分布对于相同的x\mathbf{x}值在y\mathbf{y}

空间中有多个不同的峰值。在这种情况下,高斯混合是输出的自然表示。将高斯混合作为其输出的神经网络通常被称为混合密度网络(mixture density network)。具有n个分量的高斯混合输出由下面的条件分布定义:

p(y|x)=i=1np(c=i|x)N(y;μ(i),Σ(i)(x))

神经网路必须由三个输出:定义p(c=i|x)的张量,对所有的i给出μ(i)(x)的矩阵,以及对所有的ii给出Σ(i)(x)的张量,它们必须满足不同的约束。

混合组件由潜变量c关联着,在n个不同组件熵形成Multinoulli分布。这个分布通常可以由n维向量的softmax来获得

均值指明了与第i个高斯组建项关联的中心,并且是无约束的。如果y\mathbf{y}是个d维向量,那么网络必须输出由n个这种d维向量组成的矩阵。用最大似然来学习这些均值,我们只想更新那个真正产生观测数据的组件的均值,但是在实践中,我们并不知道是哪个组件产生了观测数据。负对数似然的表达式将每个样本对每个组件的贡献进行赋权,权重的大小由相应的组件产生这个样本的概率来决定

协方差指明了每个组件i的协方差矩阵。我们通常使用对角矩阵来避免计算行列式。最大似然很复杂,它需要将每个点的部分责任分配给每个混合组件。如果给定了混合模型的正确的负对数似然,梯度下降将自动地遵顼正确的过程

基于梯度的优化方法对于混合条件高斯可能是不可靠的,部分是一位内涉及除法可能是不稳定的。一种解决方法是梯度阶段,另一种解决方法是启发式缩放梯度

隐藏单元

整流线性单元式隐藏单元记号的默认选择。通常不可能预先预测出那种隐藏单元工作得最好。先直觉认为某种隐藏单元可能表现良好,然后用它组成神经网络进行训练,最后用验证集评估它的性能

大多数的隐藏单元都可以描述为接受输入向量x\mathbf{x},计算仿射变换z=Wx+b,然后使用一个逐元素的非线性函数g(z)。隐藏单元的区别仅仅在于激活函数的形式

整流线性单元及其扩展

整流线性单元使用激活函数g(z)=max{0,z}

只要整流线性单元处于激活状态,它的导数都能保持较大。它的梯度不仅大而且一致

当初始化仿射变换的参数时,可以将b的所有元素设置成一个小的正值,这使得整流线性单元很可能初始时就对训练集中的大多数输入呈现激活状态,并且允许导数通过

整流线性单元的一个缺陷是它们不能通过基于梯度的方法学习那些使它们激活为零的样本。整流线性单元的各种扩展保证了它们能在各个位置都接收到梯度

整流线性单元的3个扩展基于当zi<0时使用要给非零的斜率αi:hi=g(z,α)i=max(0,zi)+αimin(0,zi)绝对值整流(absolute value rectification)固定αi=1来得到g(z)=|z|。它用于图像中的对象识别,其中寻找在输入照明极性反转下不变的特征是有意义的。渗漏整流线性单元(Leaky ReLU)将αi固定成一个类似0.01的小值,参数化整流线性单元(parametric ReLU)或者PReLU将αi\alpha_i作为学习的参数

maxout单元进一步扩展了整流线性单元。maxout单元将z\mathbf{z}划分为每组具有k个值的组,而不是使用作用于每个元素g(z)。每个maxout单元则输出每组中的最大元素,这提供了一种方法来学习对输入x\mathbf{x}

空间中多个方向响应的分段线性函数

maxout单元可以学习具有多达k段的分段线性的凸函数。maxout单元因此可以视为学习激活函数本身,而不仅仅是单元之间的关系。使用足够大的k,maxout单元可以以任意的精确度近似任何凸函数。具有两块的maxout层可以学习实现和传统曾相同的输入x\mathbf{x}的函数,这些传统层可以使用各种整流线性单元及其扩展

每个maxout单元现在由k个权重向量来参数化,所以maxout单元通常比整流线性单元需要更多的正则化

maxout单元还有一些其他的优点,在某些情况下,要求更少的参数可以获得一些统计和计算上的优点。如果由n个不同的线性过滤器描述的特征可以在不损失信息的情况下,用每一组k个特征的最大值来概括的话,那么下一层可以获得k倍更少的权重数

因为每个单元由多个多虑其驱动,maxout单元具有一些冗余来帮助它们抵抗一种被称为灾难遗忘(catastrophic forgetting)的现象,这个现象是说神经网络忘记了如何执行它们过去的任务

logistic sigmoid与双曲正切函数

在引入整流线性单元之前,大多数神经网络使用logistic sigmoid激活函数

g(z)=σ(z)

或者是双曲正切激活函数

g(z)=tanh(z)

这些激活函数紧密相关,因为tanh(z)=2σ(2z)1

sigmoid单元的广泛饱和性会使得基于梯度的学习变得非常困难,基于这个原因,现在不鼓励将它们用作前馈网络中的隐藏单元。当使用一个合适的代价函数抵消sigmoid的饱和性时,它们作为输出单元可以与基于梯度的学习相兼容

当必须要使用sigmoid激活函数时,双曲正切激活函数通常比logistic sigmoid函数表现更好。tanh在0附近与单位函数类似,训练深层神经网络y^=wtanh(Utanh(Vx))

类似于训练一个线性模型,只要网络的激活能够被保持的很小,这使得训练tanh网络更加容易

sigmoid激活函数在除了前馈网络以外的场景中更常见

其他隐藏单元

也存在许多其他种类的隐藏单元,但并不常用

其中一种是完全没有激活函数。也可以认为这是使用单元函数作为激活函数的情况。但如果神经网络的每一层都仅由线性变换组成,那么网络作为一个整体也将是线性的。然而,神经网络的一些层是纯线性的也是可以接受的。考虑具有n个输入和p个输出的神经网络层h=g(Wx+b)。我们可以用两层来代替它,一层使用权重矩阵U,一层使用权重矩阵V。如果第一层没有激活函数,那么我们对基于W的权重矩阵进行因式分解。分解方法是计算h=g(VUx+b)。如果U产生了Q个输出,那么U\mathbf{U}V\mathbf{V}一起仅包含(n+p)q个参数,而W\mathbf{W}包含np个参数。如果q很小,这可以在很大程度上节省参数。线性隐藏单元提供了一种减少网络中参数数量的有效方法

softmax单元是另外一种常用作输出的单元,但有时也可以用作隐藏单元。softmax单元很自然地表示具有k个可能值地离散型随机变量地概率分布,所以他们可以用作一种开关。

其他一些常见的隐藏单元类型

  • 径向基函数(radial basis function, RBF):hi=exp(1σi2W:,ix2)。这个函数在x\mathbf{x}接近模板W:,i时更加活跃。因为它对大部分x\mathbf{x}都饱和刀0,因此很难优化
  • softplus函数:g(a)=ξ(a)=log(1+ea)。这是整流线性单元地平滑版本,但它通常并不如线性整流单元
  • 硬双曲正切函数(hard tanh):它的形状和tanh以及整流线性单元类似,但是不同于后者,它是有界的,g(a)=max(1,min(1,a))

架构设计

架构一次是指网络的整体结构:它应该具有多少单元,以及这些单元应该如何连接

大多数神经网络被组成成称为层的单元组,并将这些层布置成链式结构,其中每一层都是前一层的函数

在这些链式架构中,主要的架构考虑时选择网络的深度和每一层的宽度。即使只有一个隐藏层的网络也足够适应训练集。更深层的网络通常能够对每一层使用更少的单元数和更少的参数,并且经常容易泛化到训练集,但是通常也更难优化。对于一个具体的任务,理想的网络架构必须通过实验,观测在验证集上的误差来得到

万能近似性质和深度

具有隐藏层的前馈网路哦提供了一种万能近似框架。万能近似定理(universal approximation theorem)表明,一个前馈神经网络如果具有线性输出层和至少一个具有任何一种挤压性质的激活函数的隐藏层,只要给予网络足够数量的隐藏单元,它可以以任意的精度来近似任何从一个有限维空间到另一个有限维空间的Borel可测函数。前馈网络的导数也可以任意好地近似函数的导数。

万能近似定理意味着无论我们试图学习什么函数,我们知道一个大的MLP一定能够表示这个函数。然而我们泵能保证训练算法能够学得这个函数。即使MLP能够表示这个函数,学习也可能因两个不同的原因而失败。首先,用于训练的优化算法可能找不到用于期望函数的参数值;其次,训练算法可能由于过拟合而选择了错误的函数

万能近似定理说明,存在于给足够大的网络能够达到我们所希望的任意精度,但是定理并没有说这个网络有多大。在最坏的情况下,可能需要指数数量的隐藏单元,这在二进制值的情况下很容易看到:向量v{0,1}n上的可能的二值型函数的数量时22n,并且选择一个这样的函数需要2n位,这通常需要O(2n)的自由度。因此,具有单层的前馈网路哦足以表示任何函数,但是网络层可能大得不可实现,并且可能无法正确的学习和泛化。在很多情况下,使用更深的模型能够减少表示期望函数所需的单元数量,并且可以减少泛化误差

具有d个输入、深度为l、每个隐藏层具有n个单元的深度整流网络可以描述的线性区域的数量是

Ondd(l1)nd

这是深度l的指数级。在每个单元具有k个过滤器的maxout网络中,线性区域的数量是

Ok(l1)+d

其他架构上的考虑

神经网络显示出相当的多样性。一般来说,层不需要连接在链中,尽管这是最常见的做法。许多架构构建了一个主链,但随后又添加了额外的架构特性,例如跳跃连接。这些跳跃连接使得梯度更容易从输出层流向更接近输入的层

架构设计考虑的另一个关键点是如何将层与层之间连接起来。默认的神经网路层采用线性变换。许多其他的网络具有较少的连接,使得输入层中的每个单元仅连接到输出层单元的一个小子集,这样能减少计算量,但是高度依赖具体的问题

反向传播和其他的微分算法

当我们使用前馈神经网络接受输入x\mathbf{x}并产生输出y^\hat{\mathbf{y}}时,信息通过网络向前流动,这称之为前向传播(forward propagation)。在训练过程中,前向传播可以持续向前知道它产生一个标量代价函数J(θ)。反向传播(backward propagation)算法,经常简称为backprop,允许来自代价函数的信息通过网络向后流动,以便计算梯度

计算梯度的解析表达式时很直观的,但是数值化求解这样的表达式在计算上的代价可能很大,反向传播算法使用简单和廉价的程序来实现这个目标

在学习算法中,我们最常需要的梯度时代价函数关于参数的梯度,即θJθ。许多机器学习任务需要计算其他导数,来作为学习过程的一部分,或者用来分析所得的模型。反向传播算法也是用于这些任务,不局限于计算代价函数关于参数的梯度。通过在网络中的传播信息来计算导数的想法非常普遍,它还可以用于计算注入多输入函数f的Jacobian的值

计算图

为了更精确的描述反向传播算法,使用更精确的计算图语言是很有帮助的

我们使用图中的每一个节点来表示一个变量。变量可以是标量、向量、矩阵、张量或者甚至是另一类型的变量

为了形式化图形,我们还需引入操作这一概念。操作时指一个或多个变量的简单函数。图形语言伴随着一组被允许的操作。我们可以通过将多个操作符合在一起来描述更为复杂的函数

为了不失一般性,我们定义一个操作仅返回单个输出变量

如果变量y是变量x通过一个操作计算得到的,那么我们画一条从x到y的有向边。有时我们用操作的名称来注释输出的节点

微积分中的链式法则

微积分中的链式法则用于计算复合函数的导数。反向传播是一种计算链式法则的算法,使用高效的特定运算顺序

设x是实数,f和g是从实数映射到实数的函数。假设z=f(g(x))=f(y),那么链式法则是说

dzdx=dzdydydx

将标量扩展到矢量,假设x\inRmy\inRn,g是从RmRn的映射,f是从RnR^nR的映射。如果y=g(x)并且z=f(y),那么

zxi=jzyjyjxi

用向量表示

xz=yxTyz

其中yx是g的Jacobian矩阵

从这里我们看到,变量x\mathbf{x}的梯度可以通过Jacobian矩阵和梯度yz相乘来得到

通常我们将反向传播算法应用于任意维度的张量,而不仅仅用于向量。唯一的区别是如何将数字排列成网格以形成张量。我们可以想象,在运行反向传播之前,将每个张量压扁为一个向量,计算一个向量值梯度,然后将该梯度重新构造成一个张量。因此反向传播仍然只是将Jacobian乘以梯度

递归地使用链式法则来实现反向传播

使用链式规则,我们可以直接写出某个标量关于计算图中任何产生该标量地节点的梯度的代数表达式

许多子表达式可能在计算梯度的表达式中重复若干次。在某些情况下,计算两次相同的子表达式纯粹是浪费,在复杂图中可能存在指数多的这种浪费。在其他情况下,计算两次相同的子表达式可能是以较高的运行时间为代价减少内存开销的有效手段

全连接MLP中的反向传播计算

对于一个MLP,前向传播将参数映射到与单个训练样本(x,y)相关联的监督损失函数L(y^,y)。定义损失函数J=L(y^,y)+λΩ(θ)

网络深度,l

W(i),i{1,...,l},模型的权重矩阵

b(i),i{1,...,l},模型的偏置矩阵

反向传播计算对于每一层k都产生了对激活a(k),从输出层开始向后计算一直到第一个隐藏层。这些梯度可以看作对每层的输出应如何调整以减小误差的知道,根据这些梯度可以获得对每层参数的梯度

计算过程如下:

在前向计算完成后,计算顶层的梯度:

gy^J=y^L(y^,y)

for k=l,l1,...,1 do

将关于层输出的梯度转换为非线性激活输入前的梯度

ga(k)J=gf(a(k))

计算关于权重和偏置的梯度(如果需要的话,还要包括正则项)

b(k)J=g+λb(k)Ω(θ)

W(k)J=gh(k1)+λW(k)Ω(θ)

关于下一更低层的隐藏层传播梯度

gh(k1)J=W(k)Tg

end for

符号到符号的导数

代数表达式和计算图都对符号或不具有特定值的变量进行操作。这些代数或者基于图的表达式被称为符号表示(symbolic representation)。当实际使用或者训练神经网络时,我们必须给这些符号赋特定的值

一些反向传播的方法采用计算图和一组用于图的输入的数值,然后返回在这些输入值梯度的一组数值。我们将这种方法称为符号到数值的微分

另一种方法是采用计算图以及添加一些额外的节点到计算图中,这些额外的节点提供了我们所需导数的符号描述。这种方法的主要优点是导数可以使用与原始表达式相同的语言来描述。因为导数只是另外一张计算图,我们可以再次运行反向传播,对导数再进行求导就能得到更高阶的函数

一般化的反向传播

反向传播算法非常简单。为了计算某个标量z关于图中它的一个祖先x\mathbf{x}的梯度,首先观察到它关于z的梯度由dzdz=1给出。然后,我们可以计算对图中z的每个父节点的梯度,通过现有的梯度乘以产生z操作的Jacobian。继续乘以Jacobian,以这种方式向后穿过计算图,直到到达x\mathbf{x}。对于从z出发可以经过两个或跟多路径向后行进而到达的任意节点,我们简单地对该节点来自不同路径上的梯度进行求和

一般而言,图中每个节点对应着一个变量,每个操作op业余bprop操作相关联。每个操作负则了解如何通过它参与的图中的边来反向传播。例如,我们可以使用矩阵乘法操作来产生变量C=AB。假设标量z关于C的梯度是G。矩阵乘法操作负则定义两个反向传播规则,每个规则对应于一个输入变量。矩阵乘法操作的bprop方法必须说明关于A的梯度是GB。反向传播算法不需要知道微分法则,只需要使用正确的参数调用每个操作的bprop方法即可。即op.bprop(inputs,X,G)必须返回

i(Xop.f(inputs)i)Gi

这里,inputs是提供个操作的一组输入,op.f是操作实现的数学函数,$$$\mathbf{X}$是输入,我们想要计算关于它的梯度,$$\mathbf{G}mulxx^2$$,op.bprop方法应该仍然返回x作为两个输入的导数。反向传播算法后面会将这些变量加起来获得2x,得到正确的导数

反向传播算法的软件通常提供操作和其bprop方法,所以深度学习软件库的用户能够对使用诸如矩阵乘法、指数运算、对数运算等常用操作构建的图进行反向传播

在具有n个节点的图中计算梯度,将永远不会执行超过O(n2)个操作,或者存储超过$$$O(n^2)$个操作的输出。大多数神经网路哦的代价函数大致是链式结构的,使得反向传播只有$$O(n)$$的成本。我们可以把反向传播看成一种避免重复计算的表填充算法,利用存储的中间结果来对表进行填充。图中每个节点对应着表中的一个位置,这个位置存储对该节点的梯度。通过顺序填充这些表的条目,反向传播算法避免了重复计算许多公共子表达式。这种表填充策略有时被称为动态规划(dynamic programming)

实例:用于MLP训练的反向传播

考虑一个具有单个隐藏层的非常简单的多层感知机。为了训练这个模型,我们将使用小批量随机梯度下降法。反向传播算法用于计算单个小批量上的代价的梯度。具体来说,我们使用训练集上的一小批量实例,将其规范化为一个实际矩阵X\mathbf{X}以及相关联的类标签向量y\mathbf{y}。网络计算隐藏特征层H=max{0,XW(1)}。为了简化表示,我们在模型中不使用偏置。假设我们的图语言包含relu操作,该操作可以对max{0,Z}表达式的每个元素分别进行计算。类的非归一化对数概率的预测将随后由HW(2)给出。假设我们的图语言包含cross_entropy操作,用以计算目标y\mathbf{y}和由这些未归一化对数概率定义的概率分布间的交叉熵。所得到的交叉熵定义了代价函数JMLE。最小化这个交叉熵将执行对分类器的最大似然估计。为了使这个例子更加真实,我们也包含一个正则项。总的代价函数为

J=JMLE+λi,jWi,j(1)2+i,jWi,j(2)2

它的计算图如下图给出

我们可以通过观察图中的正向传播来描述反向传播算法的行为。为了训练,我们希望计算W(1)JW(2)J。有两种不同的路径从J后退到权重:一条通过交叉熵代价,另一条通过权重衰减代价。权重衰减代价相对简单,它总是对W(i)上的梯度贡献2λW(i)

另一条通过交叉熵代价的路径稍微复杂一些。令G\mathbf{G}是由cross_entropy操作提供的对未归一化对数概率U(2)的梯度。反向传播算法现在需要探索两个不同的分支。在较短的分支上,它使用对矩阵乘法的第二个变量的反向传播规则,将HG加到W(2)的梯度上。另一条更长些的路径沿着网络逐步下降。首先,反向传播算法使用对矩阵乘法的第一个变量的反向传播规则,计算HJ=GW(2)。接下来,relu操作使用其反向传播规则来对关于U(1)的梯度中小于0的部分清零。记上述结果为G。反向传播算法的最后一步是使用matmul操作的第二个变量的反向传播规则,将XG加到W(1)的梯度上

在计算了这些梯度以后,梯度下降算法或者其他优化方法索要俎豆二就是使用这些梯度更新参数

对于MLP,计算成本主要来源于矩阵乘法。在前向传播阶段,我们乘以每个权重矩阵得到了O(w)数量的操作,其中w是权重的数量。在反向传播阶段,我们乘以每个矩阵的转置,这具有相同的计算成本。算法主要的存储成本是我们需要将输入存储到隐藏层的非线性中去。因此存储成本是O(mnh),其中m是小批量中样本的数目,nh是隐藏单元的数量

复杂化

实践中实际使用的反向传播算法更加复杂

大多数软件实现需要支持可以返回多个向量的操作。例如,如果我们希望计算张量中的最大值和该值的索引,则最好在单词运算中计算两者,因此将该过程实现为具有两个输出的操作效率更高

反向传播涉及到将许多张量加在一起,需要控制内存消耗。可以通过保持要给缓存器,在计算时将每个值加到该缓冲器来避免存储瓶颈

反向传播还需要处理各种数据类型,处理不同类型的策略需要特别的设计考虑

一些操作具有未定义的梯度,并且重要的是跟踪这些情况并且确定用于请求的梯度是否是未定义的

深度学习之外的微分

自动微分(automatic differentiation)领域关心如何以算法方式计算倒数。这里描述的反向传播算法只是自动微分的一种方法。它是一种被称为反向模式叠加的更广泛类型的技术的特殊情况。其他方法以不同的顺序来计算链式法则的子表达式

当图的输出数目大于输入的数目时,有时更偏向于使用另外一种形式的自动微分,称为前向模式累加

高阶微分

在深度学习相关领域,我们通常对Hessian矩阵的性质比较感兴趣。如果我们有函数f:RnR,那么Hessian的大小是n×n,在应用中,n将是模型的参数数量,可能很容易达到数十亿

典型的深度学习方法是使用Krylov方法,而不是显式地计算Hessian矩阵。Krylov方法是用于执行各种操作地一组迭代技术,这些操作包括像近似求解矩阵地逆或者近似矩阵地特征值、特征向量等,而不是用矩阵-向量乘法以外的任何操作

为了在Hessian矩阵上使用Krylov方法,我们只需要能够计算Hessian矩阵H和一个任意向量v间的乘积即可。实现这一目标的一种直观方法是

Hv=x[(Wf(x))v]

该表达式中的两个梯度的计算都可以由适当的软件库自动完成

如果v\mathbf{v}本身是由计算图产生的一个向量,那么重要的是指定自动微分软件不要对产生v\mathbf{v}的图进行微分

发表评论