Numpy 广播到第 4 维:... vs. : vs None
Numpy broadcasting to the 4th dimension: ... vs. : vs None
在蒙特卡洛模拟中,我有以下 7 张扑克牌,供 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.]]])
现在我想 'merge' 数组,将卡片数组扩展到第 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 个情况时,这引出了我的问题:
我如何通过广播来做到这一点?下面是我的具体问题:
我已经尝试了一些东西。
让我们专注于第一步得到花色的布尔值==np.arange(4)(第二步只是与需要广播的牌相乘与西装相同)。我的理解是我们想为 suits 数组添加一个维度,所以我们不应该用 3 点符号来表示这一点:self.suits[...,:,:,:]==np.arange(4)
?相反,以下内容似乎几乎可以工作:self.suits[:,:,:,None]==np.arange(4)
(除了它在错误的位置添加了维度)。以下内容也不起作用:self.suits[None,:,:,:]==np.arange(4)
。如何在第一维扩展数组,使结果与上述堆栈中的结果相同?
什么情况下需要...
,什么时候需要None
?我希望使用 ...
,因为这表示需要根据需要扩展此维度(在本例中为 4)?为什么这看起来不正确,而是使用 None?
您正在沿 axis=0
堆叠个人卡片结果。因此,当移植到基于广播的解决方案时,我们可以在 4D
数组中创建这些标量 1, 2, 3, 4
的范围数组,除第一个轴外,所有轴都是单一维度(长度 = 1 的暗淡)。可能有不同的方法来创建这样的 4D
数组。一种方法是:np.arange(1,5)[:,None,None,None]
,我们用 np.arange
创建一个 1D
数组,然后简单地添加三个单例 dims 作为最后三个 np.newaxis/None
。
我们将此 4D
数组与 b
进行相等比较,这将允许内部 broadcasting
个 b
元素沿着最后三个维度。然后,我们将它与 a
相乘,就像在原始代码中所做的那样,得到所需的输出。
因此,实施将是 -
out = a*(b == np.arange(1,5)[:,None,None,None])
When/how 使用 ...
(省略号):
我们使用 ...
(省略号),当尝试将新轴添加到多维数组中时,我们不想为每个维度指定 colons
。因此,要使 a
成为一个 4D
数组,最后一个 dim 是一个单例,我们会这样做:a[:,:,:,None]
。打字太多了!所以,我们在那里使用 ...
来帮助我们:a[...,None]
。请注意,无论维数如何,都会使用此 ...
符号。因此,如果 a
是一个 5D
数组,并且要在其中添加一个新轴作为最后一个轴,我们将执行 a[:,:,:,:,:,None]
或简单地使用省略号:a[...,None]
。不错吧!
在蒙特卡洛模拟中,我有以下 7 张扑克牌,供 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.]]])
现在我想 'merge' 数组,将卡片数组扩展到第 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 个情况时,这引出了我的问题:
我如何通过广播来做到这一点?下面是我的具体问题:
我已经尝试了一些东西。
让我们专注于第一步得到花色的布尔值==np.arange(4)(第二步只是与需要广播的牌相乘与西装相同)。我的理解是我们想为 suits 数组添加一个维度,所以我们不应该用 3 点符号来表示这一点:
self.suits[...,:,:,:]==np.arange(4)
?相反,以下内容似乎几乎可以工作:self.suits[:,:,:,None]==np.arange(4)
(除了它在错误的位置添加了维度)。以下内容也不起作用:self.suits[None,:,:,:]==np.arange(4)
。如何在第一维扩展数组,使结果与上述堆栈中的结果相同?什么情况下需要
...
,什么时候需要None
?我希望使用...
,因为这表示需要根据需要扩展此维度(在本例中为 4)?为什么这看起来不正确,而是使用 None?
您正在沿 axis=0
堆叠个人卡片结果。因此,当移植到基于广播的解决方案时,我们可以在 4D
数组中创建这些标量 1, 2, 3, 4
的范围数组,除第一个轴外,所有轴都是单一维度(长度 = 1 的暗淡)。可能有不同的方法来创建这样的 4D
数组。一种方法是:np.arange(1,5)[:,None,None,None]
,我们用 np.arange
创建一个 1D
数组,然后简单地添加三个单例 dims 作为最后三个 np.newaxis/None
。
我们将此 4D
数组与 b
进行相等比较,这将允许内部 broadcasting
个 b
元素沿着最后三个维度。然后,我们将它与 a
相乘,就像在原始代码中所做的那样,得到所需的输出。
因此,实施将是 -
out = a*(b == np.arange(1,5)[:,None,None,None])
When/how 使用 ...
(省略号):
我们使用 ...
(省略号),当尝试将新轴添加到多维数组中时,我们不想为每个维度指定 colons
。因此,要使 a
成为一个 4D
数组,最后一个 dim 是一个单例,我们会这样做:a[:,:,:,None]
。打字太多了!所以,我们在那里使用 ...
来帮助我们:a[...,None]
。请注意,无论维数如何,都会使用此 ...
符号。因此,如果 a
是一个 5D
数组,并且要在其中添加一个新轴作为最后一个轴,我们将执行 a[:,:,:,:,:,None]
或简单地使用省略号:a[...,None]
。不错吧!