我想出了一个更快的coo对角线:
msk = M.row==M.col
D1 = sparse.coo_matrix((M.data[msk],(M.row[msk],M.col[msk])),shape=M.shape)
sparse.tril 将此方法与mask = A.row + k >= A.col (sparse/extract.py) 一起使用
有时是 (100,100) M(和 M1 = M.tocsr())
In [303]: timeit msk=M.row==M.col; D1=sparse.coo_matrix((M.data[msk],(M.row[msk],M.col[msk])),shape=M.shape)
10000 loops, best of 3: 115 µs per loop
In [305]: timeit D=sparse.diags(M.diagonal(),0)
1000 loops, best of 3: 358 µs per loop
所以coo 获得对角线的方式很快,至少对于这个小而非常稀疏的矩阵(对角线只有 1 次)
如果我从csr 表单开始,diags 会更快。那是因为.diagonal 以csr 格式工作:
In [306]: timeit D=sparse.diags(M1.diagonal(),0)
10000 loops, best of 3: 176 µs per loop
但创建D 只是整体计算的一小部分。同样,使用M1 更快。总和以csr 格式完成。
In [307]: timeit M+M.T-D
1000 loops, best of 3: 1.35 ms per loop
In [308]: timeit M1+M1.T-D
1000 loops, best of 3: 1.11 ms per loop
另一种方法是利用coo 允许重复的i,j 值这一事实,这些值将在转换为csr 格式时相加。因此,您可以将M 的row, col, data 数组与M.T 的数组堆叠在一起(请参阅M.transpose 了解它们的构造方式),以及D 的掩码值。 (或者可以从M 或M.T 中删除被屏蔽的对角线)
例如:
def MplusMT(M):
msk=M.row!=M.col;
data=np.concatenate([M.data, M.data[msk]])
rows=np.concatenate([M.row, M.col[msk]])
cols=np.concatenate([M.col, M.row[msk]])
MM=sparse.coo_matrix((data, (rows, cols)), shape=M.shape)
return MM
# alt version with a more explicit D
# msk=M.row==M.col;
# data=np.concatenate([M.data, M.data,-M.data[msk]])
MplusMT 写的非常快,因为它只是进行数组连接,而不是求和。为此,我们必须将其转换为 csr 矩阵。
MplusMT(M).tocsr()
这需要相当长的时间。在我有限的测试中,这种方法仍然比M+M.T-D 快 2 倍以上。因此它是构建复杂稀疏矩阵的潜在工具。