python numpy maxpool:给定一个数组和来自argmax的索引,返回最大值

Posted

技术标签:

【中文标题】python numpy maxpool:给定一个数组和来自argmax的索引,返回最大值【英文标题】:python numpy maxpool: given an array and indices from argmax, returns max values 【发布时间】:2021-11-24 15:47:48 【问题描述】:

假设我有一个名为 view 的数组:

array([[[[ 7,  9],
         [10, 11]],

        [[19, 18],
         [20, 16]]],


       [[[24,  5],
         [ 6, 10]],

        [[18, 11],
         [45, 12]]]])

你可能从 maxpooling 中知道,这是原始输入的视图,内核大小为 2x2:

[[ 7,  9],  [[19, 18],
 [10, 11]],  [20, 16]]], ....

目标是找到最大值及其索引。但是,argmax 只适用于单轴,所以我需要flatten view,即使用flatten=view.reshape(2,2,4)

array([[[ 7,  9, 10, 11], [19, 18, 20, 16]],

       [[24,  5,  6, 10], [18, 11, 45, 12]]])

现在,在我的previous question 的帮助下,我可以使用inds = flatten.argmax(-1) 找到最大值索引:

array([[3, 2],
       [0, 2]])

和最大值:

i, j = np.indices(flatten.shape[:-1])
flatten[i, j, inds]

>>> array([[11, 20],
           [24, 45]])

问题 当我 展平 view 数组时,问题就出现了。由于view 数组是原始数组的视图,即view = as_strided(original, newshape, newstrides),所以vieworiginal 共享相同的数据。但是,reshape 会破坏它,因此view 上的任何更改都不会反映在original 上。这在反向传播期间是有问题的。

我的问题 给定数组view 和索引ind,我想将view 中的最大值更改为1000,而不使用整形或任何破坏vieworiginal 之间“键”的操作。感谢您的帮助!!!

可重现的例子

import numpy as np
from numpy.lib.stride_tricks import as_strided

original=np.array([[[7,9,19,18],[10,11,20,16]],[[24,5,18,11],[6,10,45,12]]],dtype=np.float64)
view=as_strided(original, shape=(2,1,2,2,2),strides=(64,32*2,8*2,32,8))

我想将view 中每个内核的最大值更改为 1000,这可以反映在original 上,即如果我运行view[0,0,0,0,0]=1000,那么视图和原始元素的第一个元素是 1000。

【问题讨论】:

您可以通过准备一个可运行的minimal reproducible example 来帮助那些试图回答您的问题的人:一个数组、一个视图以及您想用它做什么。 嗨,安德拉斯,我已经添加了一个示例 :) 如您所见,它有效 :P 再一次,您不需要(也不应该使用)as_strided:view = original.reshape(2, 1, 2, 2, 2).transpose(0, 1, 3, 2, 4) 是的,你是对的。虽然有时当涉及到步幅、膨胀和组时,比如在 pytorch conv2d 中,我不知道是否还有其他选择。我刚刚使用 numpy 完成了这个 maxpooling,不敢相信它比 conv2d 更难,索引让我非常头疼 smh。 【参考方案1】:

这个怎么样:

import numpy as np
view = np.array(
    [[[[ 7,  9],
       [10, 11]],
      [[19, 18],
       [20, 16]]],
     [[[24,  5],
       [ 6, 10]],
      [[18, 11],
       [45, 12]]]]
)
# Getting the indices of the max values
max0 = view.max(-2)
idx2 = view.argmax(-2)
idx2 = idx2.reshape(-1, idx2.shape[1])
max1 = max0.max(-1)
idx3 = max0.argmax(-1).flatten()
idx2 = idx2[np.arange(idx3.size), idx3]

idx0 = np.arange(view.shape[0]).repeat(view.shape[1])
idx1 = np.arange(view.shape[1]).reshape(1, -1).repeat(view.shape[0], 0).flatten()

# Replacing the maximal vlues with 1000
view[idx0, idx1, idx2, idx3] = 1000
print(f'view = \nview')

输出:

view = 
[[[[   7    9]
   [  10 1000]]

  [[  19   18]
   [1000   16]]]


 [[[1000    5]
   [   6   10]]

  [[  18   11]
   [1000   12]]]]

基本上,idxn 是前两个维度中包含的每个矩阵在后两个维度中最大值的索引。

【讨论】:

感谢 Yann,这看起来很有希望!您能否根据可重现示例中的originalview 调整您的答案? @Sam-gege。您是否愿意调整您的可重现示例以包含单个清晰的输入元组以及清晰且完整的预期输出?就目前而言,我不明白我的回答中的输入或输出有什么问题。 嗨 Yann,输入只是我的 view 来自可重现示例部分的数组,它比您的 view 多一维。但无论如何,我已经做出了必要的改变。您只需要更改此 idx2 = idx2.reshape(-1, idx2.shape[ - 1]) 即 idx2.shape(-1) 而不是 shape(1)。除此之外,view[ i, j, k, idx2, idx3] = 1000 中应该有 3 个轴,其中i,j,k=np.indices(view.shape[:-2]) 可以节省一些工作。无论如何,我已经接受你的回答,谢谢!

以上是关于python numpy maxpool:给定一个数组和来自argmax的索引,返回最大值的主要内容,如果未能解决你的问题,请参考以下文章

Numpy实现MaxPooling2D(最大池化)和AveragePooling2D(平均池化)

Python 使用给定窗口运行累积总和

Python/NumPy:实现运行总和(但不完全)

Python:numpy/pandas 根据条件更改值

Python: 向量矩阵和多维数组(基于NumPy库)

python--numpy笔记整理