web-dev-qa-db-ja.com

scipy.sparse行列を連結する効率的な方法はありますか?

私はいくつかのかなり大きいスパース行列(5000x5000から20000x20000)を使用していて、別々の部分から確率的行列を構築するために、柔軟な方法で行列を連結する効率的な方法を見つける必要があります。

現在、私は次の方法を使用して4つの行列を連結していますが、それは恐ろしく非効率的です。密な行列への変換を含まない、これを行うより良い方法はありますか?

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()
34
jones

スパースライブラリには、行列を水平方向と垂直方向にそれぞれ連結するための hstackvstack が追加されました。

49
Erik

さて、私は答えを見つけました。 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]) )
14
jones

アモスの答えはもはや必要ありません。入力行列がcsrまたはcsc形式であり、目的の出力形式がnoneまたは入力行列と同じ形式に設定されている場合、Scipyは内部でこれと同様のことを行います。それぞれscipy.sparse.vstackまたはscipy.sparse.hstackを使用して、行列をcsr形式で垂直にスタックするか、csc形式で水平にスタックするのが効率的です。

13
Joel Croteau

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