我有一个大的稀疏对称矩阵,我需要通过取块和来构造一个新的更小的矩阵来压缩它。
例如,对于4x4稀疏矩阵A,我想要生成一个2x2矩阵B,其中Bi,j= sum(Ai:i+2,j:j+2)。
目前,我只是逐块重新建立压缩矩阵,但这是缓慢的。对如何优化这个问题有什么想法吗?
更新:这里的是一个很好的示例代码,但是对于我想在10.000x10.000中压缩的稀疏矩阵50.000x50.000来说却很慢:
>>> A = (rand(4,4)<0.3)*rand(4,4)
>>> A = scipy.sparse.lil_matrix(A + A.T) # make the matrix symmetric
>>> B = scipy.sparse.lil_matrix((2,2))
>>> for i in range(B.shape[0]):
... for j in range(B.shape[0]):
... B[i,j] = A[i:i+2,j:j+2].sum()发布于 2012-12-20 10:49:02
首先,您正在总结的lil矩阵可能非常糟糕,我会尝试COO或CSR/CSS (我不知道哪一个会更好,但是对于许多这些操作,lil可能天生就比较慢,即使切片也可能要慢得多,尽管我没有测试)。(除非您知道,例如,dia非常适合)
基于COO,我可以想象做一些恶作剧。因为COO有row和col数组来给出确切的位置:
matrix = A.tocoo()
new_row = matrix.row // 5
new_col = matrix.col // 5
bin = (matrix.shape[0] // 5) * new_col + new_row
# Now do a little dance because this is sparse,
# and most of the possible bin should not be in new_row/new_col
# also need to group the bins:
unique, bin = np.unique(bin, return_inverse=True)
sum = np.bincount(bin, weights=matrix.data)
new_col = unique // (matrix.shape[0] // 5)
new_row = unique - new_col * (matrix.shape[0] // 5)
result = scipy.sparse.coo_matrix((sum, (new_row, new_col)))(我不能保证我不会在某个地方混淆行和列,这只适用于方阵.)
发布于 2012-12-19 19:47:21
给定大小为N的平方矩阵和d的分裂大小(因此矩阵将被划分为大小为d的N/d * N/d子矩阵),您是否可以使用numpy.split几次来构建这些子矩阵的集合,每个子矩阵之和,并将它们重新组合起来?
这应该更多地被看作是伪代码,而不是有效的实现,但它表达了我的想法:
def chunk(matrix, size):
row_wise = []
for hchunk in np.split(matrix, size):
row_wise.append(np.split(hchunk, size, 1))
return row_wise
def sum_chunks(chunks):
sum_rows = []
for row in chunks:
sum_rows.append([np.sum(col) for col in row])
return np.array(sum_rows)或者更简约地
def sum_in_place(matrix, size):
return np.array([[np.sum(vchunk) for vchunk in np.split(hchunk, size, 1)]
for hchunk in np.split(matrix, size)])这给您提供了如下内容:
In [16]: a
Out[16]:
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15]])
In [17]: chunk.sum_in_place(a, 2)
Out[17]:
array([[10, 18],
[42, 50]])发布于 2012-12-19 13:19:48
对于4x4示例,可以执行以下操作:
In [43]: a = np.arange(16.).reshape((4, 4))
In [44]: a
Out[44]:
array([[ 0., 1., 2., 3.],
[ 4., 5., 6., 7.],
[ 8., 9., 10., 11.],
[ 12., 13., 14., 15.]])
In [45]: u = np.array([a[:2, :2], a[:2, 2:], a[2:,:2], a[2:, 2:]])
In [46]: u
Out[46]:
array([[[ 0., 1.],
[ 4., 5.]],
[[ 2., 3.],
[ 6., 7.]],
[[ 8., 9.],
[ 12., 13.]],
[[ 10., 11.],
[ 14., 15.]]])
In [47]: u.sum(1).sum(1).reshape(2, 2)
Out[47]:
array([[ 10., 18.],
[ 42., 50.]])使用类似于迭代工具的东西,应该可以自动化和泛化u的表达式。
https://stackoverflow.com/questions/13950670
复制相似问题