【问题标题】:how to gather elements of specific indices in numpy?如何在numpy中收集特定索引的元素?
【发布时间】:2018-04-02 17:51:33
【问题描述】:

我想在指定轴上收集指定索引的元素,如下所示。

x = [[1,2,3], [4,5,6]]
index = [[2,1], [0, 1]]
x[:, index] = [[3, 2], [4, 5]]

这本质上是 pytorch 中的收集操作,但是如您所知,这在 numpy 中是无法实现的。我想知道numpy中是否有这样的“收集”操作?

【问题讨论】:

标签: numpy


【解决方案1】:

numpy.take_along_axis是我需要的,根据索引取元素。它可以像 PyTorch 中的收集方法一样使用。

这是手册中的一个示例:

>>> a = np.array([[10, 30, 20], [60, 40, 50]])
>>> ai = np.expand_dims(np.argmax(a, axis=1), axis=1)
>>> ai
array([[1],
       [0]])
>>> np.take_along_axis(a, ai, axis=1)
array([[30],
       [60]])

【讨论】:

    【解决方案2】:

    我不久前写了这篇文章,以在 Numpy 中复制 PyTorch 的 gather。在这种情况下,self 是您的 x

    def gather(self, dim, index):
        """
        Gathers values along an axis specified by ``dim``.
    
        For a 3-D tensor the output is specified by:
            out[i][j][k] = input[index[i][j][k]][j][k]  # if dim == 0
            out[i][j][k] = input[i][index[i][j][k]][k]  # if dim == 1
            out[i][j][k] = input[i][j][index[i][j][k]]  # if dim == 2
    
        Parameters
        ----------
        dim:
            The axis along which to index
        index:
            A tensor of indices of elements to gather
    
        Returns
        -------
        Output Tensor
        """
        idx_xsection_shape = index.shape[:dim] + \
            index.shape[dim + 1:]
        self_xsection_shape = self.shape[:dim] + self.shape[dim + 1:]
        if idx_xsection_shape != self_xsection_shape:
            raise ValueError("Except for dimension " + str(dim) +
                             ", all dimensions of index and self should be the same size")
        if index.dtype != np.dtype('int_'):
            raise TypeError("The values of index must be integers")
        data_swaped = np.swapaxes(self, 0, dim)
        index_swaped = np.swapaxes(index, 0, dim)
        gathered = np.choose(index_swaped, data_swaped)
        return np.swapaxes(gathered, 0, dim)
    

    这些是测试用例:

    # Test 1
        t = np.array([[65, 17], [14, 25], [76, 22]])
        idx = np.array([[0], [1], [0]])
        dim = 1
        result = gather(t, dim=dim, index=idx)
        expected = np.array([[65], [25], [76]])
        print(np.array_equal(result, expected))
    
    # Test 2
        t = np.array([[47, 74, 44], [56, 9, 37]])
        idx = np.array([[0, 0, 1], [1, 1, 0], [0, 1, 0]])
        dim = 0
        result = gather(t, dim=dim, index=idx)
        expected = np.array([[47, 74, 37], [56, 9, 44.], [47, 9, 44]])
        print(np.array_equal(result, expected))
    

    【讨论】:

      【解决方案3】:

      使用numpy.take() 函数,它具有大部分 PyTorch 的收集函数功能。

      【讨论】:

        【解决方案4】:
        >>> x = np.array([[1,2,3], [4,5,6]])
        >>> index = np.array([[2,1], [0, 1]])
        >>> x_axis_index=np.tile(np.arange(len(x)), (index.shape[1],1)).transpose() 
        >>> print x_axis_index
        [[0 0]
         [1 1]]
        >>> print x[x_axis_index,index]
        [[3 2]
         [4 5]]
        

        【讨论】:

        • 注意也可以使用np.arange(len(x))不确定np.range是否更可取!
        • 注意:range(x.shape[0]) 和 range(len(x)) 给出一个列表,而 np.arange(len(x)) 和 np.arange(x.shape[ 0]) 给出一个数组。数组和列表都有相同的元素。
        • 我想我的问题/陈述更多的是关于性能,在一个非常大的数组中,我怀疑使用 np.range 进行索引会更快(肯定与形状无关)。跨度>
        • 抱歉,我刚刚稍微修改了我的问题。现在有办法处理这个案子吗?
        猜你喜欢
        • 2020-07-26
        • 2017-08-06
        • 2021-11-02
        • 2018-05-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-11-29
        • 2021-09-15
        相关资源
        最近更新 更多