这在
NumPy广播文档中有很好的解释 -
通用广播规则
在操作两个数组时,NumPy会逐个元素地比较它们的形状。 它从后面的维度开始,并向前工作。当两个维度满足以下条件之一时,它们是兼容的:
- 它们相等,或者
- 其中一个是1
如果不满足这些条件,则会引发ValueError: frames are not aligned
异常,表示数组具有不兼容的形状。 结果数组的大小是输入数组每个维度的最大大小。
数组不需要具有相同数量的维度。例如,如果您有一个256x256x3的RGB值数组,并且想要按不同的值缩放图像中的每种颜色,则可以将图像乘以具有3个值的一维数组。根据广播规则对齐这些数组的尾部轴的大小,
(重点标记)
当使用形状为(4,)
的数组和形状为(4,1)
的数组进行操作时,首先将第一个数组广播到(1,4)
(因为它从尾部维度开始,并向前替换它们为1
,因此(4,)
变成了(1,4)
),然后将它们一起操作,创建一个形状为(4,4)
的数组。
而形状为(4,1)
的数组不被视为向量。它是一个二维数组。
如果x
是array([[1, 2, 3, 4]])
,即形状为(1,4)
的数组,则会发生相同的情况 -
示例 -
In [70]: y
Out[70]:
array([[1],
[2],
[3],
[4]])
In [71]: x = np.array([x])
In [72]: x
Out[72]: array([[1, 2, 3, 4]])
In [73]: x - y
Out[73]:
array([[ 0, 1, 2, 3],
[-1, 0, 1, 2],
[-2, -1, 0, 1],
[-3, -2, -1, 0]])
广播始终从最后一个维度开始匹配,因此尝试以下操作会引发错误 -
In [79]: y = np.array([[1,2,3,4],[5,6,7,8]])
In [80]: y.shape
Out[80]: (2, 4)
In [81]: x = np.array([1,2])
In [82]: x.shape
Out[82]: (2,)
In [83]: y - x
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-83-4abb3bd0a148> in <module>()
----> 1 y - x
ValueError: operands could not be broadcast together with shapes (2,4) (2,)
这是因为首先它会检查两个数组的最后一个维度,一个是
4
,另一个是
2
,根据规则,它们不匹配,因此会抛出错误。如果
x
的形状是
(2,1)
,那么就可以工作。例如:
In [84]: y - x.reshape((2,1))
Out[84]:
array([[0, 1, 2, 3],
[3, 4, 5, 6]])