共轭梯度法
最速下降法以及牛顿法都具有其自身的局限性。本文将要介绍的共轭梯度法是介于最速下降法与牛顿法之间的一种无约束优化算法,它具有超线性的收敛速度,而且算法结构简单,容易编程实现。此外,根最速下降法相类似,共轭梯度法只用到了目标函数及其梯度值,避免了二阶导数的计算,从而降低了计算量和存储量,因此它是求解无约束优化问题的一种比较有效而使用的算法。
一、共轭方向发
共轭方向法的基本思想是在求解
n
n
n维正定二次目标函数极小点时产生一组共轭方向作为搜索方向,在线搜索条件下算法之多迭代
n
n
n步即能求得极小点。京故宫适当修正后共轭方向法可以推广到求解一般非二次目标函数情形。下面先介绍共轭方向的概念。
定义1:设
G
G
G是
n
n
n阶对称正定矩阵,若
n
n
n维向量组
d
1
,
d
2
,
⋯
,
d
m
(
m
≤
n
)
满足
d_1,d_2,\cdots,d_m(m\le n)满足
d1,d2,⋯,dm(m≤n)满足
d
i
T
G
d
j
=
0
,
i
≠
j
d_i^TGd_j=0,i\neq j
diTGdj=0,i=j,则乘
d
1
,
d
2
,
⋯
,
d
m
d_1,d_2,\cdots,d_m
d1,d2,⋯,dm是
G
G
G共轭的。
显然,向量组的共轭是正交的推广,即当
G
=
I
G=I
G=I(单位阵)时,上述定义变成了向量组正交的定义。此外,不难证明,对称正定矩阵
G
G
G的共轭向量组必然是线性无关的。
下面我们考虑求解正定二次目标函数极小点的共轭方向法。设
min
f
(
x
)
=
1
2
x
T
G
x
+
b
T
x
+
c
(1)
\min f(x)=\frac{1}{2}x^TGx+b^Tx+c\tag{1}
minf(x)=21xTGx+bTx+c(1)
其中
G
G
G是
n
n
n阶对称正定阵,
b
b
b为
n
n
n为常向量,
c
c
c为常数。我们有下面的算法:
算法1:共轭方向法
0. 给定迭代精度
0
≤
ϵ
≤
1
0\le\epsilon\le 1
0≤ϵ≤1和初始点
x
0
x_0
x0。计算
g
0
=
∇
f
(
x
0
)
g_0=\nabla f(x_0)
g0=∇f(x0)。选取初始方向
d
0
d_0
d0使得
d
0
T
g
0
<
0
d_0^Tg_0\lt 0
d0Tg0<0。令
k
=
0
k=0
k=0.
- 若 ∣ ∣ g k ∣ ∣ ≤ ϵ ||g_k||\le\epsilon ∣∣gk∣∣≤ϵ,停算,输出 x ∗ ≈ x k x^*\approx x_k x∗≈xk.
- 利用线搜索方法确定步长 α k \alpha_k αk
- 令 x k + 1 = x k + α k d k x_{k+1}=x_k+\alpha_kd_k xk+1=xk+αkdk,并计算 g k + 1 = ∇ f ( x k + 1 ) g_{k+1}=\nabla f(x_{k+1}) gk+1=∇f(xk+1).
- 选取 d k + 1 d_{k+1} dk+1满足下降性和共轭性条件: d k + 1 T g k + 1 < 0 , d k + 1 T G d i = 0 , , i = 0 , 1 , ⋯ , k d_{k+1}^Tg_{k+1}\lt 0,d_{k+1}^TGd_i=0,\quad,i=0,1,\cdots,k dk+1Tgk+1<0,dk+1TGdi=0,,i=0,1,⋯,k.
- 令 k = k + 1 k=k+1 k=k+1,转步1
该算法的收敛性证明略过,如果感兴趣,可以去查找相应的数值优化专著。这里直接给出结论,在精确线搜索下,算法1求解正定二次目标函数极小化问题,之多在 n n n步内即可求得其唯一极小点。这种能在有限步内求得二次函数极小点的性质通常称为二次终止性。
二、共轭梯度法
共轭梯度法是在每一步迭代利用当前点处的最速下降方向来生成关于凸二次函数
f
f
f的海塞阵
G
G
G的共轭方向,并建立求
f
f
f在
R
n
\mathbb{R^n}
Rn上的极小点的方法。这一方法最早是由Hesteness和Stiefel于1952年为求解正定线性方程组而提出来的,后经Fletcher等人研究并应用于无约束优化问题取得了丰富的成果,共轭梯度法也因此成为当前求解无约束优化问题的重要算法类。
设函数如(1)式所定义,则
f
f
f的梯度和海塞矩阵为
g
(
x
)
=
∇
f
(
x
)
=
G
x
+
b
,
G
(
x
)
=
∇
2
f
(
x
)
=
G
(2)
g(x)=\nabla f(x)=Gx+b,\quad G(x)=\nabla^2 f(x)=G\tag{2}
g(x)=∇f(x)=Gx+b,G(x)=∇2f(x)=G(2)
下面我们讨论算法(1)中共轭方向的构造。我们取初始方向
d
0
d_0
d0为初始点
x
0
x_0
x0处的负梯度方向,即
d
0
=
−
∇
f
(
x
0
)
=
−
g
0
(3)
d_0=-\nabla f(x_0)=-g_0 \tag{3}
d0=−∇f(x0)=−g0(3)
从
x
0
x_0
x0出发沿
d
0
d_0
d0方向进行线搜索得到步长
α
0
\alpha_0
α0,令
x
1
=
x
0
+
α
0
d
0
x_1=x_0+\alpha_0d_0
x1=x0+α0d0
其中
α
0
\alpha_0
α0满足条件
∇
f
(
x
1
)
T
d
0
=
g
1
T
d
0
(4)
\nabla f(x_1)^Td_0=g_1^Td_0 \tag{4}
∇f(x1)Td0=g1Td0(4)
在
x
1
x_1
x1处,用
f
f
f在
x
1
x_1
x1的负梯度方向
−
g
1
-g_1
−g1与
d
0
d_0
d0的组合来生成
d
1
d_1
d1,即
d
1
=
−
g
1
+
β
0
d
0
(5)
d_1=-g_1+\beta_0d_0 \tag{5}
d1=−g1+β0d0(5)
然后选取系数
β
0
\beta_0
β0使
d
1
d_1
d1与
d
0
d_0
d0关于G共轭,即令
d
1
T
G
d
0
=
0
(6)
d_1^TGd_0 = 0 \tag{6}
d1TGd0=0(6)
来确定
β
0
\beta_0
β0,将(6)代入(5)得
β
0
=
g
1
T
G
d
0
d
0
T
G
d
0
(7)
\beta_0 = \frac{g_1^TGd_0}{d_0^TGd_0} \tag{7}
β0=d0TGd0g1TGd0(7)
由(2)得
g
1
−
g
0
=
G
(
x
1
−
x
0
)
=
α
0
G
d
0
(8)
g_1-g_0=G(x_1-x_0)=\alpha_0Gd_0 \tag{8}
g1−g0=G(x1−x0)=α0Gd0(8)
故由(3)~(5)可得
g
2
T
g
0
=
0
,
g
2
T
g
1
=
0
,
d
0
T
g
0
=
−
g
0
T
g
0
,
d
1
T
g
1
=
−
g
1
T
g
1
g_2^Tg_0=0,g_2^Tg_1=0,d_0^Tg_0=-g_0^Tg_0,d_1^Tg_1=-g_1^Tg_1
g2Tg0=0,g2Tg1=0,d0Tg0=−g0Tg0,d1Tg1=−g1Tg1
现假设已得到互相共轭得搜索方向
d
1
,
d
2
,
⋯
,
d
k
−
1
d_1,d_2,\cdots,d_{k-1}
d1,d2,⋯,dk−1,精确线搜索得到得步长为
α
0
,
α
1
,
⋯
,
α
k
−
1
\alpha_0,\alpha_1,\cdots,\alpha_{k-1}
α0,α1,⋯,αk−1,且满足
{
d
k
−
1
T
G
d
i
=
0
,
i
=
0
,
1
,
⋯
,
k
−
2
,
d
i
T
g
i
=
−
g
i
T
g
i
,
i
=
0
,
1
,
⋯
,
k
−
1
,
g
k
T
g
i
=
0
,
g
k
T
d
i
=
0
,
i
=
0
,
1
,
⋯
,
k
−
1.
(9)
\left\{ \begin{array}{rcl} d_{k-1}^TGd_i=0, &i=0,1,\cdots,k-2,\\ d_i^Tg_i=-g_i^Tg_i,&i=0,1,\cdots,k-1,\\ g_k^Tg_i=0,g_k^Td_i=0,&i=0,1,\cdots,k-1. \end{array} \right. \tag{9}
⎩
⎨
⎧dk−1TGdi=0,diTgi=−giTgi,gkTgi=0,gkTdi=0,i=0,1,⋯,k−2,i=0,1,⋯,k−1,i=0,1,⋯,k−1.(9)
现令
d
k
=
−
g
k
+
β
k
−
1
d
k
−
1
+
∑
i
=
0
k
−
1
β
k
(
i
)
d
i
(10)
d_k=-g_k+\beta_{k-1}d_{k-1}+\sum_{i=0}^{k-1}\beta_{k}^{(i)}d_i\tag{10}
dk=−gk+βk−1dk−1+i=0∑k−1βk(i)di(10)
其中
β
k
−
1
,
β
k
(
i
)
(
i
=
0
,
1
,
⋯
,
k
−
2
)
\beta_{k-1},\beta_k^{(i)}(i=0,1,\cdots,k-2)
βk−1,βk(i)(i=0,1,⋯,k−2)得选择要满足
d
k
T
G
d
i
=
0
,
i
=
0
,
1
,
⋯
,
k
−
1
(11)
d_k^TGd_i=0,i=0,1,\cdots,k-1\tag{11}
dkTGdi=0,i=0,1,⋯,k−1(11)
用
d
i
T
G
(
i
=
0
,
1
,
⋯
,
k
−
1
)
d_i^TG(i=0,1,\cdots,k-1)
diTG(i=0,1,⋯,k−1)左乘(10)得
β
k
−
1
=
g
k
T
G
d
k
−
1
d
k
−
1
T
G
d
k
−
1
,
β
k
(
1
)
=
g
k
T
G
d
i
d
i
T
G
d
i
,
i
=
0
,
1
,
⋯
,
k
−
2
(12)
\beta_{k-1}=\frac{g_k^TGd_{k-1}}{d_{k-1}^TGd_{k-1}},\beta_k^{(1)}=\frac{g_k^TGd_i}{d_i^TGd_i},i=0,1,\cdots,k-2\tag{12}
βk−1=dk−1TGdk−1gkTGdk−1,βk(1)=diTGdigkTGdi,i=0,1,⋯,k−2(12)
类似于(8),我们有
g
i
+
1
−
g
i
=
G
(
x
i
+
1
−
x
i
)
=
α
i
G
d
i
,
i
=
0
,
1
,
⋯
,
k
−
1
g_{i+1}-g_i=G(x_{i+1}-x_i)=\alpha_iGd_i,i=0,1,\cdots,k-1
gi+1−gi=G(xi+1−xi)=αiGdi,i=0,1,⋯,k−1
及
α
i
G
d
i
=
g
i
+
1
−
g
i
,
i
=
0
,
1
,
⋯
,
k
−
1
(13)
\alpha_iGd_i=g_{i+1}-g_i,i=0,1,\cdots,k-1\tag{13}
αiGdi=gi+1−gi,i=0,1,⋯,k−1(13)
于是由归纳法假设(9)可得
β
k
(
i
)
=
g
k
T
G
d
i
d
i
T
G
d
i
=
g
k
T
(
g
i
+
1
−
g
i
)
d
i
T
(
g
i
+
1
−
g
i
)
=
0
,
i
=
0
,
1
,
⋯
,
k
−
2.
\beta_k^{(i)}=\frac{g_k^TGd_i}{d_i^TGd_i}=\frac{g_k^T(g_{i+1}-g_i)}{d_i^T(g_{i+1}-g_i)}=0,i=0,1,\cdots,k-2.
βk(i)=diTGdigkTGdi=diT(gi+1−gi)gkT(gi+1−gi)=0,i=0,1,⋯,k−2.
于是,第k步得搜索方向为
d
k
=
−
g
k
+
β
k
−
1
d
k
−
1
,
(14)
d_k=-g_k+\beta_{k-1}d_{k-1},\tag{14}
dk=−gk+βk−1dk−1,(14)
其中
β
k
−
1
\beta_{k-1}
βk−1由(12)确定,即
β
k
−
1
=
g
k
T
G
d
k
−
1
d
k
−
1
T
G
d
k
−
1
(15)
\beta_{k-1}=\frac{g_k^TGd_{k-1}}{d_{k-1}^TGd_{k-1}}\tag{15}
βk−1=dk−1TGdk−1gkTGdk−1(15)
同时有
d
k
T
g
k
=
−
g
k
T
g
k
d_k^Tg_k=-g_k^Tg_k
dkTgk=−gkTgk。这样确定了一组由负梯度方向形成得共轭方向,而把沿着这组方向进行迭代得方向称为共轭梯度法。其证明过程这里略过。
下面我们给出共轭梯度法求解无约束优化问题(1)极小点得算法步骤
算法2:共轭梯度法
0. 给定迭代精度
0
≤
ϵ
<
1
0\le\epsilon\lt 1
0≤ϵ<1和初始点
x
0
x_0
x0。计算
g
0
=
∇
f
(
x
0
)
g_0=\nabla f(x_0)
g0=∇f(x0)。令
k
=
0
k=0
k=0
- 若 ∣ ∣ g k ∣ ∣ ≤ ϵ ||g_k||\le\epsilon ∣∣gk∣∣≤ϵ,停算,输出 x ) ≈ x k x^)\approx x_k x)≈xk
- 计算搜索方向
d
k
d_k
dk:
KaTeX parse error: Unknown column alignment: s at position 29: …\begin{array}{ls̲c} -g_k,&k=0,\\…
其中当 k ≥ 1 k\ge 1 k≥1时, β k − 1 \beta_{k-1} βk−1由(15)确定 - 利用线搜索方法确定搜索步长 α k \alpha_k αk
- 令 x k + 1 = x k + α k d k x_{k+1}=x_k+\alpha_kd_k xk+1=xk+αkdk,并计算 g k + 1 = ∇ f ( x k + 1 ) g_{k+1}=\nabla f(x_{k+1}) gk+1=∇f(xk+1)
- 令 k = k + 1 k=k+1 k=k+1,转步1
计算公式(15)是由Fletcher和Reeves给出得,故称之为FR公式,算法2也称之为FR共轭梯度法。除FR工诗外,尚有下列著名公式:
β
k
=
g
k
+
1
T
g
k
+
1
−
d
k
T
g
k
,
(
D
i
x
o
n
公式
)
β
k
=
g
k
+
1
T
g
k
+
1
d
k
T
(
g
k
+
1
−
g
k
)
,
(
D
a
i
−
Y
u
a
n
公式
)
β
k
=
g
k
+
1
T
(
g
k
+
1
−
g
k
)
d
k
T
(
g
k
+
1
−
g
k
)
,
(
C
r
o
w
d
e
r
−
W
o
l
f
e
公式
)
β
k
=
g
k
+
1
T
(
g
k
+
1
−
g
k
)
g
k
T
g
k
,
(
P
o
l
a
k
,
R
i
b
i
e
r
e
,
P
l
o
y
a
k
,
P
R
P
公式
)
\begin{aligned} \beta_k&=\frac{g_{k+1}^Tg_{k+1}}{-d_k^Tg_k}, (Dixon公式) \\ \beta_k&=\frac{g_{k+1}^Tg_{k+1}}{d_k^T(g_{k+1}-g_k)}, (Dai-Yuan公式) \\ \beta_k&=\frac{g_{k+1}^T(g_{k+1}-g_k)}{d_k^T(g_{k+1}-g_k)}, (Crowder-Wolfe公式) \\ \beta_k&=\frac{g_{k+1}^T(g_{k+1}-g_k)}{g_k^Tg_k}, (Polak,Ribiere,Ployak,PRP公式) \\ \end{aligned}
βkβkβkβk=−dkTgkgk+1Tgk+1,(Dixon公式)=dkT(gk+1−gk)gk+1Tgk+1,(Dai−Yuan公式)=dkT(gk+1−gk)gk+1T(gk+1−gk),(Crowder−Wolfe公式)=gkTgkgk+1T(gk+1−gk),(Polak,Ribiere,Ployak,PRP公式)
三、共轭梯度法得matlab实现
在共轭梯度法得实际使用中,通常在迭代n步或n+1步之后,重新选取负梯度方向作为搜索方向,我们称之为再开始共轭梯度法。这是因为对于一般非二次函数而言,n步迭代后共轭梯度法产生得搜索方向往往不再具有共轭性。而对于大规模问题,常常每
m
(
m
<
n
或
m
≪
n
)
m (m<n或m\ll n)
m(m<n或m≪n)步就进行再开始。此外,当搜索方向不是下降方向时,也插入负梯度方向所作为搜索方向。
这里给出基于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
利用程序求解无约束优化问题
min
x
∈
R
2
f
(
x
)
=
100
(
x
1
2
−
x
2
)
2
+
(
x
1
−
1
)
2
\min_{x\in\mathbb{R^2}}\quad f(x)=100(x_1^2-x_2)^2+(x_1-1)^2
x∈R2minf(x)=100(x12−x2)2+(x1−1)2
该问题由精确解
x
∗
=
(
1
,
1
)
T
,
f
(
x
∗
)
=
0
x^*=(1,1)^T,f(x^*)=0
x∗=(1,1)T,f(x∗)=0
求解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)