Numpy 广播机制
1. 广播的引出
\(numpy\) 两个数组相加、相减、相乘都是对应元素之间的操作。
示例:\(numpy\) 数组相乘。
import numpy as np
x = np.array([[2,2,3],[1,2,3]])
y = np.array([[1,1,3],[2,2,4]])
print(x*y) # numpy 中的数组相乘是对应元素的乘积,与线性代数中的矩阵相乘不一样
[[ 2 2 9]
[ 2 4 12]]
当两个数组的形状不同的时候,可以通过扩展数组的方法实现相加、相减、相乘等操作,这种机制叫广播(\(broadcasting\))。
示例:二维数组减去一维数组。
import numpy as np
arr = np.random.randn(4,3) # shape(4,3)
arr_mean = arr.mean(0) # shape(3,)
demeaned = arr -arr_mean
print(demeaned)
虽然维度不同,但可进行相减操作,这就是通过广播机制来实现的。
2. 广播的原则
广播原则:如果两个数组的后援维度(\(trailing\ dimension\),即从末尾开始算起的维度)的轴长度相符或其中一方的长度为 \(1\),则认为是广播兼容的。广播会在缺失和(或)长度为 \(1\) 的维度上进行。
广播主要发生在两种情况:
- 两个数组的维数不相等,但后援维度的轴长度相符。
- 后援维度中有一方的长度为 \(1\)。
2.1 数组维数不同,后援维度的轴长相符
示例:一维数组在轴 \(axis=0\) 上广播。
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\) 的维度相同。所以可以执行相加操作,这就是通过广播完成的,在这个例子中是将 \(arr2\) 沿 \(axis=0\) 轴进行扩展。
一维数组在轴 \(0\) 上的广播
同样的例子还有:
三维数组在轴 \(0\) 上的广播
2.2 数组维数相同,其中有个轴为1
示例:一维数组在轴 \(axis=1\) 上广播。
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\) 上的广播