1. 程式人生 > >無約束演算法-最速下降,牛頓法,擬牛頓,共軛梯度求解二次函式極小值

無約束演算法-最速下降,牛頓法,擬牛頓,共軛梯度求解二次函式極小值

import numpy as np
import math
a=np.random.randint(1,10,size=[100,1])
G=(a*a.T)+np.random.randint(1,5)*np.eye(100)
b=np.dot(G,np.ones((100,1)))
x0=np.random.random(size=[100])
def Df(x):#求出梯度函式
    return (np.dot(x,G)+b.T).reshape(100)
def hessian(df,z):#求hessian矩陣並賦值
    return np.array(G)
def fun(x):
    return 0.5*np.dot(np.dot(x,G),x.T)+np.dot(x,b)
def consice(x,dk):#精確線搜尋
    x=np.array(x)
    return (-np.dot(Df(x),dk)/(np.dot(np.dot(dk,G),dk)))
def stepest(x):#最速下降法
    return -Df(x)
def basicnewton(x):#牛頓法
    A=np.array(-np.dot(np.mat(G).I,Df(x)))
    A=A.reshape(100)
    return A
def Nnewton(x0,H0):#擬牛頓法
    return np.array(-np.dot(H0,Df(x0)))
def SR1(H0,sk,yk):#對稱秩1修正公式
    return np.array(H0+((sk.T-np.dot(H0,yk.T))*(sk-np.dot(H0,yk.T).T))/np.array((np.dot(sk-np.dot(H0,yk.T).T,yk.T))).reshape(1)[0])
def DFP(H0,sk,yk):
    return np.array(H0+(sk.T*sk)/(np.array(yk*sk.T).reshape(1)[0])-np.dot(np.dot(H0,yk.T)*yk,H0)/np.array(np.dot(np.dot(yk,H0),yk.T)).reshape(1)[0])
def BFGS(H0,sk,yk):
    return np.array(H0+(yk.T*yk)/(np.array(sk*yk.T).reshape(1)[0])-np.dot(np.dot(H0,sk.T)*sk,H0)/np.array(np.dot(np.dot(sk,H0),sk.T)).reshape(1)[0])
def solve(x0,eps):#x0為一n維向量
    k=0
    H0=np.eye(100)
    dk=-Df(x0)
    while np.linalg.norm(Df(x0))>eps:
        if 0:
            dk=basicnewton(x0)#最速下降法:stepest,牛頓法:basicnewton
            ak=consice(x0,dk)#精確線搜尋:consice,Armijo非精確線搜尋:Armijo,Wolfe非精確線搜尋:Wolfe
            x0=x0+np.dot(ak,dk)
        if 0:#擬牛頓法
            dk=Nnewton(x0,H0)#擬牛頓法
            ak=consice(x0,dk)#精確線搜尋:consice,Armijo非精確線搜尋:Armijo,Wolfe非精確線搜尋:Wolfe
            x1=x0
            y1=Df(x0)
            x0=x0+np.dot(ak,dk)
            sk=np.mat(x0-x1)
            yk=np.mat(Df(x0)-y1)
            H0=BFGS(H0,sk,yk)#修正公式選擇可選為SR1,DFP,BFGS
        if 1:#共軛梯度法
            ak=consice(x0,dk)#精確線搜尋:consice,Armijo非精確線搜尋:Armijo,Wolfe非精確線搜尋:Wolfe
            y1=Df(x0)
            x0=x0+np.dot(ak,dk)
            bk=np.dot(Df(x0),Df(x0))/np.dot(y1,y1)
            dk=-Df(x0)+bk*dk
        k+=1
        print("當前迭代點x"+str(k)+"="+str(x0)+",步長ak="+str(ak)+",方向dk="+str(dk)+"梯度範數為"+str(np.linalg.norm(Df(x0))))
    return x0
solve(x0,0.01)#初始搜尋點,精度

引數說明:

