Python 如何实现maxpool:在图像或张量上的滑动窗口上取最大值
简言之:我正在寻找一个简单的Python 如何实现maxpool:在图像或张量上的滑动窗口上取最大值,python,numpy,neural-network,conv-neural-network,array-broadcasting,Python,Numpy,Neural Network,Conv Neural Network,Array Broadcasting,简言之:我正在寻找一个简单的numpy(可能是一个线性)实现Maxpool-在numpy.narray上的窗口最大值,用于跨维度的所有窗口位置 更多细节:我正在实现一个卷积神经网络(“CNN”),这种网络中的一个典型层是MaxPool层(例如)。书写 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,...,
numpy
(可能是一个线性)实现Maxpool
-在numpy.narray
上的窗口最大值,用于跨维度的所有窗口位置
更多细节:我正在实现一个卷积神经网络(“CNN”),这种网络中的一个典型层是MaxPool
层(例如)。书写
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
窗口的最大接收量,窗口“角”位于索引b,h,w,c
一些附加细节:网络是使用numpy
实现的。CNN有许多“层”,其中一层的输出是下一层的输入。层的输入是numpy.narray
s,称为“张量”。在我的例子中,张量是四维的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.strude\u技巧的解决方案。as\u-strude
创建滑动窗口,生成一个6D
形状数组:(B,H-s+1,W-s+1,s,s,C)
,然后简单地沿第四和第五轴执行max,生成一个形状输出数组:(B,H-s+1,W-s+1,C)
。中间6D
数组将是输入数组的视图,因此不会占用更多内存。max
的后续操作是一个缩减操作,可以有效地利用滑动视图
因此,将需要实施-
# 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)
因此,输出的形状是:(B,H-S+1,W-S+1,C)
,对吗?@Divakar是的,你是对的,输出取决于你能在滑动窗口中适应多少次,为非重叠面片实现O(n)算法(独立于窗口大小),即(a,((X-X)/X)+1,(Y-Y/Y)+1,X,Y,B)
,或者干脆(a,X/X,Y/Y,X,Y,b)
,我应该使用什么样的步幅?有没有一种简单的方法将转换步幅(1,2,3..,窗口大小或全步幅)与numpy使用的步幅关联起来?我认为SaravanabalagiRamachandran使用scikit image的视图块可能更简单。