如何实现maxpool:在图像或张量上的滑动窗口上取最大值

时间:2017-01-26 19:42:15

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

简而言之:我正在寻找numpy的简单Maxpool(可能是oneliner)实现 - 在numpy.narray的所有位置的窗口上最大值横跨尺寸的窗口。

更多详细信息:我正在实施卷积神经网络(“CNN”),这种网络中的典型层之一是MaxPool层(查看示例{{3 }})。写作 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的值等于沿着第二维和第三维的大小S x S的窗口所取的最大值。输入x,窗口“角落”放在索引b,h,w,c

其他一些细节:使用numpy实施网络。 CNN有许多“层”,其中一层的输出是下一层的输入。层的输入是numpy.narray,称为“张量”。在我的情况下,张量是4维numpy.narrayx。那是x.shape是一个元组(B,H,W,C)。在张量处理图层之后,每个尺寸的尺寸都会发生变化,例如,图层i= 4的输入可以具有尺寸B = 10, H = 24, W = 24, C = 3,而输出(也称为i+1图层的输入具有{{} 1}}。如评论中所示,B = 10, H = 12, W = 12, C = 5申请后的大小为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的第三维,这不是我想要的。

1 个答案:

答案 0 :(得分:3)

这是一个使用np.lib.stride_tricks.as_strided创建滑动窗口的解决方案,生成6D形状数组:(B,H-S+1,W-S+1,S,S,C),然后简单地沿第四和第五轴执行max,从而产生形状为(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)