1°为什么以下代码返回False?我以为np.broadcast_to
会像np.repeat
一样增加数组的dimensin。
2°我可以用np.repeat
再现np.broadcast_to
给出的结果吗?
import numpy as np
n = 100
d = 10
A = np.random.uniform(size=(n,d))
np.all(np.broadcast_to(A.reshape(n,1,d),(n,d-1,d))==np.repeat(A,d-1).reshape(n,d-1,d))
3°更笼统,对于给定的形状(n,d)的射线A
,我如何用np.repeat(A,k).reshape((n,k,d))
再现np.broadcast_to
?
np.broadcast_to
为您提供array-wise重复,而np.repeat
为您提供element-wise重复行为,请参阅文档[1]和[2]中的示例。为了在这种情况下获得均等的输出,可以按如下方式更改重塑:
import numpy as np
n = 100
d = 10
A = np.random.uniform(size=(n,d))
A_bc = np.broadcast_to(A.reshape(n*d, 1), (n*d, d-1)).reshape(n, d-1, d)
A_rp = np.repeat(A, d-1).reshape(n, d-1, d)
np.all(A_rp == A_bc)
# True
注意:尽管timeit
表示broadcast_to
选项稍微快一些,但我不确定它实际上是否更节省内存。
这里发生了很多事情,使用包含少量标志值的数组来识别问题会更容易。这是一个易于使用的示例:
arr = np.array([[1, 2, 1, 2], [3, 4, 3, 4]]) # n = 2, d = 4
让我们看看broadcast_to
的作用:
broadcast_to
您可以使用>>> A.reshape(n, 1, d)
array([[[1, 2, 1, 2]],
[[3, 4, 3, 4]]])
>>> arr.broadcast_to(_, (n, d - 1, d))
array([[[1, 2, 1, 2],
[1, 2, 1, 2],
[1, 2, 1, 2]],
[[3, 4, 3, 4],
[3, 4, 3, 4],
[3, 4, 3, 4]]])
,tile
和tile
获得功能相似的数组。主要区别在于stack
不会在新维度中复制数据。相反,它会调整步幅,以使数组看起来具有正确的大小(如果您不小心,可能会导致意外行为,例如,写入缓冲区):stack
concatenate
concatenate
broadcast_to
:np.tile(arr.reshape(n, 1, d), (1, d - 1, 1))
这是扁平化的数组,其每个元素重复np.stack([arr] * (d - 1), axis=1)
次。显然,此处的重塑将与广播/平铺的版本不同:
np.concatenate([arr.reshape(n, 1, d)] * (d - 1), axis=1)
显然,逐元素重复与广播不同。但是,如果正确使用repeat
关键字,则实际上可以得到正确的结果:
repeat
[如果您想采用另一种方法,并且将数据包装在较短的行中,则可以使用>>> np.repeat(arr, d - 1) array([1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 3, 3, 3, 4, 4, 4])
和d - 1
的组合重新解释尺寸:
>>> _.reshape(n, d - 1, d)
array([[[1, 1, 1, 2],
[2, 2, 1, 1],
[1, 2, 2, 2]],
[[3, 3, 3, 4],
[4, 4, 3, 3],
[3, 4, 4, 4]]])
这里是转换的演练:
axis