我们在上一篇博客《数值优化:经典一阶确定性算法及其收敛性分析》中主要介绍了单机数值优化中一些经典的一阶确定性算法,本篇文章我们将会介绍二阶确定性算法和对偶方法。
牛顿法[1]的基本思想是将目标函数在当前迭代点处进行二阶泰勒展开,然后最小化这个近似目标函数,即
此处\(\nabla^2f(w^t)\)是目标函数在当前迭代点\(w^t\)处的海森矩阵。如果该海森矩阵是正定的,则上述问题的最优值 \(w^t -[\nabla^2f(w^t)]^{-1}\nabla f(w^t)\)处取到,牛顿法将其做为下一时刻的状态,即
下图给了一个简单实例:
牛顿法的伪代码如下所示:
相比于一阶方法中的梯度下降法,二阶的牛顿法提供了更为精细的步长调节,即利用当前状态海森矩阵的逆矩阵。因为步长更为精细,牛顿法的收敛速率比梯度下降法的收敛速率显著加快,具有二次收敛速率。
牛顿法收敛性 假设目标函数\(f: \mathbb{R}^d \rightarrow \mathbb{R}\)的导数\(\nabla f(w)\)是光滑的,存在二阶导数,并且在其最优点\(x^*\)处满足\(\nabla f\left(x^{*}\right)=0, \nabla^{2} f\left(x^{*}\right) \succ 0\)且初始点\(x^0\)与最优点\(x^*\)足够近,那么牛顿法具有\(\mathcal{O}(e^{-2^t})\)的超线性(二阶)收敛速率:
然而,事物总有两面性,相比一阶方法,虽然牛顿法的收敛速度更快,但是存在下面两个问题:
既然海森矩阵不一定正定,那就构造一个与海森矩阵相差不太远的正定矩阵作为其替代品,这正是拟牛顿法[5]的主要思想。此外,逆牛顿法可以迭代更新海森逆矩阵,而不是每次迭代都需要重新进行逆矩阵的计算。
记\(H_t = \nabla^2 f(w^t)\),\(M^t = [\nabla^2 f(w^t)]^{-1}\)。在第\(t+1\)轮迭代,对第\(t\)轮迭代的海森矩阵\(H_t\)加上一个或者两个秩为1的矩阵作为对\(t+1\)时刻的海森矩阵\(H^{t+1}\)的估计。例如:
当然,海森矩阵的更新需要满足一定的条件,比如下面推导的拟牛顿条件。
对\(f(w)\)在\(w^t\)处的二阶泰勒展开的左右两边计算梯度,可得
令\(\delta^t_1 = w^{t+1}-w^t\)为模型的更新量,\(\delta^t_2=\nabla f(w^{t+1}) - \nabla f(w^t)\)为目标函数导数的更新量,则我们有:
在拟牛顿条件下,更新规则为
此时,所对应的算法被称作BFGS算法,如下面伪代码所示:
在实际应用中基于\(M^t\)的拟牛顿法更实用,应为根据\(M^t\)计算下降方向的方法不需要对\(H^t\)矩阵求逆(解线性方程,其复杂度为\(\mathcal{O}(d^3)\),非常耗时)。但基于\(H^t\)的拟牛顿法有比较好的理论性质,产生的迭代序列比较稳定,但如果有办法快速求解线性方程组,我们也可以采用基于\(H^t\)的拟牛顿法。此外在某些场景下,比如有些带约束的优化问题的算法设计,由于需要用到海森矩阵的近似,\(H^t\)的使用也很常见。
当使用其它的海森矩阵近似方式和约束条件时,我们还可以设计出其他拟牛顿法,比如DFP[3][4]、Broyden[5]、SR1[6]等。
可以证明,当初始点最优点足够近时,拟牛顿法和牛顿法同样具有二阶收敛速率。
我们到目前为止提到的各种优化算法都是直接求解原始优化问题。某些时候,如果把原始优化问题转化成对偶优化问题,会更容易求解。比如,当原始问题的变量维度很高,但是约束条件个数不太多时,对偶问题的复杂度(对偶变量的维度对应于约束条件的个数)会远小于原始问题的复杂度,因而更容易求解(这也是支持向量机高效的主要原因)。本节我们将介绍与此相关的对偶理论以及常见的对偶优化算法[7]。
考虑下述原始优化问题\(P_0\):
包含\(m_1\)个不等式约束和\(m_2\)个等式约束。假设问题\(P_0\)的最优解为\(p^*\)。
首先,我们将有约束问题转化为无约束优化问题,即构造\(P_0\)的拉格朗日函数,将约束条件转化到目标函数中。考虑原始问题\(P_0\)中带有的约束条件,例如,当\(g_1(w^0)\geqslant0\)时,\(w^0\)就不是一个可行解,这时我们需要把对应的目标函数之补充定义为正无穷。于是可将原始优化问题转换为如下的无约束优化形式:
进一步地,我们用线性函数\(\lambda x (\lambda > 0)\)和\(\nu x\)来近似指示函数\(I_{[x>0]}\)和\(I_{[x\neq 0]}\),得到原始问题\(P_0\)所对应的拉格朗日函数:
其中,\(\lambda_i\geqslant 0\),\(\nu_j\in \mathbb{R}\)称为拉格朗日乘子。
接下来,我们讨论拉格朗日函数和原目标函数取值的大小关系,引出拉格朗日对偶函数的定义。如果假设\(w^0\)满足所有约束条件,那额拉格朗日函数中的第二项小于等于零,第三项等于零,即
在可行域\(\mathcal{W}\)上对上述不等式取最小值,得到
我们将上式左端称为拉格朗日对偶函数,简记为
由于拉格朗日对偶函数\(h(\lambda, \nu)\)是一族关于\((\lambda, \nu)\)仿射函数的逐点下确界,所以即使原始问题\(P_0\)不是凸的,拉格朗日对偶函数\(h(\lambda, \nu)\)也是凹的。
接下来我们定义对偶优化问题。既然拉格朗日对偶函数的取值是原始物体最优值的下界,在拉格朗日乘子\(\lambda\),\(\nu\)的取值空间对函数\(h(\lambda, \nu)\)取最大值,将会得到原始问题最优解的最大下界。这个问题通常被定义为原始问题\(P_0\)的对偶问题,记为\(D_0\),具体如下:
对偶问题是一个对凹函数在可行域(凸集)内求解最大值的问题,记最优值为\(d^*\)。通过上面的讨论,\(d^*<p^*\)恒成立,这个关系被称为弱对偶条件;如果\(d^* = p^*\),则称强对偶条件成立。很多研究工作讨论了强对偶条件成立的前提,比如Slater条件是强对偶的充分条件,KKT条件是强对偶的必要条件。
最后,可通过求解对偶问题来得到原始问题的解。在求解对偶问题的过程中,我们可以使用前面的各种一阶或二阶优化方法。假设对偶问题求得的解为\((\lambda^*, \nu^*)\),将其代入拉格朗日函数中,对原始变量求拉格朗日函数的最小值,即:
如果所求得的解是原始问题的一个可行解,那么它就是原始问题的最优解。
如果一个优化问题需要通过求解其对偶问题来解决,我们首先推导出它的对偶问题,并用各种一阶或者二阶方法来最大化对偶目标函数。比如,对偶坐标上升法使用梯度上升法最大化对偶目标函数,如下面伪代码所示:
对于带有线性约束的凸优化问题,对偶坐标上升法被证明至少具有线性收敛速率[6]。
到目前为止,我们介绍了求解数值优化问题的一阶、二阶确定性算法及对偶方法。作为总结,我们来对比一下这些算法的性能。
给定一个算法,对于不同凸性和光滑性质的目标函数,其收敛速率有所不同。通常来讲,更好的凸性和光滑性质会加速算法的收敛。同样对于强凸且光滑的目标函数,不同算法的性质也不同,我们有如下结论:
确定性算法是数值优化的基石。机器学习实践中更为常见也更实用的随机优化算法就是建立在确定性算法之上的,我们将在后面的博客中进行详细介绍。
我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div
总的来说,我对ruby还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
我正在尝试设置一个puppet节点,但rubygems似乎不正常。如果我通过它自己的二进制文件(/usr/lib/ruby/gems/1.8/gems/facter-1.5.8/bin/facter)在cli上运行facter,它工作正常,但如果我通过由rubygems(/usr/bin/facter)安装的二进制文件,它抛出:/usr/lib/ruby/1.8/facter/uptime.rb:11:undefinedmethod`get_uptime'forFacter::Util::Uptime:Module(NoMethodError)from/usr/lib/ruby
我想了解Ruby方法methods()是如何工作的。我尝试使用“ruby方法”在Google上搜索,但这不是我需要的。我也看过ruby-doc.org,但我没有找到这种方法。你能详细解释一下它是如何工作的或者给我一个链接吗?更新我用methods()方法做了实验,得到了这样的结果:'labrat'代码classFirstdeffirst_instance_mymethodenddefself.first_class_mymethodendendclassSecond使用类#returnsavailablemethodslistforclassandancestorsputsSeco
我希望我的UserPrice模型的属性在它们为空或不验证数值时默认为0。这些属性是tax_rate、shipping_cost和price。classCreateUserPrices8,:scale=>2t.decimal:tax_rate,:precision=>8,:scale=>2t.decimal:shipping_cost,:precision=>8,:scale=>2endendend起初,我将所有3列的:default=>0放在表格中,但我不想要这样,因为它已经填充了字段,我想使用占位符。这是我的UserPrice模型:classUserPrice回答before_val
我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer
设置:狂欢ruby1.9.2高线(1.6.13)描述:我已经相当习惯在其他一些项目中使用highline,但已经有几个月没有使用它了。现在,在Ruby1.9.2上全新安装时,它似乎不允许在同一行回答提示。所以以前我会看到类似的东西:require"highline/import"ask"Whatisyourfavoritecolor?"并得到:Whatisyourfavoritecolor?|现在我看到类似的东西:Whatisyourfavoritecolor?|竖线(|)符号是我的终端光标。知道为什么会发生这种变化吗? 最佳答案
我已经从我的命令行中获得了一切,所以我可以运行rubymyfile并且它可以正常工作。但是当我尝试从sublime中运行它时,我得到了undefinedmethod`require_relative'formain:Object有人知道我的sublime设置中缺少什么吗?我正在使用OSX并安装了rvm。 最佳答案 或者,您可以只使用“require”,它应该可以正常工作。我认为“require_relative”仅适用于ruby1.9+ 关于ruby-主要:Objectwhenrun
我有一个具有一些属性的模型:attr1、attr2和attr3。我需要在不执行回调和验证的情况下更新此属性。我找到了update_column方法,但我想同时更新三个属性。我需要这样的东西:update_columns({attr1:val1,attr2:val2,attr3:val3})代替update_column(attr1,val1)update_column(attr2,val2)update_column(attr3,val3) 最佳答案 您可以使用update_columns(attr1:val1,attr2:val2