import numpy as np
from scipy import optimize
- 定义要求最小值的函数,这里以 f(x,y)=(1−x)2+100(y−x2)2 f ( x , y ) = ( 1 − x ) 2 + 100 ( y − x 2 ) 2 为例
# 定义目标函数
def target_function(x,y):
return (1-x)**2+100*(y-x**2)**2
- 计算出定义函数的Jacobian矩阵和Hessian矩阵(BFGS不需要Hessian矩阵,但是其他算法需要,所有可以提前计算出来)
- 由于 ∂f∂x=−2+2x−400x(y−x2),∂f∂y=200y−200x2 ∂ f ∂ x = − 2 + 2 x − 400 x ( y − x 2 ) , ∂ f ∂ y = 200 y − 200 x 2 ,所以Jacobian矩阵为
[−2+2x−400x(y−x2)200y−200x2](1)
(1)
[
−
2
+
2
x
−
400
x
(
y
−
x
2
)
200
y
−
200
x
2
]
+ 由于 ∂2f∂x2=2(600x2−200y+1),∂2f∂x∂y=∂2f∂y∂x=−400x,∂2f∂y2=200 ∂ 2 f ∂ x 2 = 2 ( 600 x 2 − 200 y + 1 ) , ∂ 2 f ∂ x ∂ y = ∂ 2 f ∂ y ∂ x = − 400 x , ∂ 2 f ∂ y 2 = 200 ,所有Hessian矩阵为
[2(600x2−200y+1)−400x−400x200](2)
(2)
[
2
(
600
x
2
−
200
y
+
1
)
−
400
x
−
400
x
200
]
- 使用一个类来保存函数、函数的Jacobian矩阵、函数的Hessian矩阵
class TargetFunction(object):
def __init__(self):
self.f_points = []
self.fjac_points = []
self.fhess_points = []
def f(self,p):
'''
给定点p(x,y),返回函数值f(x,y)
'''
x,y = p.tolist()
z = target_function(x,y)
self.f_points.append((x,y))
return z
def fjac(self,p):
'''
给定点p(x,y),返回函数在点p处的Jacobian矩阵
'''
x,y = p.tolist()
self.fjac_points.append((x,y))
dx = -2 + 2*x -400*x*(y-x**2)
dy = 200*y -200*x**2
return np.array([dx,dy])
def fhess(self,p):
'''
给定点p(x,y),返回函数在点p处的Hessian矩阵
'''
x,y = p.tolist()
self.fhess_points.append((x,y))
hess = np.array([[2*(600*x**2-200*y+1),-400*x],
[-400*x,200]])
return hess
函数原型:scipy.optimize.minimize(fun, x0, args=(), method=None, jac=None, hess=None, hessp=None, bounds=None, constraints=(), tol=None, callback=None, options=None);常用参数解释如下:
fun:取局部最小值的函数
x0:初始点
method:优化方法,包括Nelder-Mead、Powell、CG、BFGS、Newtom-CG、L-BFGS-B、TNC、COBYLA、SLSQP、dogleg、trust-ncg、
jac:计算函数fun的Jacobian矩阵
hessian:计算函数fun的Hessian矩阵
target = TargetFunction()
# 初始点
init_point = (-1,-1)
# 使用BFGS求局部极小值
res = optimize.minimize(target.f,init_point,method="BFGS",jac=target.fjac)
print(res)
fun: 1.8499217223747175e-16
hess_inv: array([[ 0.50825961, 1.01607777],
[ 1.01607777, 2.03629519]])
jac: array([ 2.76270214e-07, -1.26083165e-07])
message: 'Optimization terminated successfully.'
nfev: 40
nit: 31
njev: 40
status: 0
success: True
x: array([ 1.00000001, 1.00000002])