共轭梯度法

最速下降法以及牛顿法都具有其自身的局限性。本文将要介绍的共轭梯度法是介于最速下降法与牛顿法之间的一种无约束优化算法,它具有超线性的收敛速度,而且算法结构简单,容易编程实现。此外,根最速下降法相类似,共轭梯度法只用到了目标函数及其梯度值,避免了二阶导数的计算,从而降低了计算量和存储量,因此它是求解无约束优化问题的一种比较有效而使用的算法。

一、共轭方向发
共轭方向法的基本思想是在求解简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_算法维正定二次目标函数极小点时产生一组共轭方向作为搜索方向,在线搜索条件下算法之多迭代简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_算法步即能求得极小点。京故宫适当修正后共轭方向法可以推广到求解一般非二次目标函数情形。下面先介绍共轭方向的概念。
定义1:设简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_线性代数_03简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_算法阶对称正定矩阵,若简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_算法维向量组简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_算法_06简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_算法_07,则乘简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_线性代数_08简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_线性代数_03共轭的。
显然,向量组的共轭是正交的推广,即当简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_线性代数_10(单位阵)时,上述定义变成了向量组正交的定义。此外,不难证明,对称正定矩阵简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_线性代数_03的共轭向量组必然是线性无关的。
下面我们考虑求解正定二次目标函数极小点的共轭方向法。设
简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_最优化_12
其中简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_线性代数_03简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_算法阶对称正定阵,简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_机器学习_15简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_算法为常向量,简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_数值计算_17为常数。我们有下面的算法:


算法1:共轭方向法
0. 给定迭代精度简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_算法_18和初始点简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_机器学习_19。计算简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_算法_20。选取初始方向简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_线性代数_21使得简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_算法_22。令简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_算法_23.

  1. 简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_最优化_24,停算,输出简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_数值计算_25.
  2. 利用线搜索方法确定步长简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_机器学习_26
  3. 简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_线性代数_27,并计算简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_机器学习_28.
  4. 选取简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_数值计算_29满足下降性和共轭性条件:简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_最优化_30.
  5. 简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_数值计算_31,转步1

该算法的收敛性证明略过,如果感兴趣,可以去查找相应的数值优化专著。这里直接给出结论,在精确线搜索下,算法1求解正定二次目标函数极小化问题,之多在简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_算法步内即可求得其唯一极小点。这种能在有限步内求得二次函数极小点的性质通常称为二次终止性。

二、共轭梯度法
共轭梯度法是在每一步迭代利用当前点处的最速下降方向来生成关于凸二次函数简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_数值计算_33的海塞阵简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_线性代数_03的共轭方向,并建立求简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_数值计算_33简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_线性代数_36上的极小点的方法。这一方法最早是由Hesteness和Stiefel于1952年为求解正定线性方程组而提出来的,后经Fletcher等人研究并应用于无约束优化问题取得了丰富的成果,共轭梯度法也因此成为当前求解无约束优化问题的重要算法类。
设函数如(1)式所定义,则简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_数值计算_33的梯度和海塞矩阵为
简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_线性代数_38
下面我们讨论算法(1)中共轭方向的构造。我们取初始方向简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_线性代数_21为初始点简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_机器学习_19处的负梯度方向,即
简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_线性代数_41
简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_机器学习_19出发沿简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_线性代数_21方向进行线搜索得到步长简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_算法_44,令
简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_数值计算_45
其中简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_算法_44满足条件
简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_机器学习_47
简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_最优化_48处,用简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_数值计算_33简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_最优化_48的负梯度方向简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_数值计算_51简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_线性代数_21的组合来生成简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_机器学习_53,即
简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_线性代数_54
然后选取系数简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_数值计算_55使简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_机器学习_53简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_线性代数_21关于G共轭,即令
简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_算法_58
来确定简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_数值计算_55,将(6)代入(5)得
简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_算法_60
由(2)得
简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_线性代数_61
故由(3)~(5)可得
简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_算法_62
现假设已得到互相共轭得搜索方向简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_算法_63,精确线搜索得到得步长为简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_线性代数_64,且满足
简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_机器学习_65
现令
简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_算法_66
其中简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_机器学习_67得选择要满足
简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_数值计算_68
简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_算法_69左乘(10)得
简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_机器学习_70
类似于(8),我们有
简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_线性代数_71

