我可能很难解释这个,所以我会使用一个与我的问题有点相似的例子,但是这里有:
我需要计算一个复杂的操作(重复),它只是几个标量的函数,比如x1,x2和x3。然后计算一个矩阵,其元素由x1,x2,x3(以及行和列位置)的函数确定,称为X.
在中间步骤A,B和C中涉及几种非常大的基质产物。这些产物中涉及的基质值是恒定的。
假设我们的矩阵大小为:
其中n非常大,k非常大。
该函数执行(伪代码):
func = function(x1, x2, x3)
X = make_X(x1, x2, x3)
return X * A * B * C * X^t
其中*是常规点积。输出只是一个3乘3的矩阵!
我(天真地可能)认为必须有一些自动的方法来有效地将其编译成x1,x2,x3的基本上9个函数 - 输出矩阵的每个元素一个。我经常使用numpy / scipy,但没有使用sympy或theano的经验,尽管他们似乎在球场上。关于如何解决这个问题的任何建议?
P.S。,任何解决这个问题的代码包最好都是python,但它们不一定是,只要它们可以从python中调用。
答案 0 :(得分:1)
用einsum
术语表达问题可能会有所帮助:
np.einsum('ij,jk,kl,lm,nm->in', X, A, B, C, X)
可能会分成两个步骤:
ABC = np.einsum('jk,kl,lm->jm', A, B, C) # k by k
np.einsum('ij,jm,nm->in', X, ABC, X)
所以结果的i,j
元素是:
R[i,j] = np.einsum('j,jm,m->', X[i,:], X[j,:])
并使用新的@
运算符(在这种情况下只是点的运算符版本)
R = X@A@B@C@(X.T)
对于k,n=10,20
,这最后一次是最快的。
如果您针对x1,x2,x3
的不同组合执行此操作,但只有一组A,B,C
,那么执行ABC=A@B@C
应该可以节省时间。但我怀疑将X@ABC@(X.T)
分为9个步骤的价值。 ABC
是kxk,因此您已经完成了涉及B
的较大计算。
答案 1 :(得分:1)
由于您提到了SymPy,您可以使用
轻松计算整个事物x1, x2, x3 = symbols('x1, x2, x3')
X = Matrix(...)
A = Matrix(...)
B = Matrix(...)
C = Matrix(...)
(用实际的矩阵条目替换...
)。然后计算产品
result = X*A*B*C*X.T
然后,您可以在此矩阵上使用lambdify
将其转换为可与numpy或scipy一起使用的数字函数
func = lambdify([x1, x2, x3], result)