我有十个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,我该怎么办?
答案 0 :(得分:1)
这是由于实施。限制步骤是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版本应该解决这个问题),或者在这种情况下效率低下...尝试使用{{直接更改为BLAS接口3}},但这仅适用于二维矩阵。实际上已经提出了这些问题(matmul较慢)scipy implementation。
最重要的是,将其非矢量化,或尝试使用其他实现。有时,矩阵乘法的最快方法是使用eigen
函数,但我从未在多维问题中尝试过。