了解numpy的dstack功能

时间:2014-08-04 10:25:59

标签: python numpy concatenation multidimensional-array

我很难理解numpy的dstack函数实际上在做什么。文档相当稀疏,只是说:

  

按顺序深度(沿第三轴)堆叠数组。

     

采用一系列数组并沿第三轴堆叠它们     制作单个阵列。重建数组除以dsplit。     这是将2D数组(图像)堆叠成单个的简单方法     用于处理的3D数组。

所以要么我真的很愚蠢,这个含义很明显,或者我似乎对“堆叠”,“按顺序”,“深度明智”或“沿轴”这两个术语有一些误解。但是,我的印象是我在vstackhstack的背景下理解这些术语就好了。

我们来看这个例子:

In [193]: a
Out[193]: 
array([[0, 3],
       [1, 4],
       [2, 5]])
In [194]: b
Out[194]: 
array([[ 6,  9],
       [ 7, 10],
       [ 8, 11]])
In [195]: dstack([a,b])
Out[195]: 
array([[[ 0,  6],
        [ 3,  9]],

       [[ 1,  7],
        [ 4, 10]],

       [[ 2,  8],
        [ 5, 11]]])

首先,ab没有第三个轴,所以如何将它们沿' 第三轴'开始堆叠?其次,假设ab是2D图像的表示,为什么我最终会在结果中使用三个 2D数组而不是两个2D数组'顺序'?

4 个答案:

答案 0 :(得分:50)

通过查看输出数组的np.vstack属性,您可以更轻松地了解np.hstacknp.dstack.shape *的作用。

使用两个示例数组:

print(a.shape, b.shape)
# (3, 2) (3, 2)
  • np.vstack沿着第一维连接...

    print(np.vstack((a, b)).shape)
    # (6, 2)
    
  • np.hstack沿着第二维连接...

    print(np.hstack((a, b)).shape)
    # (3, 4)
    
  • np.dstack沿第三维连接。

    print(np.dstack((a, b)).shape)
    # (3, 2, 2)
    

由于ab都是二维的,np.dstack会通过插入大小为1的第三维来扩展它们。这相当于使用{{1在第三维中为它们编制索引(或者,np.newaxis)像这样:

None

如果print(a[:, :, np.newaxis].shape) # (3, 2, 1) ,则c = np.dstack((a, b))c[:, :, 0] == a

您可以使用np.concatenate更明确地执行相同的操作:

c[:, :, 1] == b

*使用print(np.concatenate((a[..., None], b[..., None]), axis=2).shape) # (3, 2, 2) 将模块的全部内容导入全局命名空间considered bad practice for several reasons。习惯的方式是import *

答案 1 :(得分:5)

x == dstack([a, b])。然后x[:, :, 0]a相同,x[:, :, 1]b相同。通常,当dstacking 2D数组时,dstack会产生一个输出,使output[:, :, n]与第n个输入数组相同。

如果我们堆叠3D数组而不是2D:

x = numpy.zeros([2, 2, 3])
y = numpy.ones([2, 2, 4])
z = numpy.dstack([x, y])

然后z[:, :, :3]x相同,z[:, :, 3:7]y相同。

如您所见,我们必须沿第三轴取切片以恢复dstack的输入。这就是dstack行为方式的原因。

答案 2 :(得分:2)

我想在视觉上解释这一点(即使已接受的答案很有意义,但我花了几秒钟的时间才合理化)。 如果我们将2d数组想象为一个列表列表,其中第1轴给出内部列表之一,而第2轴给出该列表中的值,那么OP数组的视觉表示将是这样:

a = [
      [0, 3],
      [1, 4],
      [2, 5]
    ]
b = [
      [6,  9],
      [7, 10],
      [8, 11]
    ]
# Shape of each array is [3,2]

现在,根据current documentationdstack函数添加了第三个轴,这意味着每个数组最终看起来都像这样:

a = [
      [[0], [3]],
      [[1], [4]],
      [[2], [5]]
    ]
b = [
      [[6],  [9]],
      [[7], [10]],
      [[8], [11]]
    ]
# Shape of each array is [3,2,1]

现在,将这两个数组堆叠在第3维中只是意味着结果应该像预期的那样看起来像这样:

dstack([a,b]) = [
                  [[0, 6], [3, 9]],
                  [[1, 7], [4, 10]],
                  [[2, 8], [5, 11]]
                ]
# Shape of the combined array is [3,2,2]

希望这会有所帮助。

答案 3 :(得分:1)

因为你提到"图像",我认为这个例子很有用。如果您使用Keras训练带有输入X的2D卷积网络,那么最好将X保持为维度(#images,dim1ofImage,dim2ofImage)。

image1 = np.array([[4,2],[5,5]])
image2 = np.array([[3,1],[6,7]])

image1 = image1.reshape(1,2,2)
image2 = image2.reshape(1,2,2)

X = np.stack((image1,image2),axis=1) 
X
array([[[[4, 2],
         [5, 5]],
        [[3, 1],
        [6, 7]]]])

np.shape(X)         
X = X.reshape((2,2,2))   
X 
array([[[4, 2],
        [5, 5]],
       [[3, 1],
        [6, 7]]])

X[0] # image 1
array([[4, 2],
       [5, 5]])
X[1] # image 2
array([[3, 1],
       [6, 7]])