我试图做以下事情,并重复直到收敛:
其中每个 Xi 都是 n x p
,在一个名为 samples
的 r x n x p
数组中有 r
个。 U
是 n x n
,V
是 p 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
重塑,以便我可以使用solve
为每个x
获取A^-1 x
数组,而无需进行Python循环,但这会产生一个浪费内存的大型辅助数组。
是否有一些线性代数或numpy技巧可以同时实现三个最佳方案:没有显式逆矩阵,没有Python循环,没有大型辅助数组?或者我的最佳选择是用一种更快的语言实现带有Python循环的方法并调用它?(直接将其移植到Cython可能有所帮助,但仍然涉及大量Python方法调用;但也许不需要太麻烦地直接制作相关的blas/lapack例程。)
(事实证明,我实际上不需要最终的矩阵U
和V
——只需要它们的行列式,或者实际上只需要它们的Kronecker积的行列式。因此,如果有人有一个聪明的主意,可以做更少的工作,仍然可以得到行列式,那将不胜感激。)