12

我正在尝试执行以下操作,并重复直到收敛:

其中每个 X in x p,并且r它们在一个r x n x p名为 的数组中samplesUn x nVp x p。(我得到了矩阵正态分布的 MLE 。)尺寸都可能很大;我期待的事情至少在 r = 200, n = 1000, p = 1000.

我当前的代码确实

V = np.einsum('aji,jk,akl->il', samples, np.linalg.inv(U) / (r*n), samples)
U = np.einsum('aij,jk,alk->il', samples, np.linalg.inv(V) / (r*p), samples)

这行得通,但当然你永远不应该真正找到逆并乘以它。如果我能以某种方式利用 U 和 V 是对称且正定的这一事实,那也很好。我希望能够在迭代中计算 U 和 V 的 Cholesky 因子,但由于总和,我不知道该怎么做。

我可以通过做类似的事情来避免相反的情况

V = sum(np.dot(x.T, scipy.linalg.solve(A, x)) for x in samples)

(或类似利用 psd 的东西),但是有一个 Python 循环,这让 numpy 仙女哭了。

我还可以想象samples以这样一种方式进行重塑,即我可以获得一个A^-1 xusing solvefor each的数组,x而无需执行 Python 循环,但这会产生一个很大的辅助数组,这会浪费内存。

是否有一些线性代数或 numpy 技巧可以让我充分利用这三者:没有显式逆,没有 Python 循环,没有大的辅助数组?或者我最好的选择是用一种更快的语言实现一个 Python 循环并调用它?(直接将其移植到 Cython 可能会有所帮助,但仍会涉及大量 Python 方法调用;但直接制作相关的 blas/lapack 例程可能不会太麻烦而没有太多麻烦。)

(事实证明,我实际上并不需要矩阵UV最后 - 只是它们的行列式,或者实际上只是他们的 Kronecker 乘积的行列式。因此,如果有人对如何减少工作并仍然获得决定因素,那将不胜感激。)

4

1 回答 1

8

直到有人想出一个更有灵感的答案,如果我是你,我会让仙女哭泣……

r, n, p = 200, 400, 400

X = np.random.rand(r, n, p)
U = np.random.rand(n, n)

In [2]: %timeit np.sum(np.dot(x.T, np.linalg.solve(U, x)) for x in X)
1 loops, best of 3: 9.43 s per loop

In [3]: %timeit np.dot(X[0].T, np.linalg.solve(U, X[0]))
10 loops, best of 3: 45.2 ms per loop

因此,拥有一个 python 循环,并且必须将所有结果汇总在一起,所花费的时间是 390 毫秒,是解决必须解决的 200 个系统中的每一个系统所需时间的 200 倍多。如果循环和求和是免费的,您将获得不到 5% 的改进。也可能有一些调用 python 函数的开销,但对于求解方程的实际时间,它可能仍然可以忽略不计,无论你用什么语言编写它。

于 2013-02-09T01:38:32.033 回答