首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何从较大稀疏矩阵的块和中高效地生成新矩阵

如何从较大稀疏矩阵的块和中高效地生成新矩阵
EN

Stack Overflow用户
提问于 2012-12-19 10:50:19
回答 3查看 1.3K关注 0票数 3

我有一个大的稀疏对称矩阵,我需要通过取块和来构造一个新的更小的矩阵来压缩它。

例如,对于4x4稀疏矩阵A,我想要生成一个2x2矩阵B,其中Bi,j= sum(Ai:i+2,j:j+2)。

目前,我只是逐块重新建立压缩矩阵,但这是缓慢的。对如何优化这个问题有什么想法吗?

更新:这里的是一个很好的示例代码,但是对于我想在10.000x10.000中压缩的稀疏矩阵50.000x50.000来说却很慢:

代码语言:javascript
复制
>>> 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()
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-12-20 10:49:02

首先,您正在总结的lil矩阵可能非常糟糕,我会尝试COOCSR/CSS (我不知道哪一个会更好,但是对于许多这些操作,lil可能天生就比较慢,即使切片也可能要慢得多,尽管我没有测试)。(除非您知道,例如,dia非常适合)

基于COO,我可以想象做一些恶作剧。因为COOrowcol数组来给出确切的位置:

代码语言:javascript
复制
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)))

(我不能保证我不会在某个地方混淆行和列,这只适用于方阵.)

票数 1
EN

Stack Overflow用户

发布于 2012-12-19 19:47:21

给定大小为N的平方矩阵和d的分裂大小(因此矩阵将被划分为大小为d的N/d * N/d子矩阵),您是否可以使用numpy.split几次来构建这些子矩阵的集合,每个子矩阵之和,并将它们重新组合起来?

这应该更多地被看作是伪代码,而不是有效的实现,但它表达了我的想法:

代码语言:javascript
复制
    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)

或者更简约地

代码语言:javascript
复制
    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)])

这给您提供了如下内容:

代码语言:javascript
复制
    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]])
票数 1
EN

Stack Overflow用户

发布于 2012-12-19 13:19:48

对于4x4示例,可以执行以下操作:

代码语言:javascript
复制
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的表达式。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13950670

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档