【转】再谈 最速下降法/梯度法/Steepest Descent

转载请注明出处:http://www.codelast.com/

最速下降法(又称梯度法,或Steepest Descent),是无约束最优化领域中最简单的算法,单独就这种算法来看,属于早就“过时”了的一种算法。但是,它的理念是其他某些算法的组成部分,或者说是在其他某些算法中,也有最速下降法的“影子”。因此,我们还是有必要学习一下的。
我很久以前已经写过一篇关于最速下降法的文章了,但是这里我还打算再写一篇,提供更多一些信息,让大家可以从更简单生动的方面去理解它。

『1』名字释义
最速下降法只使用目标函数的一阶导数信息——从“梯度法”这个名字也可见一斑。并且,它的本意是取目标函数值“最快下降”的方向作为搜索方向。于是我们就想知道这个问题的答案:沿什么方向,目标函数  的值下降最快呢?

『2』函数值下降最快的方向
先说结论:沿负梯度方向 ,函数值下降最快。
下面就来推导一下。
将目标函数在点处泰勒展开(这是我们惯用的“伎俩”了)——

高阶无穷小可忽略,由于我们定义了步长,因此,当时,,即函数值是下降的。此时就是一个下降方向。
但是具体等于什么的时候,可使目标函数值下降最快呢?
文章来源:http://www.codelast.com/
Cauchy-Schwartz不等式(柯西-许瓦兹不等式)可得:

当且仅当时,等号成立,最大(>0)。
所以时,最小(<0),下降量最大。
所以是最快速下降方向。

『3』缺点
它真的“最快速”吗?答案是否定的。
事实是,它只在局部范围内具有“最速”性质。
对整体求解过程而言,它的下降非常缓慢。

『4』感受一下它是如何“慢”的
先来看一幅图(直接从维基百科上弄过来的,感谢Wiki):

文章来源:http://www.codelast.com/
这幅图表示的是对一个目标函数的寻优过程,图中锯齿状的路线就是寻优路线在二维平面上的投影。
这个函数的表达式是:

它叫做Rosenbrock function(罗森布罗克方程),是个非凸函数,在最优化领域,它通常被用来作为一个最优化算法的performance test函数。
我们来看一看它在三维空间中的图形:

文章来源:http://www.codelast.com/
它的全局最优点位于一个长长的、狭窄的、抛物线形状的、扁平的“山谷”中。

找到“山谷”并不难,难的是收敛到全局最优解(全局最优解在 (1,1) 处)。

正所谓:世界上最遥远的距离,不是你离我千山万水,而是你就在我眼前,我却要跨越千万步,才能找到你。

文章来源:http://www.codelast.com/
我们再来看另一个目标函数的寻优过程:

和前面的Rosenbrock function一样,它的寻优过程也是“锯齿状”的。
它在三维空间中的图形是这样的:

总而言之就是:当目标函数的等值线接近于圆(球)时,下降较快;等值线类似于扁长的椭球时,一开始快,后来很慢。

文章来源:http://www.codelast.com/
『5』为什么“慢”的分析
上面花花绿绿的图确实很好看,我们看到了那些寻优过程有多么“惨烈”——太艰辛了不是么?
但不能光看热闹,还要分析一下——为什么会这样呢?
精确line search满足的一阶必要条件,得:
,即
故由最速下降法的得:

即:相邻两次的搜索方向是相互直交的(投影到二维平面上,就是锯齿形状了)。
文章来源:http://www.codelast.com/
如果你非要问,为什么就表明这两个向量是相互直交的?那么我就耐心地再解释一下:
由两向量夹角的公式:

=> 
两向量夹角为90度,因此它们直交。

『6』优点
这个被我们说得一无是处的最速下降法真的就那么糟糕吗?其实它还是有优点的:程序简单,计算量小;并且对初始点没有特别的要求;此外,许多算法的初始/再开始方向都是最速下降方向(即负梯度方向)。
文章来源:http://www.codelast.com/
『7』收敛性及收敛速度
最速下降法具有整体收敛性——对初始点没有特殊要求。
采用精确线搜索的最速下降法的收敛速度:线性。

时间: 2024-10-05 14:00:19

【转】再谈 最速下降法/梯度法/Steepest Descent的相关文章

梯度下降法Gradient descent(最速下降法Steepest Descent)

