使用 NumPy 进行深度堆叠

Posted

技术标签:

【中文标题】使用 NumPy 进行深度堆叠【英文标题】:Depthwise stacking with NumPy 【发布时间】:2018-05-05 22:21:31 【问题描述】:

我正在使用以下代码并获得一个大小为 (2,9) 的输出 numpy ndarray,然后我试图将其重塑为大小 (3,3,2)。我希望使用 (3,3,2) 作为新数组的维度调用 reshape 会将 2x9 数组的每一行 row 整形为 3x3 数组并将这两个 3x3 数组包装成另一个数组。

例如,当我为 结果编制索引时,我想要以下行为:

input: print(result)
output: [[ 2.  2.  1.  0.  8.  5.  2.  4.  5.]
         [ 4.  7.  5.  6.  4.  3. -3.  2.  1.]]

result = result.reshape((3,3,2))

DESIRED NEW BEHAVIOR
input: print(result[:,:,0])
output: [[2. 2. 1.]
         [0. 8. 5.]
         [2. 4. 5.]]

input: print(result[:,:,1])
output: [[ 4.  7.  5.]
         [ 6.  4.  3.]
         [-3.  2.  1.]]

ACTUAL NEW BEHAVIOR
input: print(result[:,:,0])
output: [[2. 1. 8.]
         [2. 5. 7.]
         [6. 3. 2.]]

input: print(result[:,:,1])
output: [[ 2.  0.  5.]
         [ 4.  4.  5.]
         [ 4. -3.  1.]]

有没有办法指定我想沿深度维度逐行进行重塑?我很困惑为什么默认情况下 numpy 会选择它为 reshape 所做的选择。

这是我用来生成 result 矩阵的代码,这段代码可能对分析我的问题是必要的,也可能不是必要的。我觉得好像没有必要,但为了完整起见,我将其包括在内:

import numpy as np

# im2col implementation assuming width/height dimensions of filter and input_vol
# are the same (i.e. input_vol_width is equal to input_vol_height and the same
# for the filter spatial dimensions, although input_vol_width need not equal
# filter_vol_width)

def im2col(input, filters, input_vol_dims, filter_size_dims, stride):
    receptive_field_size = 1
    for dim in filter_size_dims:
        receptive_field_size *= dim

    output_width = output_height = int((input_vol_dims[0]-filter_size_dims[0])/stride + 1)

    X_col = np.zeros((receptive_field_size,output_width*output_height))

    W_row = np.zeros((len(filters),receptive_field_size))

    pos = 0
    for i in range(0,input_vol_dims[0]-1,stride):
        for j in range(0,input_vol_dims[1]-1,stride):
           X_col[:,pos] = input[i:i+stride+1,j:j+stride+1,:].ravel()
           pos += 1

    for i in range(len(filters)):
        W_row[i,:] = filters[i].ravel()

    bias = np.array([[1], [0]])

    result = np.dot(W_row, X_col) + bias

    print(result)


if __name__ == '__main__':
    x = np.zeros((7, 7, 3))

    x[:,:,0] = np.array([[0,0,0,0,0,0,0],
                         [0,1,1,0,0,1,0],
                         [0,2,2,1,1,1,0],
                         [0,2,0,2,1,0,0],
                         [0,2,0,0,1,0,0],
                         [0,0,0,1,1,0,0],
                         [0,0,0,0,0,0,0]])

    x[:,:,1] = np.array([[0,0,0,0,0,0,0],
                         [0,2,0,1,0,2,0],
                         [0,0,1,2,1,0,0],
                         [0,2,0,0,2,0,0],
                         [0,2,1,0,0,0,0],
                         [0,1,2,2,2,0,0],
                         [0,0,0,0,0,0,0]])

    x[:,:,2] = np.array([[0,0,0,0,0,0,0],
                         [0,0,0,2,1,1,0],
                         [0,0,0,2,2,0,0],
                         [0,2,1,0,2,2,0],
                         [0,0,1,2,1,2,0],
                         [0,2,0,0,2,1,0],
                         [0,0,0,0,0,0,0]])

    w0 = np.zeros((3,3,3))

    w0[:,:,0] = np.array([[1,1,0],
                          [1,-1,1],
                          [-1,1,1]])

    w0[:,:,1] = np.array([[-1,-1,0],
                          [1,-1,1],
                          [1,-1,-1]])

    w0[:,:,2] = np.array([[0,0,0],
                          [0,0,1],
                          [1,0,1]]


    w1 = np.zeros((3,3,3))

    w1[:,:,0] = np.array([[0,-1,1],
                         [1,1,0],
                         [1,1,0]])

    w1[:,:,1] = np.array([[-1,-1,1],
                          [1,0,1],
                          [0,1,1]])

    w1[:,:,2] = np.array([[-1,-1,0],
                          [1,-1,0],
                          [1,1,0]])


    filters = np.array([w0,w1])

    im2col(x,np.array([w0,w1]),x.shape,w0.shape,2)

【问题讨论】:

【参考方案1】:

让我们重新塑造一点不同的形状,然后在深度方面进行dstack

arr = np.dstack(result.reshape((-1,3,3)))

arr[..., 0]
array([[2., 2., 1.],
       [0., 8., 5.],
       [2., 4., 5.]])

【讨论】:

【参考方案2】:

Reshape 保持元素的原始顺序

In [215]: x=np.array(x)
In [216]: x.shape
Out[216]: (2, 9)

将 9 号尺寸重塑为 3x3 以保持您想要的元素顺序:

In [217]: x.reshape(2,3,3)
Out[217]: 
array([[[ 2.,  2.,  1.],
        [ 0.,  8.,  5.],
        [ 2.,  4.,  5.]],

       [[ 4.,  7.,  5.],
        [ 6.,  4.,  3.],
        [-3.,  2.,  1.]]])

但您必须使用 [0,:,:] 对其进行索引才能看到其中一个块。

要查看具有 [:,:,0] 的相同块,您必须将该大小的 2 维移动到末尾。 COLDSPEED's dstack 通过在第一个维度上迭代并在新的第三个维度上连接 2 个块(每个 3x3)来做到这一点。另一种方法是使用transpose 重新排列尺寸:

In [218]: x.reshape(2,3,3).transpose(1,2,0)
Out[218]: 
array([[[ 2.,  4.],
        [ 2.,  7.],
        [ 1.,  5.]],

       [[ 0.,  6.],
        [ 8.,  4.],
        [ 5.,  3.]],

       [[ 2., -3.],
        [ 4.,  2.],
        [ 5.,  1.]]])
In [219]: y = _
In [220]: y.shape
Out[220]: (3, 3, 2)
In [221]: y[:,:,0]
Out[221]: 
array([[2., 2., 1.],
       [0., 8., 5.],
       [2., 4., 5.]])

【讨论】:

以上是关于使用 NumPy 进行深度堆叠的主要内容,如果未能解决你的问题,请参考以下文章

堆叠不同大小图像的 Numpy 数组

理解 numpy 的 dstack 函数

Python使用numpy中的hstack函数水平堆叠(horizontally stack)数组实战

使用 numpy 堆叠具有一个不同维度的数组

通过沿一个轴堆叠将两个 numpy 视图组合成一个视图

Python数据分析-堆叠数组函数总结