我有一个 lambdify
d sympy 函数,其中包含一个 dot
产品,例如,
import numpy as np
import sympy
class dot(sympy.Function):
pass
x = sympy.Symbol('x')
a = sympy.Matrix([1, 1, 1])
f = dot(x, a)
ff = sympy.lambdify((x), f, modules='numpy')
x = np.random.rand(3)
print(ff(x)) # okay
(奇怪的是,自定义
dot
声明有效。不知道确切原因,但不要介意。如果有更好的解决方案,请告诉我。)我现在想一次用一堆向量调用
ff
,所以我去了x = np.random.rand(3, 10)
print(ff(x))
不好!
ValueError: shapes (3,10) and (3,1) not aligned: 10 (dim 1) != 3 (dim 0)
好的,所以我必须以某种方式转置
dot
的第一个参数。但是在 .T
上使用旧的 sympy.Symbol('x')
是不合法的。关于如何从 lambdified sympy 表达式中进行大量点积的任何提示?
最佳答案
您正在做许多奇怪的事情,但我不知道其中有多少是由于过于简化的 MCVE。
首先,对您的函数进行更优雅的定义:
import sympy as sym
x = sym.Symbol('x')
a = sym.Matrix([1, 1, 1])
dot = sym.Function('dot')
f = dot(x, a)
ff = sym.lambdify(x, f, modules='numpy')
这个和你原来的 kludge 工作的原因是因为你所要做的就是拥有一些写着“
dot
”的东西。一旦你有了它,lambdify
将用 np.dot
替换你符号的那部分。现在,为了完整起见,我会这样做:
import numpy as np
a = np.array([[1],[1],[1]])
ff = lambda x,a=a: np.dot(x,a)
我知道在您的实际问题中这可能不是一个选项,但我的经验是,如果可以在没有符号数学的情况下完成某些事情,那么这样做是值得的。
现在,对于你的错误。错误很明显,数学也很清楚。您定义了一个函数,该函数对于任何输入
x
使用 3d 列向量 x*a
计算 a
。正如错误所暗示的那样,这在极少数情况下是有意义的。如果两个操作数都是 3 元素一维数组,这将是有意义的,在这种情况下,将返回标量积。但是,由于您的操作数之一固定为形状 (3,1)
,因此 np.dot
仅执行矩阵乘法(对于向量输入,返回 1 元素的 1d 数组而不是标量)。根据您的定义,它仅适用于可以从右侧乘以 a
的矩阵,即形状为 (N,3)
的矩阵。显然,您的输入并非如此。你应该做的是在数字方面转置
x
:x = np.random.rand(3,10)
print(ff(x.T))
这将在函数中输入一个形状为
(10,3)
的数组,然后将其乘以一个形状 (3,1)
,从而产生一个 (10,1)
形状的二维数组:一个列向量,如果给定的输入向量带有 a
,则每行包含标量积。另一种选择是交换函数的定义:
f = dot(a.T,x)
ff = sym.lambdify(x, f, modules='numpy')
# or
a = np.array(1,1,1) # transpose of previous a
ff = lambda x,a=a: np.dot(a,x)
两者都将创建一个函数,将右侧的
(1,3)
形状数组与输入相乘。那么你输入的 x
形状 (3,10)
是直接兼容的;输出将是 10 个标量乘积的一维数组。在这个公式中你
关于python - SymPy:带有 (3,n)-array 的lambdified dot(),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/38269304/