Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 多维数组中根据索引的元素数和_Python_Arrays_Numpy_Pytorch_Memory Efficient - Fatal编程技术网

Python 多维数组中根据索引的元素数和

Python 多维数组中根据索引的元素数和,python,arrays,numpy,pytorch,memory-efficient,Python,Arrays,Numpy,Pytorch,Memory Efficient,我正在处理一个非常大的多维数据,但让我以二维数组为例。给定一个每次迭代都会更改的值数组 arr = np.array([[ 1, 2, 3, 4, 5], [5, 6, 7, 8, 9]]) # a*b 以及一个始终固定的索引数组 idx = np.array([[[0, 1, 1], [-1, -1, -1]], [[5, 1, 3], [1, -1, -1]]]) # n*h*w, where n = a*b, 这里-1表示不应用索引。我希望得到一个结果

我正在处理一个非常大的多维数据,但让我以二维数组为例。给定一个每次迭代都会更改的值数组

arr = np.array([[ 1, 2, 3, 4, 5], [5, 6, 7, 8, 9]]) # a*b
以及一个始终固定的索引数组

idx = np.array([[[0, 1, 1], [-1, -1, -1]],
                [[5, 1, 3], [1, -1, -1]]]) # n*h*w, where n = a*b,
这里-1表示不应用索引。我希望得到一个结果

res = np.array([[1+2+2, 0],
                [5+2+4, 2]]) # h*w
在实际操作中,我使用的是一个非常大的3D张量(n~万亿),一个非常稀疏的idx(即大量的-1)。由于
idx
是固定的,我当前的解决方案是通过填充0和1预先计算一个n*(h*w)数组
索引张量
,然后执行以下操作

tmp = arr.reshape(1, n)
res = (tmp @ index_tensor).reshape([h,w])

它工作正常,但需要巨大的内存来存储
索引张量
。是否有任何方法可以利用
idx
的稀疏性和不可更改性来降低内存成本并在python中保持合理的运行速度(使用numpy或pytorch将是最好的)?提前谢谢

暂时忽略
-1
的复杂性,直接索引和求和是:

In [58]: arr = np.array([[ 1, 2, 3, 4, 5], [5, 6, 7, 8, 9]])
In [59]: idx = np.array([[[0, 1, 1], [2, 4, 6]],
    ...:                 [[5, 1, 3], [1, -1, -1]]])
In [60]: arr.flat[idx]
Out[60]: 
array([[[1, 2, 2],
        [3, 5, 6]],

       [[5, 2, 4],
        [2, 9, 9]]])
In [61]: _.sum(axis=-1)
Out[61]: 
array([[ 5, 14],
       [11, 20]])
处理-1的一种方法(不一定快速或高效内存)是使用屏蔽数组:

In [62]: mask = idx<0
In [63]: mask
Out[63]: 
array([[[False, False, False],
        [False, False, False]],

       [[False, False, False],
        [False,  True,  True]]])

In [65]: ma = np.ma.masked_array(Out[60],mask)
In [67]: ma
Out[67]: 
masked_array(
  data=[[[1, 2, 2],
         [3, 5, 6]],

        [[5, 2, 4],
         [2, --, --]]],
  mask=[[[False, False, False],
         [False, False, False]],

        [[False, False, False],
         [False,  True,  True]]],
  fill_value=999999)
In [68]: ma.sum(axis=-1)
Out[68]: 
masked_array(
  data=[[5, 14],
        [11, 2]],
  mask=[[False, False],
        [False, False]],
  fill_value=999999)
这比掩蔽阵列方法更直接、更快

您还没有详细说明如何构造
索引张量
,因此我不会尝试对其进行比较

另一种可能是用0填充数组,并调整索引:

In [83]: arr1 = np.hstack((0,arr.ravel()))
In [84]: arr1
Out[84]: array([0, 1, 2, 3, 4, 5, 5, 6, 7, 8, 9])
In [85]: arr1[idx+1]
Out[85]: 
array([[[1, 2, 2],
        [3, 5, 6]],

       [[5, 2, 4],
        [2, 0, 0]]])
In [86]: arr1[idx+1].sum(axis=-1)
Out[86]: 
array([[ 5, 14],
       [11,  2]])
稀疏的 第一次尝试使用稀疏矩阵:

idx
重塑为二维:

In [141]: idx1 = np.reshape(idx,(4,3))
用它做一个稀疏张量。首先,我将采用迭代的
lil
方法,尽管通常直接构建
coo
(甚至
csr
)输入更快:

In [142]: M = sparse.lil_matrix((4,10),dtype=int)
     ...: for i in range(4):
     ...:     for j in range(3):
     ...:         v = idx1[i,j]
     ...:         if v>=0:
     ...:            M[i,v] = 1
     ...: 
In [143]: M
Out[143]: 
<4x10 sparse matrix of type '<class 'numpy.int64'>'
    with 9 stored elements in List of Lists format>
In [144]: M.A
Out[144]: 
array([[1, 1, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 1, 0, 1, 0, 1, 0, 0, 0],
       [0, 1, 0, 1, 0, 1, 0, 0, 0, 0],
       [0, 1, 0, 0, 0, 0, 0, 0, 0, 0]])

使用
M。A@arr.ravel()
基本上就是你要做的。虽然
M
是稀疏的,
arr
不是稀疏的。对于这种情况,
M.A@
M@

谢谢,我已经更新了我的问题。我忘了提到的一件事是,
idx
数组对于每次迭代都是固定的,这就是为什么我说我可以预先计算它。我想知道是否有任何方法可以将
idx
转换为稀疏张量并用它计算结果。您当前的方法和我提到的方法仍然需要存储非常消耗内存的
n*a*b
索引数组。任何想法都值得赞赏。我添加了一些比蒙面阵列更快的其他想法
scipy.sparse
是2d,因此我们必须展平h*w维度。如果稀疏度足够大,稀疏度对矩阵乘法有好处。实际上,稀疏索引是通过矩阵乘法和提取器矩阵实现的。但是构造稀疏矩阵需要时间。谢谢!让我试试看。预先存储的
idx
数组现在有点让我们难以忘怀。我认为稀疏可能是希望。
In [142]: M = sparse.lil_matrix((4,10),dtype=int)
     ...: for i in range(4):
     ...:     for j in range(3):
     ...:         v = idx1[i,j]
     ...:         if v>=0:
     ...:            M[i,v] = 1
     ...: 
In [143]: M
Out[143]: 
<4x10 sparse matrix of type '<class 'numpy.int64'>'
    with 9 stored elements in List of Lists format>
In [144]: M.A
Out[144]: 
array([[1, 1, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 1, 0, 1, 0, 1, 0, 0, 0],
       [0, 1, 0, 1, 0, 1, 0, 0, 0, 0],
       [0, 1, 0, 0, 0, 0, 0, 0, 0, 0]])
In [145]: M@arr.ravel()
Out[145]: array([ 3, 14, 11,  2])