Wil*_*uks 16 python performance numpy scipy sparse-matrix
我正在努力实现以下等式:
X =(Y.T * Y + Y.T * C * Y) ^ -1
Run Code Online (Sandbox Code Playgroud)
Y是(nxf)矩阵,C是(nxn)对角线; n约为300k,f在100到200之间变化.作为优化过程的一部分,这个等式将使用近1亿次,因此必须非常快速地处理.
Y是随机初始化的,C是一个非常稀疏的矩阵,对角线上300k中只有少数数字与0不同.由于Numpy的对角线函数创建了密集矩阵,我创建了C作为稀疏csr矩阵.但是当试图解决方程式的第一部分时:
r = dot(C, Y)
Run Code Online (Sandbox Code Playgroud)
由于内存限制,计算机崩溃.我决定然后尝试将Y转换为csr_matrix并进行相同的操作:
r = dot(C, Ysparse)
Run Code Online (Sandbox Code Playgroud)
这种方法耗时1.38毫秒.但是这个解决方案有点"棘手",因为我使用稀疏矩阵来存储密集的矩阵,我想知道它真的有多高效.
所以我的问题是,是否有一些方法可以将稀疏的C和密集的Y相乘,而不必将Y变为稀疏并提高性能?如果不知何故C可以表示为对角线密集而不消耗大量内存,这可能会导致非常有效的性能,但我不知道这是否可行.
我感谢您的帮助!
M.H*_*.H. 24
当计算r = dot(C,Y)时,点积运行到内存问题的原因是因为numpy的点函数不具有处理稀疏矩阵的本机支持.正在发生的是numpy认为稀疏矩阵C是一个python对象,而不是一个numpy数组.如果您进行小规模检查,您可以直接看到问题:
>>> from numpy import dot, array
>>> from scipy import sparse
>>> Y = array([[1,2],[3,4]])
>>> C = sparse.csr_matrix(array([[1,0], [0,2]]))
>>> dot(C,Y)
array([[ (0, 0) 1
(1, 1) 2, (0, 0) 2
(1, 1) 4],
[ (0, 0) 3
(1, 1) 6, (0, 0) 4
(1, 1) 8]], dtype=object)
Run Code Online (Sandbox Code Playgroud)
显然,上述内容并不是您感兴趣的结果.相反,您要做的是使用scipy的sparse.csr_matrix.dot函数进行计算:
r = sparse.csr_matrix.dot(C, Y)
Run Code Online (Sandbox Code Playgroud)
或者更紧凑
r = C.dot(Y)
Run Code Online (Sandbox Code Playgroud)
尝试:
import numpy as np
from scipy import sparse
f = 100
n = 300000
Y = np.random.rand(n, f)
Cdiag = np.random.rand(n) # diagonal of C
Cdiag[np.random.rand(n) < 0.99] = 0
# Compute Y.T * C * Y, skipping zero elements
mask = np.flatnonzero(Cdiag)
Cskip = Cdiag[mask]
def ytcy_fast(Y):
Yskip = Y[mask,:]
CY = Cskip[:,None] * Yskip # broadcasting
return Yskip.T.dot(CY)
%timeit ytcy_fast(Y)
# For comparison: all-sparse matrices
C_sparse = sparse.spdiags([Cdiag], [0], n, n)
Y_sparse = sparse.csr_matrix(Y)
%timeit Y_sparse.T.dot(C_sparse * Y_sparse)
Run Code Online (Sandbox Code Playgroud)
我的时间:
In [59]: %timeit ytcy_fast(Y)
100 loops, best of 3: 16.1 ms per loop
In [18]: %timeit Y_sparse.T.dot(C_sparse * Y_sparse)
1 loops, best of 3: 282 ms per loop
Run Code Online (Sandbox Code Playgroud)