Deep Learning阅读笔记:Chapter 4—Numerical Computation

上溢和下溢(Overflow and Underflow)

由于计算机中我们使用有限个数的位模式(bit)来表示无限个的实数,总会存在一些近似误差。因此如果理论上可行的算法并没有被设计为可以最小化舍入误差的累积,实践中就可能会出现问题。总之,在计算机中需要避免产生极小和极大值,否则它们因为舍入误差被近似为0或者∞,导致算法运算的错误。

下溢:当接近零的数被四舍五入为零时发生下溢。许多函数在其参数为零而不是一个很小的正数时才会表现出质的不同,因此通常要避免被零除(一些软件环境将在这种情况下抛出异常,有些会返回一个非数字 (not-a-number) 的占位符)或避免取零的对数(这通常被视为 −∞,进一步的算术运算会使其变成非数字)。

上溢:

当大量级的数被近似为 ∞ 或 −∞ 时发生上溢。进一步的运算通常导致这些无限值变为非数字。

以softmax函数为例,它必须对上溢和下溢进行数值稳定(避免上溢和下溢的情况)。softmax函数经常用来预测与multinoulli分布相关的概率(multimoulli分布有n个状态,softmax输出值表示能取到每个状态的概率为多少):

理论上,当所有x_{i}都取一个常数c时,它们的输出应该均为\frac{1}{n}。实际中,若c是一个很小的负数,那么分母就会趋于0,产生下溢;若c是一个很大的正数,exp(c)的上溢就会导致整个表达式未定义。解决办法是令z=x-\underset{i}{max}x_{i},转而求softmax(z)。这样分母中至少有一项为1,可以解决下溢问题;同时exp的参数最大为0,解决了上溢问题。重要的是,softmax函数不会因输入的向量减去一个标量而改变输出。

对于函数log(softmax),softmax分子上的下溢会导致softmax输出为0,如果先计算softmax输出,再传递给log,则会得到-\infty。因此要对log(softmax)也进行数值稳定,即让softmax不会因为下溢而输出0。

病态条件数(Poor Conditioning)

条件数表明函数相对于输入的微小变化而变化的快慢程度(类似导数?)。输入被轻微扰动而迅速改变的函数对于科学计算来说是可能是有问题的,因为输入中的舍入误差可能导致输出的巨大变化,这就是病态条件数。

对于函数f(x)=A^{-1}x,当A\in \mathbb{R}^{n\times n}有特征值分解时,其条件数为\underset{i,j}{max}\left | \frac{\lambda _{i}}{\lambda _{j}} \right |,也就是最大特征值和最小特征值的模之比,当该值很大时,矩阵求逆对输入的误差特别敏感。这种敏感性是矩阵本身的固有特性,而不是矩阵求逆期间舍入误差的结果。即使我们乘以完全正确的矩阵逆,病态条件数的矩阵也会放大预先存在的误差。在实践中,该错误将与求逆过程本身的数值误差进一步复合。

至于条件数与特征值的关系,其实没有很懂。不过特征值可以理解为运动的速度,其实就是变化的速度。关于特征值到底是什么,可以参考文章:https://www.matongxue.com/madocs/228.html。最大特征值就是其对应的特征向量方向上的速度,最小特征值同理,这样就是两个方向上最大变化速度与最小变化速度的比值,如果这个比值很大,说明输入有轻微扰动时,某个方向的变化速度很快,而某个方向变化速度很慢,这种变化的不一致确实和条件数的概念有符合部分。

基于梯度的优化方法(Gradient-Based Optimization)

大多数深度学习算法涉及某种形式的优化。优化指的是改变 x 以最小化或最大化某个函数 f(x) 的任务。我们通常以最小化 f(x) 指代大多数最优化问题。最大化可经由最小化算法最小化 −f(x) 来实现。我们把要最大化或最小化的函数称为目标函数(objective function)或准则(criterion)。当我们对其进行最小化时,我们也把它称为代价函数 (cost function)、损失函数 (loss function) 或误差函数 (error function)。通常用上标*表示最大化或最小化函数的x值:x^{*}=argminf(x)

