拟牛顿法过程如下:
DFP修正公式:
步长a根据线性搜索得出,也可以根据公式得出,证明如下:
代码如下:
import numpy as np import sympy as sp def jacobian(f,x):#雅可比矩阵,求一阶导数 a,b=np.shape(x)#判断变量维度 x1,x2=sp.symbols('x1 x2')#定义变量,如果多元的定义多元的 x3=[x1,x2]#将1变量放入列表中,方便查找和循环。有几个变量放几个 df=np.array([[0.00000],[0.00000]])#定义一个空矩阵,将雅可比矩阵的值放入,保留多少位小数,小数点后面就有几个0。n元变量就加n个[] for i in range(a):#循环求值 df[i,0]=sp.diff(f,x3[i]).subs({x1:x[0][0],x2:x[1][0]})#求导和求值,n元的在subs后面补充 return df def hesse(f,x):#hesse矩阵 a,b=np.shape(x) x1,x2=sp.symbols('x1 x2') x3=[x1,x2] G=np.zeros((a,a)) for i in range(a): for j in range(a): G[i,j]=sp.diff(f,x3[i],x3[j]).subs({x1:x[0][0],x2:x[1][0]})#n元的在subs后面补充 return G def dfp_newton(f, x, iters): """ 实现DFP拟牛顿算法 :param f: 原函数 :param x: 初始值 :param iters: 遍历的最大迭代次数 :return: 最终更新完毕的x值 """ a = 1#定义初始步长 H = np.eye(2) # 初始化正定矩阵 G=hesse(f,x)#初始化Hesse矩阵 epsilon = 1e-3 # 一阶导g的第二范式的最小值(阈值) for i in range(1, iters): g = jacobian(f, x) if np.linalg.norm(g) < epsilon: xbest=[] for a in x: xbest.append(round(a[0]))#将结果从矩阵中输出放到列表中并四舍五入 break #下面的迭代公式 d= -np.dot(H,g) a=-(np.dot(g.T,d)/np.dot(d.T,np.dot(G,d))) # 更新x值 x_new = x +a*d print("第 %d 次结果"%i) print(x_new) g_new = jacobian(f, x_new) y = g_new - g s = x_new - x #更新H H=H+np.dot(s,s.T)/np.dot(s.T,y)-np.dot(H,np.dot(y,np.dot(y.T,H)))/np.dot(y.T,np.dot(H,y)) #更新G G=hesse(f,x_new) x = x_new return xbest x1,x2=sp.symbols('x1 x2')#例子 x=np.array([[2],[1]]) f=2*x1**2+x2**2-4*x1+2 print(dfp_newton(f,x,20))
此代码可以求多元函数的DFP算法。运行结果如下:
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)