G=[[ 5., 1., 7., ..., 5., 2., 2.],

 [ 1., 5., 7., ..., 5., 2., 2.],

 [ 7., 7., 53., ..., 35., 14., 14.],

 ...,

 [ 5., 5., 35., ..., 29., 10., 10.],

 [ 2., 2., 14., ..., 10., 8., 4.],

 [ 2., 2., 14., ..., 10., 4., 8.]]

b=[ 518., 518., 3602., 3602., 3088., 4116., 2060., 2060., 2060., 2060., 3602., 1546., 2574., 2060., 1546., 3602., 4116., 518., 3602., 4116., 3602., 3088., 3088., 2060., 2574., 3088., 2574., 4630., 1546., 1032., 1032., 1546., 4630., 2574., 2574., 1546., 4116., 2574., 1032., 4630., 3602., 4116., 1546., 3088., 518., 1032., 4630., 4116., 2574., 3088., 4116., 3602., 518., 2574., 2574., 518., 1546., 1546., 1032., 4630., 3602., 2574., 4630., 518., 4630., 3088., 3088., 2574., 3088., 2574., 518., 3088., 3602., 3602., 3602., 3088., 2574., 2574., 4116., 1032., 2574., 2060., 3088., 4116., 1032., 3602., 518., 4116., 3602., 4116., 1032., 1032., 4116., 2574., 2060., 2060., 4630., 2574., 1032., 1032.]

初始點x0[0.36287532, 0.56325161, 0.51364076, 0.56812451, 0.7888315 , 0.51851197, 0.71170918, 0.21314076, 0.29913342, 0.60791091, 0.66803629, 0.9909708 , 0.25767777, 0.55595337, 0.38623466, 0.62318896, 0.33560756, 0.46152935, 0.2218254 , 0.25434027, 0.98353889, 0.66276815, 0.7908568 , 0.61753831, 0.32039222, 0.71970002, 0.60152159, 0.57305435, 0.79107977, 0.94360134, 0.9204414 , 0.68385586, 0.15941899, 0.56939455, 0.70809533, 0.71181405, 0.44015248, 0.64435278, 0.97920569, 0.79014869, 0.43985713, 0.74625209, 0.40611885, 0.11572177, 0.13629511, 0.4138309 , 0.36313254, 0.83684369, 0.59573989, 0.31371232, 0.12146105, 0.95490561, 0.46864787, 0.06499357, 0.44101515, 0.20665268, 0.35984193, 0.92585616, 0.15035858, 0.02689437, 0.58740769, 0.9081886 , 0.55210143, 0.96850184, 0.86565383, 0.60416907, 0.26910545, 0.18905435, 0.04546626, 0.80063242, 0.78408039, 0.14940875, 0.11748599, 0.46092049, 0.63143222, 0.75883652, 0.98800527, 0.68956898, 0.52701569, 0.62221375, 0.40302016, 0.75470691, 0.53014519, 0.37138053, 0.43437477, 0.65774449, 0.72548463, 0.3557923 , 0.99207761, 0.9516513 , 0.32944806, 0.77629668, 0.11325534, 0.83355515, 0.66354271, 0.19271679, 0.29166004, 0.72486387, 0.05547915, 0.42431452]

精度=0.01

最速下降法:

執行結果:

第一次迭代資訊如下:

第二次迭代資訊如下:

第三次迭代資訊如下:

x3處停止運算,經過三次迭代後找到極小值點

牛頓法:

第一次迭代資訊如下:

在x1處停止運算,經過一次迭代後找到極小值點

擬牛頓DFGS方法:

由於迭代次數過多,故只列出最後一次迭代資訊:

在x965處停止計算,經過965次迭代後找到極小值點

共軛梯度法

第一次迭代資訊如下:

第二次迭代資訊如下:

在x2處停止計算,經過兩次迭代找到極小值點

方法對比

最速下降法:3次迭代

牛頓法:1次迭代(精確解)

擬牛頓BFGS方法:965次迭代

共軛梯度法:2次迭代(精確解)