导数可以理解为:当函数的输入x有了微小的变化\varepsilon时,在之前的输出上如何缩放\epsilon能获得相应的变化,公式可以表示为:

f(x+\epsilon )\approx f(x)+\epsilon f'(x)。这个式子可以理解为:若是想让f(x)有一个微小的变化,也就是相当于\epsilon {f}'(x)是已知的,求得该点x的导数{f}'(x)后就可以得到x的变化\epsilon,将\epsilon作用在x上就会令f(x)产生想要的微小变化。也就是说可以通过导数求得自变量的变化方向/趋势使得函数的输出向我们期望的方向变化。例如,我们知道对于足够小的 ϵ 来说,f(x − ϵsign(f′(x))) 是比 f(x) 小的。因此我们可以将 x 往导数的反方向移动一小步来减小 f(x)。这种技术被称为梯度下降 (gradient descent)。

{f}'(x)=0,导数无法提供往哪个方向移动的信息。{f}'(x)=0的点称为临界点 (critical point) 或驻点 (stationary point)。一个局部极小点 (local minimum) 意味着这个点的 f(x) 小于所有邻近点,因此不可能通过移动无穷小的步长来减小 f(x)。一个局部极大点 (local maximum) 是 f(x) 意味着这个点的 f(x) 大于所有邻近点,因此不可能通过移动无穷小的步长来增大 f(x)。有些临界点既不是最小点也不是最大点,称为鞍点(saddle point)。

令f(x)取得绝对的最小值的点是全局最小点,函数有一个或多个相同的全局最小点,同时可能有多个不是全局最小点的局部极小点。在深度学习的背景下,我们优化的函数可能含有许多不是最优的局部极小点,或许多被非常平坦的区域包围的鞍点。尤其是当输入是多维的时候,所有这些都将使优化变得困难。因此,我们通常寻找 f 非常小的值,但在任何形式意义下并不一定是最小。

通常,最小化f(x)的过程会将多维的输入映射为一维的标量,这样才能得到所谓的“最小化”结果。对于多维的输入,求导数变为对自变量的每一维求偏导。梯度是对一个向量求导的结果,\bigtriangledown _{x}f(x)是包含了所有偏导的向量,第i个元素是f(x)对x_{i}也就是自变量的第i维求偏导的结果。多维情况下,临界点是梯度中所有元素都为零的点。

下面这部分就是利用了一个通用方向u作为中介,求方向u上的导数,通过找导数的最小值得到此时的u,会发现u的方向就是与梯度相反的方向。

在 u(单位向量)方向的方向导数 (directional derivative) 是函数 f 在 u 方向的斜率。换句话说,方向导数是函数f(x+\alpha u)关于 α 的导数(在 α = 0 时取得,只有α = 0才能利用到\bigtriangledown _{x}f(x))。使用链式法则,我们可以看到当 α = 0 时,\frac{\partial }{\partial \alpha }f(x+\alpha u)=u^{T}\bigtriangledown _{x}f(x)。为了最小化f,要找到f下降最快的方向,求方向导数最小值:

u是单位向量,因此L2范数为1,\bigtriangledown _{x}f(x)与u无关,因此等式化为min cos\theta\theta=\pi即u与梯度方向相反时方向导数取得最小值,且大小等于\bigtriangledown _{x}f(x)。也就是梯度向量指向上坡,负梯度向量指向下坡,在负梯度方向上移动x可以减小f,这就是最速下降法(method of steepest descent)或梯度下降法(gradient descent)。输入更新规则为:x'=x-\epsilon \bigtriangledown _{x}f(x)\epsilon为学习速率,是个正标量。\epsilon的选择有多种方法,若是用多个\epsilon求出f(x-\epsilon \bigtriangledown _{x}f(x))后选择其中使目标函数有最小值的那个\epsilon,这种方法称为线搜索。

