Python中的数组大小差异

3

我有一个与Python数组形状相关的问题。

数组大小(2, )(2, 1)之间有什么区别?

我试图将这两个数组相加。然而,我得到了以下错误:

形状为(2, )的不可广播输出操作数与广播形状(2, 2)不匹配


你是想要将数组的值相加还是将数组[2]添加到数组[2, 2]中? - Shodmoth
@Shadmoth,楼主几乎肯定是在指 numpy 数组的形状属性。 - juanpa.arrivillaga
@yx131,第一个是1项元组,第二个是2项元组。对于numpy数组,“(2,)”表示具有2个项目的1维数组的形状,“(2,2)”表示具有2行和2列的2维数组(矩阵)的形状。如果您想要添加2个数组,则它们的形状应该相同,或者它们应该遵循numpy广播规则 - hygull
4个回答

2
在原始内存中没有区别,但在逻辑上,一种是由两个值组成的一维数组,另一种是二维数组(其中一个维度恰好为1)。这种逻辑区分对于 numpy 非常重要;当你尝试将他们相加时,它想要创建一个新的2x2数组,其中顶行是 (2, 1) 数组的顶部“行”与 (2,) 数组中每个值的和。如果你使用 '+=' 来完成这个操作,就表示你期望能够就地修改 (2,) 数组,但这是不可能的,因为需要重新调整大小(这是 numpy 不会做到的)。如果你将代码从以下内容更改:
arr1 += arr2

to:

arr1 = arr1 + arr2

它将愉快地创建一个新的(2, 2)数组。或者,如果目标是让2x1的数组像一个平坦的1D数组一样工作,你可以使用flatten函数:

alreadyflatarray += twodarray.flatten()

0

(2,) 是一维数组,(2,1) 是只有一列的矩阵

您可以通过使用 np.zero 并传递所需的形状来轻松地创建全零数组,从而清楚地看到它们之间的区别:

>>> np.zeros((2,))
array([0., 0.])

>>> np.zeros((2,1))
array([[0.],
       [0.]])

0

@yx131,你可以看下面的代码,以便清晰地了解元组及其在定义numpy数组形状中的使用。

注意: 不要忘记查看下面的代码,它有关于numpy广播相关问题的解释。

另外请查看numpy的广播规则:https://docs.scipy.org/doc/numpy/user/basics.broadcasting.html

在编程中,(2)(2,)之间有一个区别。第一个是字面值2,而第二个是一个元组。 (2,)是一个包含1个项目的元组,(2, 2)是一个包含2个项目的元组。在代码示例中很清楚。 注意:对于numpy数组来说,(2,)表示包含2个项目的一维数组的形状,(2, 2)表示包含2行2列的二维数组(矩阵)的形状。如果要将两个数组相加,则它们的形状应该相同。
v = (2)   # Assignment of value 2
t = (2,)  # Comma is necessary at the end of item to define 1 item tuple, it is not required in case of list
t2 = (2, 1)  # 2 item tuple
t3 = (3, 4)  # 2 item tuple

print(v, type(v))
print(t, type(t))
print(t2, type(t2))
print(t3, type(t3))

print(t + t2)
print(t2 + t3)

"""
2 <class 'int'>
(2,) <class 'tuple'>
(2, 1) <class 'tuple'>
(3, 4) <class 'tuple'>
(2, 2, 1)
(2, 1, 3, 4)
"""

现在,让我们看一下下面的代码,来找出与广播相关的错误。这都与维度有关。
# Python 3.5.2

import numpy as np

arr1 = np.array([1, 4]);
arr2 = np.array([7, 6, 3, 8]);
arr3 = np.array([3, 6, 2, 1]);

print(arr1, ':', arr1.shape)
print(arr2, ":", arr2.shape)
print(arr3, ":", arr3.shape)
print ("\n")
"""
[1 4] : (2,)
[7 6 3 8] : (4,)
[3 6 2 1] : (4,)
"""

# Changing shapes (dimensions)
arr1.shape = (2, 1)
arr2.shape = (2, 2)
arr3.shape = (2, 2)

print(arr1, ':', arr1.shape)
print(arr2, ":", arr2.shape)
print(arr3, ":", arr3.shape)
print("\n")
print(arr1 + arr2)
"""
[[1]
 [4]] : (2, 1)
[[7 6]
[3 8]] : (2, 2)
[[3 6]
 [2 1]] : (2, 2)


[[ 8  7]
 [ 7 12]]
"""

arr1.shape = (2, )
print(arr1, arr1.shape)
print(arr1 + arr2)
"""
[1 4] (2,)
[[ 8 10]
 [ 4 12]]
"""

# Code with error(Broadcasting related)
arr2.shape = (4,)
print(arr1+arr2)
"""
Traceback (most recent call last):
  File "source_file.py", line 53, in <module>
    print(arr1+arr2)
ValueError: operands could not be broadcast together 
with shapes (2,) (4,) 
"""

所以在你的情况下,问题与需要添加的不匹配的维度有关(根据numpy的广播)。谢谢。


0
创建一个形状为(2,)的数组。
In [164]: a = np.array([3,6])
In [165]: a
Out[165]: array([3, 6])        
In [166]: a.shape
Out[166]: (2,)
In [167]: a.reshape(2,1)
Out[167]: 
array([[3],
       [6]])
In [168]: a.reshape(1,2)
Out[168]: array([[3, 6]])

第一个显示为简单列表 [3,6]。第二个则是具有 2 个嵌套列表的列表。第三个则是具有一个嵌套列表和 2 个项目的列表。因此,形状和列表嵌套之间存在着一致的关系。

In [169]: a + a
Out[169]: array([ 6, 12])                # shape (2,)
In [170]: a + a.reshape(1,2)
Out[170]: array([[ 6, 12]])             # shape (1,2)
In [171]: a + a.reshape(2,1)
Out[171]: 
array([[ 6,  9],                        # shape (2,2)
       [ 9, 12]])

维度的行为如下:

(2,) + (2,) => (2,) (2,) + (1,2) => (1,2) + (1,2) => (1,2) (2,) + (2,1) => (1,2) + (2,1) => (2,2) + (2,2) => (2,2)

这意味着较低维度的数组可以通过添加前导大小为1的维度来扩展到匹配的维度数量。

并且大小为1的维度可以更改以匹配相应的维度。

我怀疑您在执行 a += ... 时遇到了错误(如果是这样,您应该清楚地说明)。

In [172]: a += a
In [173]: a += a.reshape(1,2)
....
ValueError: non-broadcastable output operand with shape (2,) 
    doesn't match the broadcast shape (1,2)

In [175]: a += a.reshape(2,1)
...
ValueError: non-broadcastable output operand with shape (2,) 
    doesn't match the broadcast shape (2,2)

使用 a+=... 进行加法运算时,结果的形状被固定为 (2,),这是由 a 的形状所决定的。但正如上面所述,这两个加法操作会生成形状为 (1,2) 和 (2,2) 的结果,它们与 (2,) 不兼容。

同样的推理可以解释这些加法操作和错误:

In [176]: a1 = a.reshape(1,2)
In [177]: a1 += a                
In [178]: a1
Out[178]: array([[12, 24]])
In [179]: a2 = a.reshape(2,1)
In [180]: a2 += a
...
ValueError: non-broadcastable output operand with shape (2,1) 
    doesn't match the broadcast shape (2,2)
In [182]: a1 += a2
...
ValueError: non-broadcastable output operand with shape (1,2) 
    doesn't match the broadcast shape (2,2)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接