高效创建掩码 - Numpy / Python

时间:2017-11-10 05:46:09

标签: python performance numpy

假设我有一个NumPy数组,其形状(50,10000,10000)具有1000个不同的“簇”。例如,只有1s的小音量,2s的另一个小音量等等。我想迭代每个簇来创建一个像这样的掩码:

for i in np.unique(arr)[1:]:
    mask = arr == i
    #do other stuff with mask

创建每个掩码大约需要15秒,迭代1000个集群需要4个多小时。有没有一种方法可以加速代码,或者这是最好的,因为没有避免迭代遍历数组的每个元素?

编辑:数组的dtype是uint16

1 个答案:

答案 0 :(得分:1)

我假设arr稀疏:

  • 你说群集很小,1000个群集不会平铺大数
  • 的数组
  • 你迭代np.unique(arr)[1:],所以我假设第一个唯一值为0

在这种情况下,我建议利用scipy.sparse.csr_matrix

from scipy.sparse import csr_matrix
sp_arr = csr_matrix(arr.reshape(1,-1))

这会将您的大密集数组转换为单行压缩稀疏行数组。由于稀疏数组不喜欢2个以上的维度,因此使用了ravelled索引。现在sp_arrdata(群集标签),indices(被碾压的索引)和indptr(这里很简单,因为我们只有一行)。所以,

for i in np.unique(sp_arr.data):  # as a bonus this `unique` call should be faster too
    x, y, z = np.unravel_index(sp_arr.indices[sp_arr.data == i], arr.shape)

应该更有效地给出等效坐标

for i in np.unique(arr)[:1]:
    x, y, z = np.nonzero(arr == i)

其中x, y, zTruemask值的索引。从那里你可以重建mask或处理索引(推荐)。

您也可以使用numpy完全执行此操作,并且最后仍然有一个布尔掩码,但内存效率会降低一点:

all_mask = arr != 0    # points assigned to any cluster
data = arr[all_mask]   # all cluster labels
for i in np.unique(data):
    mask = all_mask.copy()
    mask[mask] = data == i  # now mask is same as before