最速下降在梯度的每一个元素为零时收敛(或在实践中,很接近零时)。在某些情况下,我们也许能够避免运行该迭代算法,并通过解方程 ∇xf(x) = 0 直接跳到临界点。虽然梯度下降被限制在连续空间中的优化问题,但不断向更好的情况移动一小步(即近似最佳的小移动)的一般概念可以推广到离散空间。递增带有离散参数的目标函数被称为爬山 (hill climbing) 算法。

Jacobian and Hessian Matrics:

当函数f(x)的输入和输出都是高与一维的向量时,计算的所有偏导数所组成的矩阵称为Jacobian矩阵。若f:\mathbb{R}^{m}\rightarrow \mathbb{R}^{n},则Jacobian矩阵为J\in \mathbb{R}^{n\times m},每一行为输出的一个分量对输入的所有分量的梯度,输入有m维因此矩阵有m列;每一列为输出的所有分量对输入中某个分量的梯度,输出有n维因此矩阵有n行。矩阵表示为:J_{i,j}=\frac{\partial }{\partial x_{j}}f(x)_{i}

有时候我们也需要二阶导数告诉我们的一阶导数将如何随着输入的变化而改变。它表示只基于梯度信息的梯度下降步骤是否会产生如我们预期的那样大的改善,可以认为二阶导数是对曲率的衡量。假设有一个二次函数(虽然很多实践中的函数都不是二次,但至少在局部可以很好地用二次近似)。如果这样的函数具有零二阶导数,那就没有曲率,是一条直线,这时只需要梯度就可以预测它的值:当沿负梯度方向大小做 ϵ 的下降步,若梯度是 1 ,代价函数将也下降 ϵ。如果二阶导数是负的,函数曲线向下凹陷 (向上凸出),因此代价函数将下降的比 ϵ 多;如果二阶导数是正的,函数曲线是向上凹陷(向下凸出),因此代价函数将下降的比 ϵ 少。

当函数的输入是多维时,二阶导数可用Hessian矩阵表示:H(f)(x)_{i,j}=\frac{\partial ^{2}}{{\partial x_{i}}{\partial x_{i}}}f(x),等价于梯度的Jacobian矩阵。由于微分算子在任何二阶偏导连续的点处可交换,有

,可得H_{i,j}=H_{j,i},即Hessian矩阵在这些点处是对称的。深度学习的背景下,大多数函数的Hessian矩阵都是处处对称的。根据其实对称性,可以将其分解为一组实特征值和特征向量的正交。在特定方向 d 上的二阶导数可以写成 d^{T}Hd。当 d 是 H 的一个特征向量时,这个方向的二阶导数就是对应的特征值。对于其他的方向 d,方向二阶导数是所有特征值的加权平均,权重在 0 和 1 之间,且与 d 夹角越小的特征向量有更大的权重。最大特征值确定最大二阶导数,最小特征值确定最小二阶导数。

可以通过(方向)二阶导数预期一个梯度下降步骤能表现得多好。我们在当前点 x(0) 处作函数 f(x) 的近似二阶泰勒级数:

其中,g是梯度,H是x^{(0)}的Hessian,设学习速率为\epsilon,则更新的x为:x=x^{(0)}-\epsilon g,把该x代入上面式子可得:

该式子中包含了三项:函数的原始值、函数斜率导致的预期改善、函数曲率导致的校正。当这最后一项太大时,梯度下降实际上是可能向上移动的。当 g^{T}Hg为零或负时,近似的泰勒级数表明增加 ϵ 将永远导致 f 的下降。在实践中,泰勒级数不会在 ϵ 大的时候也保持准确,因此在这种情况下我们必须采取更启发式的选择。当g^{T}Hg为正时,通过计算可得,使近似泰勒级数下降最多的最优步长为:\epsilon *=\frac{g^{T}g}{g^{T}Hg},最坏的情况也就是学习速率最小为\epsilon * = \frac{1}{\lambda _{max}},此时g与H的最大特征值\lambda _{max}对应的特征向量对齐(一个方向),即g^{T}Hg=\lambda _{max}。我们要最小化的函数能用二次函数很好地近似的情况下,Hessian的特征值决定了学习速率的量级。

