(FR)共轭梯度法是介于最速下降法和牛顿法之间的一个方法,相比最速下降法收敛速度快,并且不需要像牛顿法一样计算Hesse矩阵,只需计算一阶导数
共轭梯度法是共轭方向法的一种,意思是搜索方向都互相共轭
共轭的定义如下:
共轭梯度法是一种典型的共轭方向法,它的搜索方向是负梯度方向和上一次搜索方向的一个组合
关于βk-1,有两种常用的计算公式
(PRP公式)
(PRP公式)
预处理共轭法改善了G的条件数,使算法的收敛速度加快
预处理的方法是寻找一个非奇异矩阵C,使得C-TGC-1的条件数小于G的条件数
再开始共轭梯度法是满足某一条件后重新使用最速下降方向作为搜索方向,这个条件包括迭代n步,或共轭梯度方向是上升方向
下面给出这几种方法的python实现
FR共轭梯度法:
# coding=utf-8 # FR-CG共轭梯度法 from linear_search.Function import * from linear_search.wolfe import * import numpy as np def conjugate(_f, _x): fun = Function(_f) x = array(_x) d = -fun.grad(x) while fun.norm(x) > 0.01: alpha = wolfe(_f, x, d) g = np.mat(fun.grad(x)) beta = 1 / np.dot(g, g.T) x = x + alpha * d g = np.mat(fun.grad(x)) beta = beta * np.dot(g, g.T) d = array(-g + beta * d)[0] return x
再开始共轭梯度法:
# coding=utf-8 # 再开始共轭梯度法 from linear_search.Function import * from linear_search.wolfe import * import numpy as np def restart_conjugate(_f, _x, n): fun = Function(_f) x = array(_x) while True: d = -fun.grad(x) k=0 if(np.linalg.norm(d)<0.01): break while fun.norm(x) > 0.01: g = np.mat(fun.grad(x)) alpha = wolfe(_f, x, d) x = x + alpha * d k=k+1 g1= np.mat(fun.grad(x)) if np.dot(g1,g.T)/np.dot(g1,g1.T)>0.1 or k>=n: if np.linalg.norm(g1)<0.01: return x break else: beta = np.dot(g1, g1.T) / np.dot(g, g.T) d = array(-g + beta * d)[0] if np.dot(mat(d),g1.T)>0: break return x