背景
因为数组之间的很多计算都是逐元素对应进行的,这就对参与运算的数组尺寸有一定的要求才行。
import numpy as np
a = np.array([[10, 20, 30], [40, 50, 60]])
b = np.array([[1, 1, 1], [1, 1, 1]])
print(a + b)
# [[11 21 31]
# [41 51 61]]
如果数组维度很高,数据量很大,这种给数组中每个元素 加1 的操作会需要专门构建一个同尺寸的数组b
,在传统的规则下计算非常不灵活。
广播机制
广播机制是NumPy
在处理不同「尺寸」数组之间算数运算的一种方式。当两种不同尺寸的数组进行对应元素数值运算时,可以按照一定的规则将小尺寸数组进行拉伸,使两个数组达到相同的尺寸,从而进行运算。
当然,这种拉伸只是理解意义上的,NumPy
底层并没有进行这样的操作,毕竟拷贝数据增加尺比较影响效率,底层当然是使用C
语言的循环去解决的啦。
import numpy as np
a = np.arange(10) # 1 x 10 dimension
b = np.array([2]) # 1 x 1 dimension
c = a + b # 1 x 10 dimension
print(c) # [ 2 3 4 5 6 7 8 9 10 11]
可以形式上理解为,数组b
在计算过程中扩展成了和a
相同1 x 10
尺寸的数组,实现了两个数组中各元素对齐,从而完成了运算。甚至可以直接把b
写成常数。
import numpy as np
a = np.arange(3)
b = 6
c = a * b
print(c) # [ 0 6 12]
看一个特殊点的扩展案例:
import numpy as np
a = np.ones((3, 2)) # 3 x 2 dimension
b = np.ones((1, 2)) # 1 x 2 dimension
c = a + b
"""
a b a b(after broadcasting)
1 1 1 1 1 1 1 1
1 1 + ==> 1 1 + (1) (1)
1 1 1 1 (1) (1)
"""
print(c)
# [[2. 2.]
# [2. 2.]
# [2. 2.]]
扩展的数组只能沿着一个维度进行扩展,看一个更特殊的扩展案例,进行运算的两个数组都进行了尺寸扩展。
import numpy as np
a = np.ones((3, 1))
b = np.ones(1, 2)
c = a + b
"""
a b a(after) b(after)
1 1 1 1 (1) 1 1
1 + ==> 1 (1) + (1) (1)
1 1 (1) (1) (1)
"""
print(c)
# [[2. 2.]
# [2. 2.]
# [2. 2.]]
总结一下:
- 在每个维度上,总是小尺寸的数组扩展成另一个数组的尺寸。
- 每个数组都只能朝一个维度进行扩展。
- 这种扩展只是便于理解,
NumPy
底层并未通过扩展形成新的数组。