the*_*hem 4 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,..., S-1; j = 0,...,S-1.
Run Code Online (Sandbox Code Playgroud)
也就是说,y
如果narray
索引处的值等于沿着输入的第二维和第三维大小的b,h,w,c
窗口所取的最大值,则窗口“角”被放置在索引处。S x S
x
b,h,w,c
一些其他细节:网络是使用numpy
. CNN 有许多“层”,其中一层的输出是下一层的输入。层的输入numpy.narray
称为“张量”。就我而言,张量是 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))
Run Code Online (Sandbox Code Playgroud)
据说这会给我想要的东西,x.shape
但是(2,3,3,4)
对于退化的情况,我最大化的窗口的大小为3 x 3
,第二维和第三维的大小x
,这不完全是我想要的。
这是一个解决方案,用于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))
Run Code Online (Sandbox Code Playgroud)
样本运行 -
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)
Run Code Online (Sandbox Code Playgroud)