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

问题描述 投票:0回答:5

我正在处理一些相当大的稀疏矩阵(从 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()
python concatenation scipy sparse-matrix
5个回答
55
投票

稀疏库现在有

hstack
vstack
分别用于水平和垂直连接矩阵。


17
投票

阿莫斯的回答已经不再必要了。如果输入矩阵采用 csr 或 csc 格式,并且所需的输出格式设置为无或与输入矩阵相同的格式,Scipy 现在会在内部执行类似的操作。分别使用

scipy.sparse.vstack
scipy.sparse.hstack
垂直堆叠 csr 格式的矩阵或水平堆叠 csc 格式的矩阵非常高效。


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))

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]) )

0
投票

Amos 的解决方案仅适用于两个矩阵,如果其中一个没有条目,则会失败,这在我的用例中很常见。此版本没有这些限制:

def concatenate_sparse_csc_matrices(list_of_matrices):
    num_rows = list_of_matrices[0].shape[0]
    num_cols = sum(m.shape[1] for m in list_of_matrices)

    data = []
    indices = []
    indptr_diff = [[0]]

    for m in list_of_matrices:
        if m.nnz > 0:
            data.append(m.data)
            indices.append(m.indices)
            indptr_diff.append(np.diff(m.indptr))
        else:
            indptr_diff.append([0] * m.shape[1])

    if data:
        data = np.concatenate(data)

    if indices:
        indices = np.concatenate(indices)

    indptr = np.cumsum(np.concatenate(indptr_diff))
    concatenated_matrix = csc_matrix((data, indices, indptr), shape=(num_rows, num_cols))

    return concatenated_matrix
© www.soinside.com 2019 - 2024. All rights reserved.