(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