其他分享
首页 > 其他分享> > 如何实现maxpool:在图像或张量的滑动窗口上获取最大值

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

作者:互联网

简而言之:我正在寻找Maxpool的一个简单的numpy(也许是oneliner)实现-在numpy.narray上的窗口上,该窗口在所有尺寸上的所有位置都达到最大值.

更详细地讲:我正在实现一个卷积神经网络(“ CNN”),这种网络中的典型层之一是MaxPool层(例如here).写作
y = MaxPool(x,S),x是输入narray,S是参数,使用伪代码,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.

也就是说,y是narray,其中索引b,h,w,c处的值等于沿着输入x的第二维和第三维在大小为S x S的窗口上所取的最大值,窗口“ corner”位于索引b,h,w,c.

其他一些细节:网络是使用numpy实现的. CNN具有许多“层”,其中一层的输出是下一层的输入.图层的输入是被称为“张量”的numpy.narrays.在我的情况下,张量是4维numpy.narray的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.如注释所示,使用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,即第二和第三个维度的大小x,这不完全是我想要的.

解决方法:

这是一个使用np.lib.stride_tricks.as_strided的解决方案来创建滑动窗口,从而生成形状为(B,HS 1,WS 1,S,S,S,C)的6D数组,然后简单地沿第四轴和第五轴执行max,生成形状为(B,HS 1,WS 1,C)的输出数组.中间6D数组将是输入数组的视图,因此不再占用内存. max的后续减少操作将有效地利用滑动视图.

因此,一个实现将是-

# Based on https://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)

标签:numpy-broadcasting,neural-network,conv-neural-network,python,numpy
来源: https://codeday.me/bug/20191111/2022364.html