Python SciPy/numpy:仅保留稀疏矩阵块的最大值

Python SciPy/numpy:仅保留稀疏矩阵块的最大值,python,numpy,scipy,Python,Numpy,Scipy,我尝试在一个大型稀疏矩阵上操作,目前为12000 x 12000。 我想做的是将它的块设置为零,但将最大值保持在这个块内。 我已经有了一个针对密集矩阵的运行解决方案: import numpy as np from scipy.sparse import random np.set_printoptions(precision=2) #x = random(10,10,density=0.5) x = np.random.random((10,10)) x = x.T * x print(x)

我尝试在一个大型稀疏矩阵上操作,目前为12000 x 12000。 我想做的是将它的块设置为零,但将最大值保持在这个块内。 我已经有了一个针对密集矩阵的运行解决方案:

import numpy as np
from scipy.sparse import random

np.set_printoptions(precision=2)
#x = random(10,10,density=0.5)
x = np.random.random((10,10))
x = x.T * x
print(x)

def keep_only_max(a,b,c,d):
  sub = x[a:b,c:d]
  z = np.max(sub)
  sub[sub < z] = 0


sizes = np.asarray([0,1,5,4])
sizes_sum = np.cumsum(sizes)

for i in range(1,len(sizes)):
  current_i_min = sizes_sum[i-1]
  current_i_max = sizes_sum[i]
  for j in range(1,len(sizes)):
    if i >= j:
      continue
    current_j_min = sizes_sum[j-1]
    current_j_max = sizes_sum[j]

    keep_only_max(current_i_min, current_i_max, current_j_min, current_j_max)
    keep_only_max(current_j_min, current_j_max, current_i_min, current_i_max)

print(x)
但是,这对稀疏矩阵不起作用。请尝试取消顶部行的注释。 你知道我如何在不调用todense的情况下有效地实现这一点吗

def keep_only_max(a,b,c,d):
  sub = x[a:b,c:d]
  z = np.max(sub)
  sub[sub < z] = 0
对于稀疏x,子切片适用于csr格式。它不会像等效的密集切片那样快,但它会创建x部分的副本

我必须检查稀疏最大值函数。但我可以想象将sub转换为coo格式,在.data属性上使用np.argmax,并使用相应的行和列值,构造一个形状相同但只有一个非零值的新矩阵

如果你的块以规则的、不重叠的方式覆盖了x,我建议用sparse.bmat构造一个新的矩阵。这基本上收集所有组件的coo属性,将它们连接到一组具有适当偏移量的数组中,并生成一个新的coo矩阵

如果块分散或重叠,则可能必须生成,并将它们逐个插入x。csr格式应该适用于这一点,但它将发出稀疏的效率警告。lil应该能够更快地更改值。我想它可以接受区块


我可以想象使用稀疏矩阵执行此操作,但设置测试用例和调试过程需要时间。

多亏了hpaulj,我成功地使用scipy.sparse.bmat实现了一个解决方案:

从scipy.sparse导入coo_矩阵 从scipy.sparse导入csr_矩阵 从scipy.sparse导入rand 从scipy.sparse导入bmat 将numpy作为np导入 np.set_打印选项精度=2 我的矩阵是对称的,所以生成随机对称矩阵 x=rand10,10,密度=0.4 x=x.T*x x=x def仅保留最大值A、b、c、d: sub=x[a:b,c:d] z=np.Unlavel_indexsub.argmax,sub.shape i1=z[0] j1=z[1] 新=csr_矩阵[sub[i1,j1],[i1],[j1],形状=b-a,d-c 还新 def保持所有A、b、c、d: 返回x[a:b,c:d]。复制 我们想要创建一个棋盘图案,其中第一个中心块是1x1,第二个是5x5,最后一个是4x4 尺寸=np.asarray[0,1,5,4] 尺寸总和=np.cumsumsizes 获取2D阵列以存储我们的棋盘区块 r=范围-1 块=[[0代表r中的x]代表r中的y] 对于范围1中的i,透镜尺寸: 当前最小值=大小和[i-1] 当前_i_max=大小_和[i] 对于范围i中的j,透镜尺寸: 当前_j_min=大小_和[j-1] 当前_j_max=大小_和[j] 如果i==j: 将挡块完全保持在对角线上 sub=保持所有当前值最小值、当前值最大值、当前值最小值、当前值最大值 区块[i-1][j-1]=子区块 其他: 不在数字上的块只保留其最大值 当前_j_min=大小_和[j-1] 当前_j_max=大小_和[j] 我们可以利用矩阵对称性,只计算一个新矩阵。 m1=仅保持最大值、当前值、最大值、当前值、最小值、最大值 m2=m1.T 区块[i-1][j-1]=m1 区块[j-1][i-1]=m2 z=bmatblocks 托登斯印刷厂
这些块实际上是不重叠的,因为我或多或少创建了一个棋盘模式,其中每个单元格只保留其最大值。