有没有一种高效的方法来连接scipy.sparse矩阵?

40

我正在处理一些相当大的稀疏矩阵(从5000x5000到20000x20000),需要找到一种有效的灵活方式来连接矩阵,以便从分离的部分构建随机矩阵。

目前我正在使用以下方法来连接四个矩阵,但效率非常低。有没有更好的方法可以做到这一点,而不涉及转换为密集矩阵?

rmat[0:m1.shape[0],0:m1.shape[1]] = m1
rmat[m1.shape[0]:rmat.shape[0],m1.shape[1]:rmat.shape[1]] = m2
rmat[0:m1.shape[0],m1.shape[1]:rmat.shape[1]] = bridge
rmat[m1.shape[0]:rmat.shape[0],0:m1.shape[1]] = bridge.transpose()
4个回答

55

现在稀疏库有 hstackvstack 分别用于水平和垂直拼接矩阵。


6
请使用scipy.sparse.hstack代替numpy.hstack。 - pettinato
在这个答案中应该补充说明:hstack是将稀疏矩阵按行进行连接(水平连接),而vstack是将稀疏矩阵按列进行连接(垂直连接)。 - Farid Alijani

17

Amos的回答现在已不再必要。如果输入矩阵采用csr或csc格式,且期望的输出格式设置为无格式或与输入矩阵相同的格式,则Scipy现在会在内部执行类似于此操作的操作。使用scipy.sparse.vstack垂直堆叠csr格式的矩阵,或使用scipy.sparse.hstack水平堆叠csc格式的矩阵是高效的。


“现在”指的是哪个版本?你有任何参考资料吗? - lenz
相关代码是 scipy.sparse.bmat 中的 这段代码vstackhstack 都使用它。这个 hack 最初是在 2013 年的 这里 添加的。看起来它最初是包含在 scipy 1.0.0 中的。 - Joel Croteau
1
实际上,我的说法是错误的。它最初包含在0.14版本中。 - Joel Croteau

16

使用hstack、vstack或concatenate,比直接连接内部数据对象要慢得多。原因是hstack/vstack将稀疏矩阵转换为coo格式,当矩阵非常大且不在coo格式时,这个过程可能会非常缓慢。以下是连接csc矩阵的代码,类似的方法也可用于csr矩阵:

def concatenate_csc_matrices_by_columns(matrix1, matrix2):
    new_data = np.concatenate((matrix1.data, matrix2.data))
    new_indices = np.concatenate((matrix1.indices, matrix2.indices))
    new_ind_ptr = matrix2.indptr + len(matrix1.data)
    new_ind_ptr = new_ind_ptr[1:]
    new_ind_ptr = np.concatenate((matrix1.indptr, new_ind_ptr))

    return csc_matrix((new_data, new_indices, new_ind_ptr))

1
刚刚在寻找一种快速的方法来追加新行到CSR矩阵中。这正是我所需要的。感谢@amos。 - singleton
1
如果您使用此方法,则需要在'return csc_matrix((new_data,new_indices,new_ind_ptr))'中指定形状,即:'return csc_matrix((new_data,new_indices,new_ind_ptr),shape =(matrix1.shape [1],matrix1.shape [1] + matrix2.shape [1])'。 - simeon
csr矩阵的代码是什么?原生的scipy实现现在真的更快吗?因为我必须连接四个子矩阵(左上,右上,左下,右下),而且我对结果不满意。重新计算整个矩阵所需的时间比计算右上和左下要少。因此,在我的情况下,这种缓慢基本上使制表无用。这让我很烦恼,因为我认为如果矩阵和操作都得到了最佳实现,那么只需要在C中更改一些指针即可。 - Radio Controlled
虽然我不确定索引指针是在C中存储在列表中还是数组中。如果它是一个列表,你不只需要在列表末尾重置一个指针吗?现在的方式是,矩阵越大,堆栈就越长... - Radio Controlled

14

好的,我找到了答案。使用scipy.sparse.coo_matrix比使用lil_matrix快得多。我将矩阵转换为coo格式(简单且快速),然后只是在添加正确填充后连接数据、行和列。

data = scipy.concatenate((m1S.data,bridgeS.data,bridgeTS.data,m2S.data))
rows = scipy.concatenate((m1S.row,bridgeS.row,bridgeTS.row + m1S.shape[0],m2S.row + m1S.shape[0]))
cols = scipy.concatenate((m1S.col,bridgeS.col+ m1S.shape[1],bridgeTS.col ,m2S.col + m1S.shape[1])) 

scipy.sparse.coo_matrix((data,(rows,cols)),shape=(m1S.shape[0]+m2S.shape[0],m1S.shape[1]+m2S.shape[1]) )

1
感谢您回来并评论了如何快速完成它。我需要它用于我的NLP课程。 - placeybordeaux

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接