二阶导数还可以被用于确定一个临界点是否是局部极大点、局部极小点或鞍点。在临界点处 f′(x) = 0。而 f′′(x) > 0 意味着 f′(x) 会随着我们移向右边而增加,移向左边而减小,也就是 f′(x − ϵ) < 0 和 f′(x + ϵ) > 0 对足够小的 ϵ 成立。当我们移向右边,斜率开始指向右边的上坡,当我们移向左边,斜率开始指向左边的上坡。因此我们得出结论,当 f′(x) = 0 且 f′′(x) > 0 时,x 是一个局部极小点。同样,当 f′(x) = 0 且 f′′(x) < 0 时,x 是一个局部极大点。这就是所谓的二阶导数测试 (second derivative test)。不幸的是,当 f′′(x) = 0 时测试是不确定的,x可以是一个鞍点或者是平坦区域的一部分。

在多维情况下,我们需要检测函数的所有二阶导数。利用Hessian的特征值分解,我们可以将二阶导数测试扩展到多维情况。在临界点处(∇xf(x) = 0),我们通过检测Hessian的特征值来判断该临界点是一个局部极大点、局部极小点还是鞍点。如果Hessian是正定的,也就是所有特征值为正,即二阶导数为正,则这是局部极小点;如果Hessian是负定的,该临近点就是局部极大点。若Hessian的特征值中有正有负,则说明该临近点是某个截面的局部极大点,也是另一个截面的局部极小点,如下图所示:

多维时,一个点的每个方向上的二阶导数可能都不同,如果Hessian有病态条件数,即有些方向的二阶导数大小差异很大,表示不同方向变化速率差距大,梯度下降法的效果就会很差。(有点没懂)。步长的选择也会比较困难,因为步长稍大就可能会冲过最小然后向曲率较强的方向上升,但步长过小又会导致其在其他的方向上进展过慢,如下图所示:

梯度下降仅利用了梯度信息进行优化,称为一阶优化算法(first-order optimization algorithm),使用Hessian矩阵进行优化称为二阶最优化算法(second-order optimization algorithm),比如牛顿法。牛顿法是利用Hessian矩阵直接求解矩阵临界点的方法,其基于一个二阶泰勒展开来近似x^{(0)}附近的f(x)

直接计算求得函数的临界点:

如果f是正定二次函数,那么直接使用一次上式就可以得到临界点;如果只是局部正定,则需要多次迭代(因为可能停留在了鞍点,鞍点处的Hessian矩阵存在负特征值,因此非正定):迭代地更新近似函数并跳到该近似函数的最小点,仍然比梯度下降法更快。牛顿法在接近局部最小点时是很有用的,在鞍点附近是有害的。

约束优化(Constrained Optimization)

约束优化就是在一定条件下的优化:条件约束了x的范围,得到了子集S,在这些集合S中找f(x)的最大值或最小值就称为约束优化,集合S内的点x称为可行点(feasible)。比如,有时候希望找到某个意义上小的点,这时约束优化就是加上范数约束,比如\left \| x\right \|=1

解决约束优化有两类方法:

第一种是把约束考虑在内后对梯度下降略微修改:在梯度下降后,若是固定的步长,则可以得到梯度下降的单步结果,每次投影回S集合;若是在线搜索(步长是一个集合,集合中所有步长尝试后选择效果最好的一个),可以将线上每个点(不同步长对应的点)投影回S。也可以在梯度下降或在线搜索前,把梯度投影到可行点的切空间。

第二种方法是将带约束的优化问题转化为一个不带约束的优化问题,无约束得到的解可转换成原问题的解。比如:在x\in \mathbb{R}^{2}中最小化f(x),其中x约束为具有单位L2范数。则该问题可以转化为关于\theta最小化g(\theta )=f(\left [ cos \theta ,sin\theta \right ]^{T}),然后返回\left [ cos \theta ,sin\theta \right ]作为解。一种通用的方法是Karush-Kuhn-Tucker(KKT):

