我有一个lambdified的sympy函数,其中包含一个点积,例如
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
(奇怪的是,自定义点声明有效.不知道为什么会这样,但请不要介意.如果有更好的解决方案,请告诉我.)
我现在想一次用一堆向量调用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的第一个参数.在sympy.Symbol(‘x’)上使用旧的.T是不合法的.
关于如何从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')
之所以如此,是因为您最初要做的事情是因为您所要做的就是拥有一个说“点”的东西.一旦有了它,lambdify就会将np.dot替换为符号的该部分.
现在,为了完整起见,这是我应该做的事情:
import numpy as np
a = np.array([[1],[1],[1]])
ff = lambda x,a=a: np.dot(x,a)
我知道这可能不是您实际问题中的选择,但是我的经验是,如果可以在没有符号数学的情况下完成某些工作,那么这样做是值得的.
现在,为您的错误.错误很明显,数学也很清楚.您定义了一个函数,该函数对于任何输入x都会使用3d列向量a计算x * a.正如错误所暗示的,这在非常有限的情况下是有意义的.如果两个操作数都是3元素1d数组,则将是有意义的,在这种情况下,将返回标量积.但是,由于您的一个操作数固定为形状(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)的2d数组:列向量,每行包含如果给定输入向量带有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)与输入相乘.然后,您输入的形状为(3,10)的x是直接兼容的;输出将是10个标量积的一维数组.
在这个公式中