深入浅出最优化(5) 共轭梯度下降法

1 共轭方向的定义

对于正定二次函数f(\tilde{x})=\frac{1}{2}\tilde{x}^T\tilde{G}\tilde{x}+\tilde{b}^T\tilde{x},其中Gn\times n对角阵,对角元均为正数,这种情况下函数关于原点中心对称,每列由一个n元向量组成,向着每个维度,即正交搜索方向\tilde{d},作一次精确线搜索就可以得到最小值的精确解,具有二次终止性。这个过程结合图像不难理解。

在这里插入图片描述

G是是n\times n对称正定阵,而非对角阵,为了利用这一性质,我们需要将非对角阵变换为对角阵。作变换\tilde {x}=Dx,则有f(Dx)=\frac{1}{2}x^T(D^TGD)x+b^T(Dx),D中包含的每两个向量满足:

d_i^TGd_j=0,\quad i,j=0,1,...,n-1,i\neq j

这样一来,最后D^TGD就变成了对角矩阵\tilde{G}。我们称这样的每两个方向d_id_j共轭方向,经过这样的变换可以将共轭方向变为正交搜索方向。

三维直角坐标系中的正交搜索方向是很容易求取的,而对于非对角正定二次函数,我们主要要确定共轭方向,这相当于是对坐标进行变换后在新的坐标空间内的正交搜索方向

在这里插入图片描述

Gn\times n。若存在对称正定矩阵T,使得T^2=G,则称TG平方根矩阵,记为T=\sqrt{G},有变换d=T^{-1}\tilde{d}将正交搜索方向变为共轭方向。

对于秩为n的对称正定矩阵G,共轭方向有n个。

由任意x_0出发,依次沿直线f(\alpha)=x_k+\alpha d_k作满足g_k^Td_j=0的精确线性搜索,其中g_k=Gx_k+b(正定二次函数梯度),则搜满n个共轭方向后x_k线性流形X_k=\{x|x\in R^n,x=x_0+\displaystyle\sum_{j=0}^{k-1}\beta_jd_j,\beta_j\in R,j=0,...,k-1\}中的极小点。

2 针对二次函数的共轭梯度法

给定初始点,取初始搜索方向为负梯度方向,在后面的迭代中取负梯度方向和前一搜索方向的线性组合作为搜索方向d_k=-\nabla f(x_k)+\beta_kd_{k-1},k\geq 1,控制\beta_k使得共轭性条件d_k^TGd_{k-1}=0满足。

d_k=\begin{cases}-\nabla f(x_0)\quad k=0\\-\nabla f(x_0)+\beta_k d_{k-1}\quad k\geq 1\end{cases}

对于共轭方向有d^T_{k-1}Gd_k=0,则有d_{k-1}^TGd_k=-d_{k-1}^TG\nabla f(x_k)+\beta_k d_{k-1}^TGd_{k-1}=0,所以\beta_k=\frac{d_{k-1}^TG\nabla f(x_k)}{d_{k-1}^TGd_{k-1}}

因此可以得到针对二次函数的共轭梯度法步骤:

  1. 给定初始点,令d_0=-g_0,k=0
  2. 计算d_k=-g_k+\displaystyle\sum_{j=0}^{k-1}\frac{d_j^TGg_k}{d_j^TGd_j}d_j
  3. k=n-1,则停止
  4. 线搜索确定步长
  5. g_{k+1}=\nabla f(x_k+\alpha d_k),令k=k+1,转步2

3 针对一般函数的共轭梯度法

为了使得共轭梯度法适用于一般函数,我们要消除掉迭代公式中的G。

x_{k}=x_{k-1}+\alpha_{k-1}d_{k-1},k=1,2,...,两边求梯度有\nabla f(x_k)=\nabla f(x_{k-1})+\alpha_{k-1}Gd_{k-1},则有Gd_{k-1}=\frac{\nabla f(x_k)-\nabla f(x_{k-1})}{\alpha_{k-1}},代入\beta_k的计算公式可以消掉G,这种方法被称为HS共轭梯度法,有\beta_k^{HS}=\frac{\nabla f(x_k)^T[\nabla f(x_k)-\nabla f(x_{k-1})]}{d_{k-1}^T[\nabla f(x_k)-\nabla f(x_{k-1})]},k=1,2,...

HS法的共轭性证明见附录1。由共轭性证明我们可以得到三个结论:

  1. \nabla f(x_k)^Td_j=0
  2. \nabla f(x_k)^T\nabla f(x_j)=0,j<k
  3. \nabla f(x_k)^Td_k=-||\nabla f(x_k)||^2

