优化包含大型矩阵运算的函数

时间:2016-06-28 04:52:31

标签: python numpy linear-algebra theano sympy

我可能很难解释这个,所以我会使用一个与我的问题有点相似的例子,但是这里有:

我需要计算一个复杂的操作(重复),它只是几个标量的函数,比如x1,x2和x3。然后计算一个矩阵,其元素由x1,x2,x3(以及行和列位置)的函数确定,称为X.

在中间步骤A,B和C中涉及几种非常大的基质产物。这些产物中涉及的基质值是恒定的。

假设我们的矩阵大小为:

  • A:k by n
  • B:n by n
  • C:n by k
  • X:3 by k

其中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中调用。

2 个答案:

答案 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)