最优化

您所在的位置:网站首页 求函数极值点的方法步骤 最优化

最优化

2024-06-30 19:03| 来源: 网络整理| 查看: 265

共轭梯度法(一般函数形式)

文章目录 共轭梯度法(一般函数形式)一般形式函数对共轭梯度法的挑战复习一下二次型函数的共轭梯度法步长 a k a_k ak​的变形 β k \beta_k βk​的变形Hesyenes-Stiefel公式Polak-Ribiere 公式Fletcher-Reeves公式Dai-Yuan公式Powell公式 重置搜索方向迭代过程代码示例调用函数定义搜索步长的函数构建搜索 β \beta β 的函数构造函数接口每n次迭代重置一次搜索方向 判断收敛比较多个方法之间的差异测试并绘图 声明参考

一般形式函数对共轭梯度法的挑战

一般形式的函数,黑塞矩阵不一定是个常量,这就必须寻找另外一个办法来迭代计算。当然也可以使用牛顿法进行近似,但是牛顿法到每步迭代都需要再迭代n步来近似,所以计算量还是很大的。

复习一下二次型函数的共轭梯度法

点击这里可以看我之前写的二次型共轭函数的博客

迭代过程**

初始条件: g 1 = H x 1 − b d 1 = r 1 = − g 1 g_1 = Hx_1-b\\ d_1 = r_1 = -g_1 g1​=Hx1​−bd1​=r1​=−g1​

迭代关系 a k = d K T r K d k T H d k x k + 1 = x k + a k d k r k + 1 = r k − a k H d k β k = r k + 1 T H d k d k T H d k d k + 1 = r k + 1 − β k d k a_k = \frac{d^T_Kr_K}{d^T_kHd_k}\\x_{k+1} = x_k + a_kd_k\\r_{k+1} = r_k - a_kHd_k\\\beta_{k} = \frac{r_{k+1}^THd_{k}}{d^T_{k}Hd_{k}}\\d_{k+1} = r_{k+1} - \beta_kd_k ak​=dkT​Hdk​dKT​rK​​xk+1​=xk​+ak​dk​rk+1​=rk​−ak​Hdk​βk​=dkT​Hdk​rk+1T​Hdk​​dk+1​=rk+1​−βk​dk​

黑塞矩阵H在非二次型函数中是一个n*n的每个元素都是一个关于自变量 X X X的函数的矩阵,所以计算量是很大的,特别是当函数是个多元函数的时候

所以我们既想要保留共轭梯度法的优势,有想要尽量避免H的计算

由上面的迭代关系可以看到,H的计算主要是在 a k 和 β k a_k和\beta_k ak​和βk​的计算中,所以我们现在需要的就是变形这两个公式,来近似原本的迭代过程。( r k + 1 r_{k+1} rk+1​这边没写是因为 r k + 1 r_{k+1} rk+1​可以变形成 − g k + 1 -g_{k+1} −gk+1​)

步长 a k a_k ak​的变形

步长的迭代其实就是找到该搜索方向下降速度最快的步长,(该方向的极小值),我们可以使用一维搜索算法,如果希望得到精确结果,可以使用牛顿法(一维的牛顿法H是常量矩阵),但是计算量比较大;也可以使用非精确的搜搜,例如划界法,黄金分割法等等…

β k \beta_k βk​的变形

β k \beta_k βk​的变形存在许多数学家提出的变形公式,不同的公式对不同的目标函数可能有不同的效果,我们在之后的代码中会进行比较

Hesyenes-Stiefel公式

我们知道 β k \beta_k βk​的迭代公式是这样的 β k = r k + 1 T H d k d k T H d k \beta_{k} = \frac{r_{k+1}^THd_{k}}{d^T_{k}Hd_{k}} βk​=dkT​Hdk​rk+1T​Hdk​​ 该方法选择使用一下公式来近似 H d k Hd_k Hdk​ H d k = g k + 1 − g k a k Hd_k = \frac{g_{k+1}-g_k}{a_k} Hdk​=ak​gk+1​−gk​​ 于是原本的公式就变形称为了 β k = − g k + 1 T ( g k + 1 − g k ) d k T ( g k + 1 − g k ) \beta_{k} = -\frac{g_{k+1}^T(g_{k+1}-g_k)}{d^T_{k}(g_{k+1}-g_k)} βk​=−dkT​(gk+1​−gk​)gk+1T​(gk+1​−gk​)​

Polak-Ribiere 公式

是在上一个公式的基础上进一步变形,这里不详细说了 β k = − g k + 1 T ( g k + 1 − g k ) d k T ( g k + 1 − g k ) = − g k + 1 T ( g k + 1 − g k ) d k T g k + 1 − d k T g k = g k + 1 T ( g k + 1 − g k ) d k T g k \beta_{k} = -\frac{g_{k+1}^T(g_{k+1}-g_k)}{d^T_{k}(g_{k+1}-g_k)}=-\frac{g_{k+1}^T(g_{k+1}-g_k)}{d^T_{k}g_{k+1}-d^T_{k}g_k}= \frac{g_{k+1}^T(g_{k+1}-g_k)}{d^T_{k}g_k} βk​=−dkT​(gk+1​−gk​)gk+1T​(gk+1​−gk​)​=−dkT​gk+1​−dkT​gk​gk+1T​(gk+1​−gk​)​=dkT​gk​gk+1T​(gk+1​−gk​)​ 这里的变形用到了共轭梯度法的性质:当前点的梯度方向与之前所有点的搜索方向都正交 d k = r k − β k − 1 d k − 1 = − g k − β k − 1 d k − 1 g k T d k = − g k T g k − β k − 1 g k T d k − 1 = − g k T g k β k = g k + 1 T ( g k − g k + 1 ) g k T g k d_k = r_k - \beta_{k-1}d_{k-1}=-g_k - \beta_{k-1}d_{k-1}\\ g_k^Td_k =-g_k^Tg_k - \beta_{k-1}g_k^Td_{k-1}=-g_k^Tg_k\\ \beta_k = \frac{g_{k+1}^T(g_{k}-g_{k+1})}{g_k^Tg_k} dk​=rk​−βk−1​dk−1​=−gk​−βk−1​dk−1​gkT​dk​=−gkT​gk​−βk−1​gkT​dk−1​=−gkT​gk​βk​=gkT​gk​gk+1T​(gk​−gk+1​)​

