通常对于两个numpy数组的相加、相减以及相乘都是对应元素之间的操作,这种操作要求被操作的两个数据具有相同的形状(shape)。
广播机制主要应用在两个数组的形状不相同的时候,这时可以通过扩展数组的方法来实现相加、相减、相乘等操作,这种机制叫做广播(broadcasting)。
广播的两种情况
两个数组的后缘维度(trailing dimension,即从末尾开始算起的维度)的轴长度相符,或其中的一方的某个维度的长度为1,则认为它们是广播兼容的。广播会在缺失和(或)长度为1的维度上进行。
这句话乃是理解广播的核心。广播主要发生在两种情况,一种是两个数组的维数不相等,但是它们的后缘维度的轴长相符;另外一种是有一方的某个维度的长度为1。
情况一:后缘维度的轴长度相符
我们来看一个例子:
import numpy as np arr1 = np.array([[0, 0, 0],[1, 1, 1],[2, 2, 2], [3, 3, 3]]) #arr1.shape = (4,3) arr2 = np.array([1, 2, 3]) #arr2.shape = (3,) arr_sum = arr1 + arr2 print(arr_sum) 输出结果如下: [[1 2 3] [2 3 4] [3 4 5] [4 5 6]]
上例中arr1的shape为(4,3),arr2的shape为(3,)。可以说前者是二维的,而后者是一维的。但是它们的后缘维度相等,arr1的第二维长度为3,和arr2的维度相同。arr1和arr2的shape并不一样,但是它们可以执行相加操作,这就是通过广播完成的,在这个例子当中是将arr2沿着0轴进行扩展。
上面程序当中的广播如下图所示:
从上面的图可以看到,(3,4,2)和(4,2)的维度是不相同的,前者为3维,后者为2维。但是它们后缘维度的轴长相同,都为(4,2),所以可以沿着0轴进行广播。
同样,还有一些例子:(4,2,3)和(2,3)是兼容的,(4,2,3)还和(3)是兼容的,后者需要在两个轴上面进行扩展。
情况二:有一方的某个维度的长度为1
我们来看下面的例子:
import numpy as np arr1 = np.array([[0, 0, 0],[1, 1, 1],[2, 2, 2], [3, 3, 3]]) #arr1.shape = (4,3) arr2 = np.array([[1],[2],[3],[4]]) #arr2.shape = (4, 1) arr_sum = arr1 + arr2 print(arr_sum) 输出结果如下: [[1 1 1] [3 3 3] [5 5 5] [7 7 7]]
arr1的shape为(4,3),arr2的shape为(4,1),它们都是二维的,但是第二个数组在1轴上的长度为1,所以,可以在1轴上面进行广播,如下图所示:
在这种情况下,其中有一个轴的长度为1,两个数组的维度要保证相等的话,就会沿着长度为1的轴进行扩展。这样的例子还有:(4,6)和(1,6) 。(3,5,6)和(1,5,6)、(3,1,6)、(3,5,1),后面三个分别会沿着0轴,1轴,2轴进行广播。
除此之外,当两个数组同时出现有维度长度为1的情况时,可以对这两个维度同时进行扩展。
import numpy as np
a = np.random.random([4,1])
b = np.random.random([1,3])
print(a)
print(b)
print(a+b)
输出如下:
[[0.52516774] [0.91748993] [0.05884029] [0.11340764]] [[0.7499946 0.12830281 0.01696532]] [[1.27516233 0.65347055 0.54213306] [1.66748453 1.04579274 0.93445525] [0.80883489 0.1871431 0.07580561] [0.86340224 0.24171045 0.13037296]]