简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_线性代数_72
于是由归纳法假设(9)可得
简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_线性代数_73
于是,第k步得搜索方向为
简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_数值计算_74
其中简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_线性代数_75由(12)确定,即
简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_线性代数_76
同时有简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_数值计算_77。这样确定了一组由负梯度方向形成得共轭方向,而把沿着这组方向进行迭代得方向称为共轭梯度法。其证明过程这里略过。
下面我们给出共轭梯度法求解无约束优化问题(1)极小点得算法步骤


算法2:共轭梯度法
0. 给定迭代精度简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_机器学习_78和初始点简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_机器学习_19。计算简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_算法_20。令简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_算法_23

  1. 简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_最优化_24,停算,输出简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_算法_83
  2. 计算搜索方向简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_算法_84:
    KaTeX parse error: Unknown column alignment: s at position 29: …\begin{array}{ls̲c} -g_k,&k=0,\\…
    其中当简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_机器学习_85时,简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_线性代数_86由(15)确定
  3. 利用线搜索方法确定搜索步长简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_机器学习_26
  4. 简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_线性代数_27,并计算简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_机器学习_28
  5. 简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_数值计算_31,转步1

计算公式(15)是由Fletcher和Reeves给出得,故称之为FR公式,算法2也称之为FR共轭梯度法。除FR工诗外,尚有下列著名公式:
简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_数值计算_91

三、共轭梯度法得matlab实现
在共轭梯度法得实际使用中,通常在迭代n步或n+1步之后,重新选取负梯度方向作为搜索方向,我们称之为再开始共轭梯度法。这是因为对于一般非二次函数而言,n步迭代后共轭梯度法产生得搜索方向往往不再具有共轭性。而对于大规模问题,常常每简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_数值计算_92步就进行再开始。此外,当搜索方向不是下降方向时,也插入负梯度方向所作为搜索方向。
这里给出基于Armijo-rule非精确线搜索得再开始FR共轭梯度法得matlab程序。

function [fmin, xmin] = frcg(fun, gfun, x0, epsilon)

maxk = 5000;
rho = 0.6;
sigma = 0.4;
k = 0;
n = length(x0);
 
 while k < maxk
     g = feval(gfun, x0);
     itern = k - (n+1) * floor(k / (n + 1));
     itern = itern + 1;
     
     if (itern == 1)
         d = -g;
     else
         beta = (g' * g) / (g0' * g0);
         d = -g + beta * d0; gd = g' * d;
         if (gd >= 0.0)
             d = -g;
         end
     end
     
     if (norm(g) < epsilon), break; end
     
     m = 0; mk = 0;
     
     while (m < 20)  % armijo-rule 
         if (feval(fun, x0 + rho^m*d) < feval(fun, x0) + sigma * rho^m*g'*d)
             mk = m; break;
         end
         m = m + 1;
     end
     
     x0 = x0 + rho^mk*d;
     val = feval(fun, x0);
     fprintf('kIter = %d, fmin = %f\n', k, val);
     
     g0 = g; d0 = d;
     k = k+1;
 end
 x = x0;
 val = feval(fun, x);
 xmin = x;
 fmin = val;


end

利用程序求解无约束优化问题
简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_算法_93
该问题由精确解简单的共轭梯度法的Python代码示例代码例子 共轭梯度法优缺点_机器学习_94

求解main函数

x0 = [0, 0]';
epsilon = 1e-4;

[fmin, xmin] = frcg('func', 'gfunc', x0, epsilon);
fprintf('frcg: fmin = %f, xmin = (%f, %f)\n', fmin, xmin(1), xmin(2));

[x, f] = fminsearch('func', x0);
fprintf('build-in search: fmin = %f, xmin = (%f, %f)\n', f, x(1), x(2));

函数定义以及梯度求解

function f = func(x)

f = 100 * (x(1)^2 - x(2))^2 + (x(1) - 1)^2;

end
function grad = gfunc(x)

grad = [400 * x(1) * (x(1)^2-x(2))+2*(x(1)-1); ...
    -200 * (x(1)^2-x(2))];

end

求解结果为:

frcg: fmin = 0.000000, xmin = (0.999921, 0.999841)
build-in search: fmin = 0.000000, xmin = (1.000004, 1.000011)