最陡下降法(steepest descent method)又称梯度下降法(英语:Gradient descent)是一个一阶最优化算法. 函数值下降最快的方向是什么?沿负梯度方向  d=−gk 原文地址:https://www.cnblogs.com/focusonoutput/p/12151198.html

C++ Primer 学习笔记_73_面向对象编程 --再谈文本查询示例

面向对象编程 --再谈文本查询示例 引言: 扩展第10.6节的文本查询应用程序,使我们的系统可以支持更复杂的查询. 为了说明问题,将用下面的简单小说来运行查询: Alice Emma has long flowing red hair. Her Daddy says when the wind blows through her hair, it looks almost alive, like a fiery bird in flight. A beautiful fiery bird, he

C++ Primer 学习笔记_74_面向对象编程 --再谈文本查询示例[续/习题]

面向对象编程 --再谈文本查询示例[续/习题] //P522 习题15.41 //1 in TextQuery.h #ifndef TEXTQUERY_H_INCLUDED #define TEXTQUERY_H_INCLUDED #include <iostream> #include <fstream> #include <sstream> #include <vector> #include <set> #include <map&g

再谈MySQL全库备份

再谈MySQL全库备份 简介 Part1:写在最前 在很早之前,我写过一个MySQL生产库全库备份脚本,今天有同事问我是不是要再加一个-R参数来备份存储过程,理由的话是由于mysqldump --help中 关于存储过程的默认备份是false. routines                          FALSE MySQL生产库全库备份脚本 http://suifu.blog.51cto.com/9167728/1758022 实战 Part1:写在最前 我备份一般就三个参数 --s

Android 再谈handler

今天在做http网络事件的响应网络接收处理一般不能放在主线程中使用,目前也只会使用AsyncTask进行处理!之前虽然写过handler处理的一些文章但是发现全不会了!无奈~ 关于handler某位兄弟已经整理的很透彻了!现在引用下原话如下: Handler监听者框架:子线程是事件源,主线程是监听者.Handler作为子线程的监听器出现:主线程中生成Handler的子类,并重写handleMessage(Message msg) 方法,用来对子线程响应.子线程调用Hanlder的sendMess

再谈ORACLE CPROCD进程

罗列一下有关oprocd的知识点 oprocd是oracle在rac中引入用来fencing io的 在unix系统下,如果我们没有采用oracle之外的第三方集群软件,才会存在oprocd进程 在linux系统下,只有在10.2.0.4版本后,才会具有oprocd进程 在window下,不会存在oprocd 进程,但是会存在一个oraFenceService服务,用来实现相同的功能,该服务采用的技术是基于windows的,与oprocd不同 oprocd进程可以运行在两者模式下:fatal和n

Java基础——再谈面向对象

去年的这个时候,心血来潮写了篇<简述面向对象技术>,先在看来不由的会想:这都是写的什么跟什么啊?(ps:虽然现在写的博客依然不咋地)但是,Java的学习中又一次不得不再一次面向对象,所以,奉上一篇<再谈面向对象>,做为新年的一盘开胃菜. 面向对象是相对于面向过程而言,是一种思想. 区别于面向过程: 面向过程是以函数为基础,完成各种操作,强调的是过程,而面向对象是以对象为基础,强调的是对象. 比如说把大象装进冰箱分为几步,宋丹丹是这样说的:三步呗, 第一步:打开冰箱门, 第二步:把大

再谈multistage text input(中文输入法)下UITextView的内容长度限制

之前写过一篇<如何更好地限制一个UITextField的输入长度>,在文章最后得到的结论是可以直接使用 UIKIT_EXTERN NSString *const UITextFieldTextDidChangeNotification; 进行监听,截断超出maxLength的部分. 所以后来我在处理UITextView的内容长度时,也直接参考这个方法: [[NSNotificationCenter defaultCenter] addObserver:self selector:@select

再谈javascript图片预加载技术

图片预加载技术的典型应用: 如lightbox方式展现照片,无疑需要提前获得大图的尺寸,这样才能居中定位,由于javascript无法获取img文件头数据,必须等待其加载完毕后才能获取真实的大小然后展示出来,所以lightbox显示的图片的速度体验要比直接输出的差很多,而本文说提到的预加载技术主要针对获取图片尺寸. 一段典型的使用预加载获取图片大小的例子: var imgLoad = function (url, callback) {    var img = new Image();