利用以上三个结论可以得到HS共轭梯度法的更多变形,这两种变形产生算法的收敛性是可以得到证明的:

  • PRP共轭梯度法\beta_k^{PRP}=\frac{\nabla f(x_k)^T[\nabla f(x_k)-\nabla f(x_{k-1})]}{||\nabla f(x_{k-1})||^2},k=1,2,...
  • FR共轭梯度法\beta_k^{FR}=\frac{||\nabla f(x_k)||^2}{||\nabla f(x_{k-1})||^2},k=1,2,...

步骤:

  1. 给定初始点x_0\in R^n,精度\epsilon>0,令d_0=-\nabla f(x_0),k=0
  2. 若满足终止准则,则得解x_k,算法终止
  3. 确定步长\alpha_k
  4. x_{k+1}=x_k+\alpha_kd_k
  5. 由以上各种方法确定\beta_{k+1}
  6. d_{k+1}=-\nabla f(x_{k+1})+\beta_{k+1}d_{k}确定d_{k+1},令k=k+1,转2

4 性能评估

4.1 收敛性

使用精确搜索时,算法的收敛性是可以保证的。(证明见附录2)

  • 对于FR算法,采用非精确线性搜索时,需要使用强Wolfe-Powell条件,且0<\sigma<\frac{1}{2}(证明见附录3)

  • 对于PRP算法,采用非精确线性搜索时,需要使用PRP^+公式\beta^{PRP^+}=max\{\beta^{PRP},0\}。这是为了使得产生的\beta不为负数,保证下降方向的产生

4.2 其他性能

  • 二次终止性:满足,且若矩阵G有r个不同特征值,则算法最多经过r次迭代达到问题的最优解
  • 计算量:小,无需计算黑森矩阵
  • 储存空间:小,只需记录两点梯度和前一点方向。这使得共轭梯度法适用于解决大规模最优化问题

5 实战测试

对于本文集的第一篇文章深入浅出最优化(1) 最优化问题概念与基本知识中提出的最小二乘问题,x_1,x_2,x_3,x_4的初值均在[-2,2]的范围内随机生成,总共生成100组起点。统计迭代成功(在1000步内得到最优解且单次步长搜索迭代次数不超过1000次)的样本的平均迭代步数、平均迭代时间和得到的最优解及残差平方和最小值。

PRP+:

平均迭代步数 平均迭代时间 最优解 残差平方和最小值
17.1 0.41s x_1=0.1925~x_2=0.1989~x_3=0.1252~ x_4=0.1391 1.5382\times10^{-4}

FR:

平均迭代步数 平均迭代时间 最优解 残差平方和最小值
23.2 0.56s x_1=0.1807~x_2=0.4828~x_3=0.1868~ x_4=0.2556 1.8243\times10^{-4}

代码实现

本博客所有代码在https://github.com/HarmoniaLeo/optimization-in-a-nutshell开源,如果帮助到你,请点个star,谢谢这对我真的很重要!

你可以在上面的GitHub链接或本文集的第一篇文章深入浅出最优化(1) 最优化问题概念与基本知识中找到Function.py和lagb.py

import numpy as np
from Function import Function   #定义法求导工具
from lagb import *  #线性代数工具库
from scipy import linalg

n=2 #x的长度

def myFunc(x):  #x是一个包含所有参数的列表
    return x[0]**2 + 2*x[1]**2 + 2*x[0] - 6*x[1] +1 #目标方程

x=np.zeros(n)   #初始值点
e=0.001
beta1=1
sigma=0.4
rho=0.55
tar=Function(myFunc)
k=0
d=-tar.grad(x)
while tar.norm(x)>e:
    a=1
    if not (tar.value(x+a*d)<=tar.value(x)+rho*a*dot(turn(tar.grad(x)),d) and \
        np.abs(dot(turn(tar.grad(x+a*d)),d))>=sigma*dot(turn(tar.grad(x)),d)):
        a=beta1
        while tar.value(x+a*d)>tar.value(x)+rho*a*dot(turn(tar.grad(x)),d):
            a*=rho
        while np.abs(dot(turn(tar.grad(x+a*d)),d))<sigma*dot(turn(tar.grad(x)),d):
            a1=a/rho
            da=a1-a
            while tar.value(x+(a+da)*d)>tar.value(x)+rho*(a+da)*dot(turn(tar.grad(x)),d):
                da*=rho
            a+=da
    lx=x
    x=x+a*d
    beta=np.max((dot(turn(tar.grad(x)),tar.grad(x)-tar.grad(lx))/(tar.norm(lx)**2),0))  #PRP+
    beta=(tar.norm(x)**2)/(tar.norm(lx)**2) #FR
    d=-tar.grad(x)+beta*d
    k+=1
    print(k)
print(x)

附录

  1. 在这里插入图片描述
  2. 使用精确搜索时共轭梯度算法收敛性证明:因为g_{k}^Td_{k-1}=0,从而g_k^Td_k=-g_k^Tg_k+\beta_{k-1}g_k^Td_{k-1}<0

  3. 在这里插入图片描述
在这里插入图片描述
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。