Numpy广播到第四维:...... vs.:vs None

时间:2016-11-02 14:25:41

标签: numpy numpy-broadcasting

在montecarlo模拟中,我有以下7个pokercards为2名球员和3个不同的蒙特卡洛跑。

self.cards:

array([[[  6.,  12.],
    [  1.,   6.],
    [  3.,   3.],
    [  8.,   8.],
    [  1.,   1.],
    [  4.,   4.],
    [  2.,   2.]],

   [[  6.,   7.],
    [  1.,   1.],
    [  3.,   3.],
    [  2.,   2.],
    [ 12.,  12.],
    [  5.,   5.],
    [ 10.,  10.]],

   [[  6.,   3.],
    [  1.,  11.],
    [  2.,   2.],
    [  6.,   6.],
    [ 12.,  12.],
    [  6.,   6.],
    [  7.,   7.]]])

相应的诉讼是:

self.suits

array([[[ 2.,  1.],
    [ 1.,  2.],
    [ 2.,  2.],
    [ 2.,  2.],
    [ 1.,  1.],
    [ 2.,  2.],
    [ 2.,  2.]],

   [[ 2.,  0.],
    [ 1.,  3.],
    [ 2.,  2.],
    [ 0.,  0.],
    [ 1.,  1.],
    [ 1.,  1.],
    [ 1.,  1.]],

   [[ 2.,  2.],
    [ 1.,  0.],
    [ 3.,  3.],
    [ 2.,  2.],
    [ 1.,  1.],
    [ 1.,  1.],
    [ 1.,  1.]]])

现在我想以一种卡阵列扩展到第4维的方式'合并'数组,第4维的大小为4:0,包含所有套装== 1,1所有套装== 2,2均适合== 3和3所有套装== 4

我可以轻松创建4个不同的数组:

club_cards=(self.suits == 1) * self.cards 
diamond_cards=(self.suits == 2) * self.cards 
heart_cards=(self.suits == 3) * self.cards 
spade_cards=(self.suits == 4) * self.cards

然后将它们堆叠在一起:

stacked_array=np.stack((club_cards,diamond_cards, heart_cards, spade_cards),axis=0)

预期结果的形状为(4,3,8,2)

array([[[[  1.,  12.],
         [  1.,   1.],
         [  0.,   0.],
         [  0.,   0.],
         [  0.,   0.],
         [  0.,   0.],
         [  0.,   0.],
         [-11.,   0.]],

        [[ 12.,  12.],
         [ 10.,  10.],
         [  5.,   5.],
         [  1.,   0.],
         [  0.,   0.],
         [  0.,   0.],
         [  0.,   0.],
         [  0.,   0.]],

        [[ 12.,  12.],
         [  7.,   7.],
         [  6.,   6.],
         [  1.,   0.],
         [  0.,   0.],
         [  0.,   0.],
         [  0.,   0.],
         [  0.,   0.]]],


       [[[  8.,   8.],
         [  6.,   6.],
         [  4.,   4.],
         [  3.,   3.],
         [  2.,   2.],
         [  0.,   0.],
         [  0.,   0.],
         [ -4.,  -4.]],

        [[  6.,   3.],
         [  3.,   0.],
         [  0.,   0.],
         [  0.,   0.],
         [  0.,   0.],
         [  0.,   0.],
         [  0.,   0.],
         [ -6.,  -9.]],

        [[  6.,   6.],
         [  6.,   3.],
         [  0.,   0.],
         [  0.,   0.],
         [  0.,   0.],
         [  0.,   0.],
         [  0.,   0.],
         [ -6.,  -6.]]],


       [[[  0.,   0.],
         [  0.,   0.],
         [  0.,   0.],
         [  0.,   0.],
         [  0.,   0.],
         [  0.,   0.],
         [  0.,   0.],
         [-12., -12.]],

        [[  0.,   1.],
         [  0.,   0.],
         [  0.,   0.],
         [  0.,   0.],
         [  0.,   0.],
         [  0.,   0.],
         [  0.,   0.],
         [-12., -11.]],

        [[  2.,   2.],
         [  0.,   0.],
         [  0.,   0.],
         [  0.,   0.],
         [  0.,   0.],
         [  0.,   0.],
         [  0.,   0.],
         [-10., -10.]]],


       [[[  0.,   0.],
         [  0.,   0.],
         [  0.,   0.],
         [  0.,   0.],
         [  0.,   0.],
         [  0.,   0.],
         [  0.,   0.],
         [-12., -12.]],

        [[  0.,   0.],
         [  0.,   0.],
         [  0.,   0.],
         [  0.,   0.],
         [  0.,   0.],
         [  0.,   0.],
         [  0.,   0.],
         [-12., -12.]],

        [[  0.,   0.],
         [  0.,   0.],
         [  0.,   0.],
         [  0.,   0.],
         [  0.,   0.],
         [  0.,   0.],
         [  0.,   0.],
         [-12., -12.]]]])

虽然在上述情况下这可能有意义,但并不总是可行,特别是如果有超过4个案例需要堆叠在一起,这就引出了我的问题:

我怎么能用广播呢?在我的具体问题下面:

我尝试了一些事情。

  1. 让我们专注于让布尔做套装的第一步== np.arange(4)(第二步只是卡片的倍增,需要以与卡片相同的方式播放西装)。我的理解是我们想为suit数组添加一个维度,所以我们不应该用3点符号表示这个:self.suits[...,:,:,:]==np.arange(4)?相反,以下似乎几乎可以工作:self.suits[:,:,:,None]==np.arange(4)(除了它将维度添加到错误的位置)。以下内容也不起作用:self.suits[None,:,:,:]==np.arange(4)。如何在第一维中扩展数组,以便结果与上面的堆栈相同?

  2. 在什么情况下我需要...None?我希望使用...,因为这表示需要根据需要扩展此维度(在这种情况下,大小为4)?为什么这似乎不正确而使用了无?

1 个答案:

答案 0 :(得分:4)

您正在axis=0堆叠单个卡片结果。因此,当移植到基于广播的解决方案时,我们可以在1, 2, 3, 4数组中创建这些标量4D的范围数组,其中所有轴都是单一维度(dims,长度= 1),第一个除外。可以有不同的方法来创建这样的4D数组。一种方法是:np.arange(1,5)[:,None,None,None],我们使用1D创建一个np.arange数组,并添加三个单独的dims作为最后三个np.newaxis/None

我们针对4D对此b数组执行相等比较,这将允许最后三个dims内部broadcastingb个元素。然后,我们将它与原始代码中的a相乘,得到所需的输出。

因此,实施将是 -

out = a*(b == np.arange(1,5)[:,None,None,None]) 

何时/如何使用...(省略号):

我们在尝试将新轴添加到多维数组中时使用...(省略号),并且我们不希望每个dim指定colons。因此,要使a一个4D数组的最后一个dim为单例,我们会执行:a[:,:,:,None]。打字太多了!因此,我们使用...来帮助我们:a[...,None]。请注意,无论维度数量如何,都会使用此...表示法。因此,如果a是一个5D数组,并在其中添加一个新轴作为最后一个,我们会a[:,:,:,:,:,None]或只使用省略号:a[...,None]。干嘛!