说明
NumPy 教程 持续更新中,提供建议、纠错、催更等加作者微信: gairuo123(备注:pandas教程)和关注公众号「盖若」ID: gairuo。跟作者学习,请进入 Python学习课程。欢迎关注作者出版的书籍:《深入浅出Pandas》 和 《Python之光》。
广播(Array Broadcasting)描述的是 NumPy 如何计算不同形状的数组之间的运算。如果是较大的矩阵和较小的矩阵进行运算的话,较小的矩阵就会被广播,从而保证运算的正确进行。
术语广播描述了 NumPy 如何在算术运算中处理具有不同形状的数组,受限于某些数据条件,较小的数组在较大的数组中“广播”,以便它们具有兼容的形状。广播提供了一种对数组操作进行矢量化的方法,这样循环就可以用 C 而不是 Python 进行。这样做就没有了不必要的数据拷贝,通常使算法高效的实现。然而,在有些情况下,广播也有自己的缺点,因为它会导致内存的低效使用,从而降低计算速度。
NumPy 操作通常是按一一对应元素对数组执行的。在最简单的情况下,两个数组具有完全相同的形状,如下例所示:
a = np.array([1.0, 2.0, 3.0])
b = np.array([2.0, 2.0, 2.0])
a * b
# array([ 2., 4., 6.])
当数组的形状满足某些约束时,NumPy 的广播规则会放宽这个约束。最简单的广播示例是在操作中组合数组和标量值时:
a = np.array([1.0, 2.0, 3.0])
b = 2.0
a * b
# array([ 2., 4., 6.])
这个结果与前面的例子类似,其中 b 是一个数组。我们可以认为标量 b 在算术运算中被拉伸成与 a 形状相同的数组。b 中的新元素只是原始标量的副本。这里的拉伸类比只是概念上的,因为 NumPy 足够聪明,可以使原始的标量值无需实际复制,因此让广播操作的内存和计算之间的效率尽可能高。
第二个示例中的代码比第一个示例中的代码效率更高,因为广播在乘法期间移动的内存更少(b 是标量而不是数组)。
广播的原则是,如果两个数组的后缘维度(即:从末尾开始算起的维度)的轴长相符或其中一方的长度为 1,则认为它们是广播兼容的,广播会在缺失和(或)长度为 1 的轴上进行。
在两个数组上操作时,NumPy 会按元素比较它们的形状。它从尾缘(即最右边的)维度开始,然后向左运行。当:
如果不满足这些条件,将引发 ValueError: operands could not be broadcast together
(操作数无法一起广播异常),指示数组具有不兼容的形状。结果数组的大小是沿输入的每个轴不是 1 的大小。
数组不需要具有相同的维数。例如,如果有一个 256x256x3 的 RGB 值数组,并且希望按不同的值缩放图像中的每种颜色,则可以将图像乘以一个具有 3 个值的一维数组。根据广播规则排列这些阵列的后轴大小,表明它们是兼容的:
Image (3d array): 256 x 256 x 3
Scale (1d array): 3
Result (3d array): 256 x 256 x 3
当比较的任何一个维度是一个时,将使用另一个维度。换句话说,尺寸为1的尺寸标注将被拉伸或“复制”以匹配另一个尺寸标注。
在下面的示例中,A和B阵列都具有长度为1的轴,这些轴在广播操作期间被扩展到更大的尺寸:
A (4d array): 8 x 1 x 6 x 1
B (3d array): 7 x 1 x 5
Result (4d array): 8 x 7 x 6 x 5
下面是更多的例子:
A (2d array): 5 x 4
B (1d array): 1
Result (2d array): 5 x 4
A (2d array): 5 x 4
B (1d array): 4
Result (2d array): 5 x 4
A (3d array): 15 x 3 x 5
B (3d array): 15 x 1 x 5
Result (3d array): 15 x 3 x 5
A (3d array): 15 x 3 x 5
B (2d array): 3 x 5
Result (3d array): 15 x 3 x 5
A (3d array): 15 x 3 x 5
B (2d array): 3 x 1
Result (3d array): 15 x 3 x 5
以下是不广播的形状示例:
A (1d array): 3
B (1d array): 4 # trailing dimensions do not match
A (2d array): 2 x 1
B (3d array): 8 x 4 x 3 # second from last dimensions mismatched
广播实践的一个例子:
x = np.arange(4)
xx = x.reshape(4,1)
y = np.ones(5)
z = np.ones((3,4))
x.shape
# (4,)
y.shape
# (5,)
x + y
# ValueError: operands could not be
# broadcast together with shapes (4,) (5,)
xx.shape
# (4, 1)
y.shape
# (5,)
(xx + y).shape
# (4, 5)
xx + y
'''
array([[ 1., 1., 1., 1., 1.],
[ 2., 2., 2., 2., 2.],
[ 3., 3., 3., 3., 3.],
[ 4., 4., 4., 4., 4.]])
'''
x.shape
# (4,)
z.shape
# (3, 4)
(x + z).shape
# (3, 4)
x + z
'''
array([[ 1., 2., 3., 4.],
[ 1., 2., 3., 4.],
[ 1., 2., 3., 4.]])
'''
广播提供了一种获取两个阵列的外积(或任何其他外部操作)的方便方法。以下示例显示两个一维数组的外部加法操作:
a = np.array([0.0, 10.0, 20.0, 30.0])
b = np.array([1.0, 2.0, 3.0])
a[:, np.newaxis] + b
'''
array([[ 1., 2., 3.],
[ 11., 12., 13.],
[ 21., 22., 23.],
[ 31., 32., 33.]])
'''
这里 newaxisindex 操作符将一个新轴插入到数组中,使其成为二维4x1数组。将4x1数组与具有形状(3,)的b组合,得到一个4x3数组。
更新时间:2021-06-29 11:06:28 标签:numpy 广播