问题描述
当我尝试从形状(1,)到形状()进行现场广播时,numpy会引发ValueError: non-broadcastable output operand with shape () doesn't match the broadcast shape (1,)
。我understand认为 inplace运算符旨在与输入在相同的内存块上进行操作,这就是为什么您不能从形状(5,)就地广播的原因变成形状(1,)。但是,对于形状(1,)(或大小为1的任何数组),其大小与形状为()的标量相同。那么为什么我不能执行就位操作a += b
,其中a
的形状为()
而b
的形状为(1,)
?相反的起作用。
代码:
a = np.array(0)
b = np.array([0])
a + b # valid
b += a # valid
a += b # ValueError
结果:
ValueError: non-broadcastable output operand with shape () doesn't match the broadcast shape (1,)
解决方法
虽然我们可以从测试中获得一些想法,但它可能取决于实现细节(在编译后的代码中)。
In [81]: a = np.array(0); b = np.array([0])
In [82]: a,b
Out[82]: (array(0),array([0]))
两者之和产生一个(1,)数组。这与广播规则一致。 a
广播到(1,),然后求和。
In [83]: a+b
Out[83]: array([0])
我们可以添加()或标量:
In [84]: a += a
但是您的错误情况显然是试图将这个(1,)总和放入()目标:
In [85]: a += b
Traceback (most recent call last):
File "<ipython-input-85-294cacd62d6f>",line 1,in <module>
a += b
ValueError: non-broadcastable output operand with shape () doesn't match the broadcast shape (1,)
可以使用正确的索引为a
分配一个值:
In [86]: a[:] = 1
Traceback (most recent call last):
File "<ipython-input-86-aa15caba710a>",in <module>
a[:] = 1
IndexError: too many indices for array: array is 0-dimensional,but 1 were indexed
In [87]: a[()] =2
In [88]: a
Out[88]: array(2)
In [89]: a[...] = a+b
In [90]: a
Out[90]: array(2)
但是显然+=
这种分配确实使用了这种更通用的分配方法。
我们也不能+=
将(1,1)变成(1,):
In [92]: b += np.array([[1]])
Traceback (most recent call last):
File "<ipython-input-92-15b525996e5d>",in <module>
b += np.array([[1]])
ValueError: non-broadcastable output operand with shape (1,) doesn't match the broadcast shape (1,1)
显然,+=
类型的分配无法减少数字维度。
作为旁注,可以将(1,)数组广播为(0,)
In [100]: c = np.zeros((0,))
In [101]: c += b
In [102]: c
Out[102]: array([],dtype=float64)
也就是说,在第二个广播步骤中(在匹配尺寸数之后),可以将尺寸1的尺寸减小为0。但这与将尺寸数从n+1
更改为n
不同。