Fletcher-Reeves公式

β k = − g k + 1 T g k + 1 g k T g k \beta_k = -\frac{g^T_{k+1}g_{k+1}}{g^T_kg_k} βk​=−gkT​gk​gk+1T​gk+1​​

可以看出明显也是从上面的改进而来的。

Dai-Yuan公式

β k = − g k T g k d k − 1 T ( g k − g k − 1 ) \beta_k = -\frac{g^T_kg_k}{d^T_{k-1}(g_k-g_{k-1})} βk​=−dk−1T​(gk​−gk−1​)gkT​gk​​

Powell公式

β k = m a x { 0 , g k + 1 T ( g k − g k + 1 ) g k T g k } \beta_k = max\lbrace0, \frac{g_{k+1}^T(g_{k}-g_{k+1})}{g_k^Tg_k}\rbrace βk​=max{0,gkT​gk​gk+1T​(gk​−gk+1​)​}

重置搜索方向

这里还有一个问题,对于二次型函数共轭函数可以在n步之内达到极小值,但是对于非二次型的函数,由于我们采用的是近似的方法,并不能保证在n步之内就达到最小值,但是n元的目标函数最多只能构建n个互相线性独立的共轭防线,所以我们需要

将n次或者n次以后的搜索方向重置为梯度负方向

迭代过程

初始条件 g 1 = g ( x 0 ) d 1 = − g 1 g_1 = g(x0) \\d_1 = -g1 g1​=g(x0)d1​=−g1

迭代 α k = s e a c h − a l p h a ( . . . ) x k + 1 = x k + α k d k β k = 选 择 一 种 公 式 d k + 1 = − g k + 1 − β k d k \alpha_k = seach-alpha(...) \\x_{k+1} = x_k + \alpha_kd_k \\\beta_k = 选择一种公式 \\d_{k+1} = -g_{k+1}-\beta_kd_k αk​=seach−alpha(...)xk+1​=xk​+αk​dk​βk​=选择一种公式dk+1​=−gk+1​−βk​dk​

代码示例 using LinearAlgebra using Gadfly ## 非精确方法 function inexact_alpha(f,g,xk,fk,gk,d; α0 =1,ϵ=0.1,τ =0.5, η = 0.5,ζ=2.0) α = α0 Φ0 = d' * gk δ = α .* d xn = xk .+ δ fn = f(xn...) gn = g(xn...) # Armijo 不太大条件 while fn > fk + ϵ*α*Φ0 α = τ * α δ = α .* d xn = xk .+ δ fn = f(xn...) gn = g(xn...) end # Wolfe 不太小条件 while d' *gn < η * Φ0 α = ζ*α δ = α .* d xn = xk .+ δ fn = f(xn...) gn = g(xn...) end return α,δ,xn,fn,gn end ## TODO 划界法搜索步长 function aecant_alpha(f,g,xk,fk,gk,d;α0=1,accuracy=0.001,maxIter = 128) # _l是当前点,k-1 # _u是下一个点,k αl = α0 αu = α0*1.1 xl = xk .+ αl .* d xu = xk .+ αu .* d gl = g(xl...) gu = g(xu...) Φl = d' * gl Φu = d' * gu for i in 1:maxIter Δ = Φu - Φl # 防止出现分母为0的数学错误 if Δ == 0.0 println("error:出现分母为0的数学错误") return αu,αu.*d,xu,f(xu...),gu else Δ = Φu * (αu - αl)/ Δ end if abs(Δ) fk + ϵ*α*Φ0 α = τ * α δ = α .* d xn = xk .+ δ fn = f(xn...) gn = g(xn...) end # Wolfe 不太小条件 while d' *gn < η * Φ0 α = ζ*α δ = α .* d xn = xk .+ δ fn = f(xn...) gn = g(xn...) end return α,δ,xn,fn,gn end ##划界法搜索步长 function aecant_alpha(f,g,xk,fk,gk,d;α0=1,accuracy=0.001,maxIter = 128) # _l是当前点,k-1 # _u是下一个点,k αl = α0 αu = α0*1.1 xl = xk .+ αl .* d xu = xk .+ αu .* d gl = g(xl...) gu = g(xu...) Φl = d' * gl Φu = d' * gu for i in 1:maxIter Δ = Φu - Φl # 防止出现分母为0的数学错误 if Δ == 0.0 println("error:出现分母为0的数学错误") return αu,αu.*d,xu,f(xu...),gu else Δ = Φu * (αu - αl)/ Δ end if abs(Δ)


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3