Python 高效地将稠密矩阵与稀疏向量相乘

Python 高效地将稠密矩阵与稀疏向量相乘,python,python-2.7,scipy,sparse-matrix,Python,Python 2.7,Scipy,Sparse Matrix,我正在寻找一种有效的方法,将密集矩阵乘以稀疏向量,Av,其中a的大小为(M x N),v的大小为(N x 1)。向量v是一个scipy.sparse.csc_矩阵 我目前使用两种方法: 在方法1中,我选取v中的非零值,比如vi,将vi与A的对应列相乘,然后将这些列相加。所以如果y=Av,那么y=A[:,0]*v0+…+A[:,N]*vN,仅适用于非零i def dense_dot_sparse(dense_matrix, sparse_column): prod = np.zeros((

我正在寻找一种有效的方法,将密集矩阵乘以稀疏向量,
Av
,其中a的大小为(M x N),v的大小为(N x 1)。向量v是一个scipy.sparse.csc_矩阵

我目前使用两种方法:

在方法1中,我选取v中的非零值,比如vi,将vi与A的对应列相乘,然后将这些列相加。所以如果
y=Av
,那么
y=A[:,0]*v0+…+A[:,N]*vN
,仅适用于非零i

def dense_dot_sparse(dense_matrix, sparse_column):
    prod = np.zeros((dense_matrix.shape[0]))
    r, c = sparse_column.nonzero()
    indices = zip(r, c)
    for ind in indices:
        prod = prod + dense_matrix[:, ind[1]] * sparse_column[ind]
    return prod
在方法2中,我通过简单地生成稀疏向量
.todense()
并使用
np.dot()
来执行乘法

A的典型大小为(512 x 2048),v的稀疏度在1到200个非零条目之间变化。我根据v的稀疏性选择使用哪种方法。如果v的稀疏度为~200个非零,则方法1需要~45毫秒,方法2需要~5毫秒。但是当v非常稀疏时,~1非零,那么方法1需要~1ms,而方法2仍然需要5ms。检查v的稀疏性(
.nnz
)会增加将近0.2ms

我必须执行其中大约1500次乘法(在分割数据和多重处理之后),所以时间加起来

[编辑:添加一个简单的代表性示例

rows = 512
cols = 2048
sparsity = 0.001  # very sparse: 0.001 for ~ 1 non-zero, moderately sparse: 0.1 for ~ 200 non-zero
big_matrix = np.random.rand(rows, cols)  # use as dense matrix
col = np.random.rand(cols, 1)
col = np.array([i[0] if i < sparsity else 0.0 for i in col])
sparse_col = csc_matrix(col)  # use as sparse vector
print sparse_col.nnz 
rows=512
cols=2048
稀疏度=0.001#非常稀疏:对于~1个非零,稀疏度为0.001;对于~200个非零,稀疏度为0.1
大矩阵=np.random.rand(行,列)#用作密集矩阵
col=np.random.rand(cols,1)
col=np.array([i[0]如果i
结束编辑]


我正在寻找一个对非常稀疏和中等稀疏v都快速的实现。

一个可运行的示例将有助于检查numpy的索引魔术是否有用。@Dietrich添加了代表我问题的示例代码。
rows = 512
cols = 2048
sparsity = 0.001  # very sparse: 0.001 for ~ 1 non-zero, moderately sparse: 0.1 for ~ 200 non-zero
big_matrix = np.random.rand(rows, cols)  # use as dense matrix
col = np.random.rand(cols, 1)
col = np.array([i[0] if i < sparsity else 0.0 for i in col])
sparse_col = csc_matrix(col)  # use as sparse vector
print sparse_col.nnz