【问题标题】:How to implement maxpool: taking a maximum on sliding window on image or tensor如何实现maxpool:在图像或张量的滑动窗口上取最大值
【发布时间】:2017-06-12 09:46:02
【问题描述】:

简而言之:我正在寻找一个简单的numpy(可能是oneliner)实现Maxpool - 在numpy.narray 上的一个窗口上的最大值,用于跨维度的窗口的所有位置。

更多细节:我正在实现一个卷积神经网络(“CNN”),这种网络中的典型层之一是MaxPool 层(例如here)。写作 y = MaxPool(x, S)x 是输入 narrayS 是参数,使用伪代码,MaxPool 的输出由以下公式给出:

     y[b,h,w,c] = max(x[b, s*h + i, s*w + j, c]) over i = 0,..., S-1; j = 0,...,S-1.

也就是说,ynarray,其中索引b,h,w,c 处的值等于沿输入x 的第二和第三维的大小为S x S 的窗口所占用的最大值,窗口“角落”放置在索引b,h,w,c

一些额外的细节:网络是使用numpy 实现的。 CNN 有许多“层”,其中一层的输出是下一层的输入。层的输入是numpy.narrays,称为“张量”。在我的例子中,张量是 4 维的 numpy.narray's、x。那就是x.shape 是一个元组(B,H,W,C)。层处理张量后,每个维度的大小都会发生变化,例如层i= 4 的输入可以有大小B = 10, H = 24, W = 24, C = 3,而输出,也就是i+1 层的输入有B = 10, H = 12, W = 12, C = 5。如 cmets 所示,应用MaxPool 后的大小为(B, H - S + 1, W - S + 1, C)

具体来说:如果我使用

import numpy as np

y = np.amax(x, axis = (1,2)) 

其中x.shape(2,3,3,4) 这将给我我想要的,但对于我最大化的窗口大小为3 x 3 的退化情况,@987654355 的第二和第三维度的大小@,这不是我想要的。

【问题讨论】:

  • 所以,输出的形状是:(B,H-S+1,W-S+1,C),对吧?
  • @Divakar 是的,你是对的,输出取决于你能在滑动窗口中放多少次
  • scipy.ndimage.maximum_filter1d 实现 O(n) 算法(与窗口大小无关)

标签: python numpy neural-network conv-neural-network array-broadcasting


【解决方案1】:

这是一个解决方案,使用np.lib.stride_tricks.as_strided 创建滑动窗口,生成6D 形状数组:(B,H-S+1,W-S+1,S,S,C),然后简单地沿第四轴和第五轴执行最大值,生成形状输出数组:(B,H-S+1,W-S+1,C) .中间6D 数组将是输入数组的视图,因此不会再占用内存。 max 的后续操作是归约,将有效地利用滑动 views

因此,实现将是 -

# Based on http://stackoverflow.com/a/41850409/3293881
def patchify(img, patch_shape):
    a, X, Y, b = img.shape
    x, y = patch_shape
    shape = (a, X - x + 1, Y - y + 1, x, y, b)
    a_str, X_str, Y_str, b_str = img.strides
    strides = (a_str, X_str, Y_str, X_str, Y_str, b_str)
    return np.lib.stride_tricks.as_strided(img, shape=shape, strides=strides)

out = patchify(x, (S,S)).max(axis=(3,4))

示例运行 -

In [224]: x = np.random.randint(0,9,(10,24,24,3))

In [225]: S = 5

In [226]: np.may_share_memory(patchify(x, (S,S)), x)
Out[226]: True

In [227]: patchify(x, (S,S)).shape
Out[227]: (10, 20, 20, 5, 5, 3)

In [228]: patchify(x, (S,S)).max(axis=(3,4)).shape
Out[228]: (10, 20, 20, 3)

【讨论】:

  • 对于不重叠的补丁,即(a, ((X-x)/x)+1, (Y-y/y)+1, x, y, b) 或简单的(a, X/x, Y/y, x, y, b),我使用什么步幅?有没有一种简单的方法可以将 conv 步幅(1、2、3..、window_size 或完整步幅)与 numpy as_strided 使用的步幅关联起来?
  • @SaravanabalagiRamachandran 我认为使用 scikit-image 的 view_as_blocks 可能更简单。
猜你喜欢
  • 2019-07-11
  • 1970-01-01
  • 2015-02-19
  • 1970-01-01
  • 2021-01-22
  • 1970-01-01
  • 1970-01-01
  • 2012-06-03
相关资源
最近更新 更多