我有十个6000 x 784
矩阵。如果我运行np.cov,然后对它们每个进行pinv,则总时间为:
%timeit for n in range(10): pinv(np.cov(A,rowvar = False))
1.64 s ± 78.6 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
如果我改为循环np.cov并计算3D堆栈的pinv,则会得到:
%timeit for n in range(10): dd[n] = np.cov(A,rowvar = False)
485 ms ± 18 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit pinv(dd)
4.59 s ± 369 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
为什么3D上的pinv这么慢?
如何计算堆栈的np.cov和相应的pinv?
最佳答案
这是由于实施。限制步骤是numpy matmul
。首先,我认为SVD是限制步骤,但它线性扩展(每次迭代〜130 ms,十个包为1.3 s)。
以下是分析的某些部分:
1个通话(您的第一个摘录)
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.131 0.131 0.131 0.131 linalg.py:1299(svd)
1 0.011 0.011 0.011 0.011 {built-in method numpy.core.multiarray.matmul}
1 0.003 0.003 0.144 0.144 <ipython-input-76-2a63f1c84429>:1(pinv)
一包10包(第二段)
ncalls tottime percall cumtime percall filename:lineno(function)
1 2.952 2.952 2.952 2.952 {built-in method numpy.core.multiarray.matmul}
1 1.265 1.265 1.265 1.265 linalg.py:1299(svd)
1 0.026 0.026 4.266 4.266 <ipython-input-76-2a63f1c84429>:1(pinv)
也许存在C排序的内部问题(但是最近的numpy版本应该解决这个问题),或者在这种情况下效率低下...尝试过尝试使用scipy implementation直接更改为BLAS接口,但是这仅适用于二维矩阵。这些问题(matmul较慢)实际上已提出elsewhere。
最重要的是,将其非矢量化,或尝试使用其他实现。有时,矩阵乘法的最快方法是使用
eigen
函数,但是我从未在多维问题中尝试过。关于python - 为什么矢量化Pinv慢于未矢量化?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/55084206/