![](/img/trans.png)
[英]Difference in numpy and sympy lambdify results for basic optimization
[英]sympy lambdify with sympy matrix and numpy vector inputs
我想用 sympy 计算一个符号梯度,例如,
import sympy as sym
x, y, z = sym.symbols("x y z", real=True)
T = sym.cos(x**2+y**2)
gradT = sym.Matrix([sym.diff(T, x), sym.diff(T,y), sym.diff(T,z)])
现在我想用这个表达式创建一个 lamddify 函数:
func = lambdify((x,y,z), gradT,'numpy')
要使用我有的功能:
gradT_exact = func(np.linspace(0,2,100), np.linspace(0,2,100), np.linspace(0,2,100))
我收到以下错误:
<lambdifygenerated-3>:2: VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray.
return (array([[-2*x*sin(x**2 + y**2)], [-2*y*sin(x**2 + y**2)], [0]]))
如果我将 T 更改为 x,y,z 的函数,它不会给我带来任何问题......当 T 仅取决于 x 和 y 并且 z 设置为零时,为什么它会发出警告。
提前致谢!
gradT
表达式:
In [84]: gradT
Out[84]:
⎡ ⎛ 2 2⎞⎤
⎢-2⋅x⋅sin⎝x + y ⎠⎥
⎢ ⎥
⎢ ⎛ 2 2⎞⎥
⎢-2⋅y⋅sin⎝x + y ⎠⎥
⎢ ⎥
⎣ 0 ⎦
并将其转换为numpy
:
In [87]: print(func.__doc__)
Created with lambdify. Signature:
func(x, y, z)
Expression:
Matrix([[-2*x*sin(x**2 + y**2)], [-2*y*sin(x**2 + y**2)], [0]])
Source code:
def _lambdifygenerated(x, y, z):
return (array([[-2*x*sin(x**2 + y**2)], [-2*y*sin(x**2 + y**2)], [0]]))
如果x
和y
是数组,则 2 项将反映它们的维度,但最后一项是[0]
。 这就是为什么你的ragged
警告。
lambdify
做了一个相当简单的词法翻译。 它没有实现对numpy
数组的任何深入理解。 在某种程度上,您有责任检查 numpy 代码是否合理。
使用标量输入:
In [88]: func(1,2,3)
Out[88]:
array([[1.91784855],
[3.8356971 ],
[0. ]])
但如果一个输入是一个数组:
In [90]: func(np.array([1,2]),2,3)
<lambdifygenerated-1>:2: VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray.
return (array([[-2*x*sin(x**2 + y**2)], [-2*y*sin(x**2 + y**2)], [0]]))
Out[90]:
array([[array([ 1.91784855, -3.95743299])],
[array([ 3.8356971 , -3.95743299])],
[0]], dtype=object)
结果是包含 2 个数组和[0]
列表的对象 dtype。
为了避免这个问题, lambdify
必须产生一个函数,如:
In [95]: def f(x,y,z):
...: temp = 0*x*y
...: return np.array([-2*x*np.sin(x**2 + y**2), -2*y*np.sin(x**2 + y**2)
...: , temp])
其中temp
旨在给出0
值,但其形状反映了其他项中x
和y
上的广播操作。 我认为这对lambdify
要求过高。
In [96]:
In [96]: f(np.array([1,2]),2,3)
Out[96]:
array([[ 1.91784855, -3.95743299],
[ 3.8356971 , -3.95743299],
[ 0. , 0. ]])
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.