我正在计算标量字段的Hessian,并尝试使用numdifftools。这似乎可行,但是速度很慢,所以我使用有限的差异编写了自己的方法。
这是我的黑森州代码:
def hessianComp ( func, x0, epsilon=1.e-5):
f1 = scipy.optimize.approx_fprime( x0, func, epsilon=epsilon)
# Allocate space for the hessian
n = x0.shape[0]
hessian = np.zeros ( ( n, n ) )
# The next loop fill in the matrix
xx = x0
for j in range( n ):
xx0 = xx[j] # Store old value
xx[j] = xx0 + epsilon # Perturb with finite difference
# Recalculate the partial derivatives for this new point
f2 = scipy.optimize.approx_fprime( xx, func, epsilon=epsilon)
hessian[:, j] = (f2 - f1)/epsilon # scale...
xx[j] = xx0 # Restore initial value of x0
return hessian
我使用以下代码在测试函数上都尝试了
def testfunction(x):
return(x[0]**2 + x[1]**2)
out1 = hessianComp(testfunction, np.array([2.,2.]))
out2 = numdifftools.Hessian(testfunction)([2., 2.])
返回
out1 = array([[2.00000017, 0. ],
[0. , 2.00000017]])
out2 = array([[2.00000000e+00, 1.04776726e-14],
[1.04776726e-14, 2.00000000e+00]])
因此对于我的测试功能,它似乎给出了正确的结果。但是,如果我尝试在计算Hessian的实际函数上执行此操作,则不会获得相同的结果。我要为其计算Hessian的函数是一个标量字段:
def lambda2Field(x):
out = solve_ivp(doubleGyreVar, t_span=(0, T), y0=[x[0], x[1], 1, 0, 0, 1],t_eval=[0, T], rtol = 1e-10, atol=1e-10)
output = out.y
J = output[2:,-1].reshape(2,2,order="F")
CG = np.matmul(J.T , J)
lambdas, xis = np.linalg.eig(CG)
lambda_2 = np.max(np.abs(lambdas))
return lambda_2
out1 = hessianComp(lambda2Field, np.array([2.,2.]))
out2 = numdifftools.Hessian(lambda2Field)([2., 2.])
并给出以下内容:
out1 = array([[-1.53769104e+18, -2.20719407e+21],
[-2.20719407e+21, 1.39720111e+27]])
out2 = array([[-1.53767292e+18, 2.27457455e-07],
[ 2.27457455e-07, -9.43198781e+16]])
有趣的是,只有我的黑森州矩阵的第一个元素(1,1)是相同的。其他元素相差很大。有人可以帮我了解这可能来自哪里吗?
谢谢!