如何获得渐变和 Hessian |同情
How to get the Gradient and Hessian | Sympy
情况如下:我有一个符号函数 lamb,它是变量 z 的元素和变量 h 的函数元素的函数。这是 lamb 符号函数的图像
.
现在我想计算这个函数关于变量 eta 和 xi 的梯度和 Hessian。当然,我用谷歌搜索了它,但我找不到直接的方法来做到这一点。我发现的是 here,但正如我所说,这并不是解决这种情况的最佳方法。任何的想法?
贝娄,源代码。谢谢
from sympy import Symbol, Matrix, Function, simplify
eta = Symbol('eta')
xi = Symbol('xi')
x = Matrix([[xi],[eta]])
h = [Function('h_'+str(i+1))(x[0],x[1]) for i in range(3)]
z = [Symbol('z_'+str(i+1)) for i in range(3)]
lamb = 0
for i in range(3):
lamb += 1/(2*sigma**2)*(z[i]-h[i])**2
simplify(lamb)
你可以简单地计算梯度向量"manually"(假设变量的顺序是(z1, z2, z3, eta)
):
[lamb.diff(x) for x in z+[eta]]
同理,对于Hessian矩阵:
[[lamb.diff(x).diff(y) for x in z+[eta]] for y in z+[eta]]
您可以使用 Stelios 建议的非常 Pythonic 的方式,或者使用 SymPy 最近添加的一些功能:
In [14]: from sympy.tensor.array import derive_by_array
In [15]: derive_by_array(lamb, (eta, xi))
Out[15]:
[-(z_1 - h_1(xi, eta))*Derivative(h_1(xi, eta), eta)/sigma**2 - (z_2 - h_2(xi,
eta))*Derivative(h_2(xi, eta), eta)/sigma**2 - (z_3 - h_3(xi, eta))*Derivativ
e(h_3(xi, eta), eta)/sigma**2, -(z_1 - h_1(xi, eta))*Derivative(h_1(xi, eta),
xi)/sigma**2 - (z_2 - h_2(xi, eta))*Derivative(h_2(xi, eta), xi)/sigma**2 - (z
_3 - h_3(xi, eta))*Derivative(h_3(xi, eta), xi)/sigma**2]
不幸的是,打印机仍然缺少 N-dim 数组,您可以通过将它们转换为列表来可视化(或者,使用 .tomatrix()):
In [16]: list(derive_by_array(lamb, (eta, xi)))
Out[16]:
⎡ ∂ ∂
⎢ (z₁ - h₁(ξ, η))⋅──(h₁(ξ, η)) (z₂ - h₂(ξ, η))⋅──(h₂(ξ, η)) (z₃ - h₃(ξ, η
⎢ ∂η ∂η
⎢- ──────────────────────────── - ──────────────────────────── - ─────────────
⎢ 2 2
⎣ σ σ
∂ ∂ ∂
))⋅──(h₃(ξ, η)) (z₁ - h₁(ξ, η))⋅──(h₁(ξ, η)) (z₂ - h₂(ξ, η))⋅──(h₂(ξ, η))
∂η ∂ξ ∂ξ
───────────────, - ──────────────────────────── - ────────────────────────────
2 2 2
σ σ σ
∂ ⎤
(z₃ - h₃(ξ, η))⋅──(h₃(ξ, η))⎥
∂ξ ⎥
- ────────────────────────────⎥
2 ⎥
σ ⎦
对于 Hessian,只需重复该过程两次:
In [18]: list(derive_by_array(derive_by_array(lamb, (eta, xi)), (eta, xi)))
Out[18]:
⎡ 2 2
⎢ ∂ ∂
⎢ (z₁ - h₁(ξ, η))⋅───(h₁(ξ, η)) (z₂ - h₂(ξ, η))⋅───(h₂(ξ, η)) (z₃ - h₃(ξ,
⎢ 2 2
⎢ ∂η ∂η
⎢- ───────────────────────────── - ───────────────────────────── - ───────────
⎢ 2 2
⎣ σ σ
2
∂ 2 2 2
η))⋅───(h₃(ξ, η)) ⎛∂ ⎞ ⎛∂ ⎞ ⎛∂ ⎞
2 ⎜──(h₁(ξ, η))⎟ ⎜──(h₂(ξ, η))⎟ ⎜──(h₃(ξ, η))⎟ (z
∂η ⎝∂η ⎠ ⎝∂η ⎠ ⎝∂η ⎠
────────────────── + ─────────────── + ─────────────── + ───────────────, - ──
2 2 2 2
σ σ σ σ
2 2
∂ ∂
₁ - h₁(ξ, η))⋅─────(h₁(ξ, η)) (z₂ - h₂(ξ, η))⋅─────(h₂(ξ, η)) (z₃ - h₃(ξ,
∂ξ ∂η ∂ξ ∂η
───────────────────────────── - ─────────────────────────────── - ────────────
2 2
σ σ
2
∂ ∂ ∂ ∂ ∂
η))⋅─────(h₃(ξ, η)) ──(h₁(ξ, η))⋅──(h₁(ξ, η)) ──(h₂(ξ, η))⋅──(h₂(ξ, η))
∂ξ ∂η ∂η ∂ξ ∂η ∂ξ
─────────────────── + ───────────────────────── + ───────────────────────── +
2 2 2
σ σ σ
2
∂ ∂ ∂
──(h₃(ξ, η))⋅──(h₃(ξ, η)) (z₁ - h₁(ξ, η))⋅─────(h₁(ξ, η)) (z₂ - h₂(ξ, η))
∂η ∂ξ ∂ξ ∂η
─────────────────────────, - ─────────────────────────────── - ───────────────
2 2
σ σ
2 2
∂ ∂ ∂ ∂
⋅─────(h₂(ξ, η)) (z₃ - h₃(ξ, η))⋅─────(h₃(ξ, η)) ──(h₁(ξ, η))⋅──(h₁(ξ, η))
∂ξ ∂η ∂ξ ∂η ∂η ∂ξ
──────────────── - ─────────────────────────────── + ─────────────────────────
2 2 2
σ σ σ
∂
∂ ∂ ∂ ∂ (z₁ - h₁(ξ, η))⋅──
──(h₂(ξ, η))⋅──(h₂(ξ, η)) ──(h₃(ξ, η))⋅──(h₃(ξ, η))
∂η ∂ξ ∂η ∂ξ ∂ξ
+ ───────────────────────── + ─────────────────────────, - ──────────────────
2 2 2
σ σ σ
2 2 2
∂ ∂
─(h₁(ξ, η)) (z₂ - h₂(ξ, η))⋅───(h₂(ξ, η)) (z₃ - h₃(ξ, η))⋅───(h₃(ξ, η))
2 2 2
∂ξ ∂ξ
─────────── - ───────────────────────────── - ───────────────────────────── +
2 2
σ σ
⎤
2 2 2⎥
⎛∂ ⎞ ⎛∂ ⎞ ⎛∂ ⎞ ⎥
⎜──(h₁(ξ, η))⎟ ⎜──(h₂(ξ, η))⎟ ⎜──(h₃(ξ, η))⎟ ⎥
⎝∂ξ ⎠ ⎝∂ξ ⎠ ⎝∂ξ ⎠ ⎥
─────────────── + ─────────────── + ───────────────⎥
2 2 2 ⎥
σ σ σ ⎦
有一个答案 ,它使用 hessian
和一个单行 jacobian
函数。
情况如下:我有一个符号函数 lamb,它是变量 z 的元素和变量 h 的函数元素的函数。这是 lamb 符号函数的图像
现在我想计算这个函数关于变量 eta 和 xi 的梯度和 Hessian。当然,我用谷歌搜索了它,但我找不到直接的方法来做到这一点。我发现的是 here,但正如我所说,这并不是解决这种情况的最佳方法。任何的想法? 贝娄,源代码。谢谢
from sympy import Symbol, Matrix, Function, simplify
eta = Symbol('eta')
xi = Symbol('xi')
x = Matrix([[xi],[eta]])
h = [Function('h_'+str(i+1))(x[0],x[1]) for i in range(3)]
z = [Symbol('z_'+str(i+1)) for i in range(3)]
lamb = 0
for i in range(3):
lamb += 1/(2*sigma**2)*(z[i]-h[i])**2
simplify(lamb)
你可以简单地计算梯度向量"manually"(假设变量的顺序是(z1, z2, z3, eta)
):
[lamb.diff(x) for x in z+[eta]]
同理,对于Hessian矩阵:
[[lamb.diff(x).diff(y) for x in z+[eta]] for y in z+[eta]]
您可以使用 Stelios 建议的非常 Pythonic 的方式,或者使用 SymPy 最近添加的一些功能:
In [14]: from sympy.tensor.array import derive_by_array
In [15]: derive_by_array(lamb, (eta, xi))
Out[15]:
[-(z_1 - h_1(xi, eta))*Derivative(h_1(xi, eta), eta)/sigma**2 - (z_2 - h_2(xi,
eta))*Derivative(h_2(xi, eta), eta)/sigma**2 - (z_3 - h_3(xi, eta))*Derivativ
e(h_3(xi, eta), eta)/sigma**2, -(z_1 - h_1(xi, eta))*Derivative(h_1(xi, eta),
xi)/sigma**2 - (z_2 - h_2(xi, eta))*Derivative(h_2(xi, eta), xi)/sigma**2 - (z
_3 - h_3(xi, eta))*Derivative(h_3(xi, eta), xi)/sigma**2]
不幸的是,打印机仍然缺少 N-dim 数组,您可以通过将它们转换为列表来可视化(或者,使用 .tomatrix()):
In [16]: list(derive_by_array(lamb, (eta, xi)))
Out[16]:
⎡ ∂ ∂
⎢ (z₁ - h₁(ξ, η))⋅──(h₁(ξ, η)) (z₂ - h₂(ξ, η))⋅──(h₂(ξ, η)) (z₃ - h₃(ξ, η
⎢ ∂η ∂η
⎢- ──────────────────────────── - ──────────────────────────── - ─────────────
⎢ 2 2
⎣ σ σ
∂ ∂ ∂
))⋅──(h₃(ξ, η)) (z₁ - h₁(ξ, η))⋅──(h₁(ξ, η)) (z₂ - h₂(ξ, η))⋅──(h₂(ξ, η))
∂η ∂ξ ∂ξ
───────────────, - ──────────────────────────── - ────────────────────────────
2 2 2
σ σ σ
∂ ⎤
(z₃ - h₃(ξ, η))⋅──(h₃(ξ, η))⎥
∂ξ ⎥
- ────────────────────────────⎥
2 ⎥
σ ⎦
对于 Hessian,只需重复该过程两次:
In [18]: list(derive_by_array(derive_by_array(lamb, (eta, xi)), (eta, xi)))
Out[18]:
⎡ 2 2
⎢ ∂ ∂
⎢ (z₁ - h₁(ξ, η))⋅───(h₁(ξ, η)) (z₂ - h₂(ξ, η))⋅───(h₂(ξ, η)) (z₃ - h₃(ξ,
⎢ 2 2
⎢ ∂η ∂η
⎢- ───────────────────────────── - ───────────────────────────── - ───────────
⎢ 2 2
⎣ σ σ
2
∂ 2 2 2
η))⋅───(h₃(ξ, η)) ⎛∂ ⎞ ⎛∂ ⎞ ⎛∂ ⎞
2 ⎜──(h₁(ξ, η))⎟ ⎜──(h₂(ξ, η))⎟ ⎜──(h₃(ξ, η))⎟ (z
∂η ⎝∂η ⎠ ⎝∂η ⎠ ⎝∂η ⎠
────────────────── + ─────────────── + ─────────────── + ───────────────, - ──
2 2 2 2
σ σ σ σ
2 2
∂ ∂
₁ - h₁(ξ, η))⋅─────(h₁(ξ, η)) (z₂ - h₂(ξ, η))⋅─────(h₂(ξ, η)) (z₃ - h₃(ξ,
∂ξ ∂η ∂ξ ∂η
───────────────────────────── - ─────────────────────────────── - ────────────
2 2
σ σ
2
∂ ∂ ∂ ∂ ∂
η))⋅─────(h₃(ξ, η)) ──(h₁(ξ, η))⋅──(h₁(ξ, η)) ──(h₂(ξ, η))⋅──(h₂(ξ, η))
∂ξ ∂η ∂η ∂ξ ∂η ∂ξ
─────────────────── + ───────────────────────── + ───────────────────────── +
2 2 2
σ σ σ
2
∂ ∂ ∂
──(h₃(ξ, η))⋅──(h₃(ξ, η)) (z₁ - h₁(ξ, η))⋅─────(h₁(ξ, η)) (z₂ - h₂(ξ, η))
∂η ∂ξ ∂ξ ∂η
─────────────────────────, - ─────────────────────────────── - ───────────────
2 2
σ σ
2 2
∂ ∂ ∂ ∂
⋅─────(h₂(ξ, η)) (z₃ - h₃(ξ, η))⋅─────(h₃(ξ, η)) ──(h₁(ξ, η))⋅──(h₁(ξ, η))
∂ξ ∂η ∂ξ ∂η ∂η ∂ξ
──────────────── - ─────────────────────────────── + ─────────────────────────
2 2 2
σ σ σ
∂
∂ ∂ ∂ ∂ (z₁ - h₁(ξ, η))⋅──
──(h₂(ξ, η))⋅──(h₂(ξ, η)) ──(h₃(ξ, η))⋅──(h₃(ξ, η))
∂η ∂ξ ∂η ∂ξ ∂ξ
+ ───────────────────────── + ─────────────────────────, - ──────────────────
2 2 2
σ σ σ
2 2 2
∂ ∂
─(h₁(ξ, η)) (z₂ - h₂(ξ, η))⋅───(h₂(ξ, η)) (z₃ - h₃(ξ, η))⋅───(h₃(ξ, η))
2 2 2
∂ξ ∂ξ
─────────── - ───────────────────────────── - ───────────────────────────── +
2 2
σ σ
⎤
2 2 2⎥
⎛∂ ⎞ ⎛∂ ⎞ ⎛∂ ⎞ ⎥
⎜──(h₁(ξ, η))⎟ ⎜──(h₂(ξ, η))⎟ ⎜──(h₃(ξ, η))⎟ ⎥
⎝∂ξ ⎠ ⎝∂ξ ⎠ ⎝∂ξ ⎠ ⎥
─────────────── + ─────────────── + ───────────────⎥
2 2 2 ⎥
σ σ σ ⎦
有一个答案 hessian
和一个单行 jacobian
函数。