为什么 numpy 的广播有时允许比较不同长度的数组?

Why does numpy's broadcasting sometimes allow comparing arrays of different lengths?

我正在尝试了解 numpy 的广播如何影响 np.allclose 的输出。

>>> np.allclose([], [1.])
True

我不明白为什么会这样,但这行不通:

>>> np.allclose([], [1., 2.])
ValueError: operands could not be broadcast together with shapes (0,) (2,)

这里的规则是什么?我在 numpy docs 中找不到任何关于空数组的内容。

除了影响任何其他功能外,广播不会以任何其他方式影响 np.allclose

在@cel 的评论中,[1.] 是维度 1,因此可以广播到任何其他维度,包括 0。另一方面,[1., 2.] 是维度 2,因此无法播放。

现在为什么要 allclose([],[1.]) == True?这实际上是有道理的:它意味着 [] 中的所有元素都接近 1.。相反的意思是 [] 中至少有一个元素不接近 1. 显然是 False 因为 [] 中根本没有元素。

另一种思考方式是问问自己,您实际会如何编码 allclose():

def allclose(array, target=1.):
    for x in array:
        if not isclose(x, target):
            return False
    return True

当用 [] 调用时,这将 return True

广播规则也适用于加法,

In [7]: np.array([])+np.array([1.])
Out[7]: array([], dtype=float64)

In [8]: np.array([])+np.array([1.,2.])
....

ValueError: operands could not be broadcast together with shapes (0,) (2,)

让我们看看形状。

In [9]: np.array([]).shape,np.array([1.]).shape,np.array([1,2]).shape
Out[9]: ((0,), (1,), (2,))

(0,) 和 (1,) - (1,) 可以调整以匹配另一个数组的形状。可以调整 1 维度以匹配另一个数组,例如从 1 增加到 3。但这里(显然)从 1 调整到 0。我通常不使用 0 维度的数组,但这看起来像是对更高维度的适当概括。

尝试 (0,) 和 (1,1)。结果是 (1,0):

In [10]: np.array([])+np.array([[1.]])
Out[10]: array([], shape=(1, 0), dtype=float64)

(0,), (1,1) => (1,0),(1,1) => (1,0)

对于第二种情况,形状为(0,)和(2,);没有任何尺寸 1 尺寸可以调整,因此出现错误。

形状 (0,) 和 (2,1) 广播(到 (2,0)):

In [12]: np.array([])+np.array([[1.,2]]).T
Out[12]: array([], shape=(2, 0), dtype=float64)