将S用等式(涉及m个函数g^{(i)})和不等式(涉及n个函数h^{(j)})描述:S=\left \{ x|\forall i,g^{(i)}(x)}=0 and \forall j,h^{(j)}(x)\geq 0\ right \},涉及g^{(i)}的等式称为等式约束(equality constriant),涉及h^{(j)}的不等式称为不等式约束(inequality constraint)。为所有约束引入变量\lambda _{i}\alpha _{i},称为KKT乘子。然后得到广义Lagrangian(generalized lagrangian):

优化问题转为优化无约束的广义的Lagrangian,只要存在至少一个可行点且f(x)不允许取\infty,则\underset{x}{min}\underset{\lambda }{max}\underset{\alpha ,\alpha > 0}{max}L(x,\lambda ,\alpha )\underset{x\in S}{min}f(x)有相同的最优目标函数值和最优点集x。因为当约束满足时,\underset{\lambda }{max}\underset{\alpha ,\alpha > 0}{max}L(x,\lambda ,\alpha )=f(x),而不满足约束时,\underset{\lambda }{max}\underset{\alpha ,\alpha > 0}{max}L(x,\lambda ,\alpha )=\infty,这可以保证不可行点不会是最佳的(代入得到\infty),而可行点范围内的最优点不变(不受影响)。以上是最小化f(x)的过程,若是最大化f(x),可以利用带-f(x)的广义Lagrangian函数:

或者直接把最外层转化为最大化:

等式约束项前的符号不重要,因为\lambda _{i}的符号是可以随意选择的;对于不等式约束项:如果{h^_{(i)}}(x*)=0(x*是最优点),称该约束是活跃的;如果不活跃,{h^_{(i)}}是负的,那么在x*处定有\alpha _{i}=0(因为广义Lagrangian中要先最大化,{h^_{(i)}}是负的,而\alpha又有限制必须非负,只能令{h^_{(i)}}对应的\alpha _{i}为0,才能得到最大化)。因此在解中,有\alpha \odot h(x)=0的限制,即对于所有的i,\alpha _{i}\geq 0h^{(j)}(x)\leq 0在收敛时必有一个是活跃的。这个限制相当于对解强加了一个边界,通过KKT乘子影响了解,因此带有该约束和不带有该约束的问题间会存在一个局部的相同解(该约束过滤了部分解)。

用一组简单的性质也就是KKT条件描述最优点,这也是确定一个点为最优点的必要条件(不一定是充分条件):

广义Lagrangian的梯度为0;

所有关于x和KKT乘子的约束都满足;

不等式约束显示的互补“松弛性”:\alpha \odot h(x)=0

线性最小二乘(Linear Least Square)

要找到最小化以下式子的x值:

如果利用梯度下降来解决:

计算梯度:

然后按算法进行梯度下降:

如果利用牛顿法解决:因为函数是二次的,可以一步收敛到全局最小点,引入Lagrangian函数:

转为求该问题:\underset{x}{min}\underset{\lambda ,\lambda \geq 0}{max}L(x,\lambda ),利用Moore-Penrose伪逆找到无约束最小二乘问题的最小范数解(Moore-Penrose伪逆得到的是最小范数解),如果该点可行,就是最优问题的解。关于x对Lagrangian微分:

解的形式为:

因为有约束\lambda \geq 0,所以先关于\lambda进行梯度上升:

当x的范数大于1(x^{T}x>1)时,该导数是正的,为了增加Lagrangian,要增大\lambda。又因为Lagrangian中有约束项\lambda (x^{T}x-1)\lambda

增大时,x的范数会变小,在增大\lambda和减小x范数中调节,.直到x范数符合要求同时\lambda的梯度为0(Lagrangian函数不会随\lambda再增加了),那么在\lambda上就达到了最大化L(x,\lambda ),同时也找了使其最小化的x。

猜你喜欢

转载自blog.csdn.net/lynlindasy/article/details/86548604