Numpy中的广播Broadcast用法

广播仅仅是一组用于在不同大小的数组上应用二元ufuncs(加法、减法、乘法等)的规则。

对于相同大小的数组,二元操作按元素逐元素执行。

In[1]: import numpy as np
In[2]: a = np.array([0, 1, 2])
b = np.array([5, 5, 5])
a + b
Out[2]: array([5, 6, 7])

广播允许在不同大小的数组上执行这些类型的二元操作。

在NumPy中,广播遵循一组严格的规则来确定两个数组之间的操作:

规则1:如果两个数组在维度的数量上有差异,那么维度较少的数组的形状就会被用1填充在它的前导(左)边
规则2:如果两个数组的形状在任何维度上都不匹配,但等于1,那么在这个维度中,形状为1的数组将被拉伸以匹配另一个形状。

规则3:如果在任何维度上,大小都不一致,且两者都不等于1,就会出现错误。

下面看例子:

In[1]: import numpy as np
In[2]: M = np.ones((2, 3))
       a = np.arange(3)

In [3]: M.shape
Out[3]: (2, 3)
In [4]: a.shape
Out[4]: (3,)

根据规则1,数组a的维数更少,所以我们用1填充在它的左边。

M.shape -> (2, 3)
a.shape -> (1, 3)

根据规则2,我们现在看到第一个维度不匹配,所以我们扩展这个维度来匹配。

M.shape -> (2, 3)
a.shape -> (2, 3)

现在就可以相加了,而且最终的shape是(2, 3)。我们验证一下:

In [5]: (M + a).shape
Out[5]: (2, 3)

再看一个例子:

In[6]: a = np.arange(3).reshape((3, 1))
        b = np.arange(3)

In [7]: a.shape
Out[7]: (3, 1)
In [8]: b.shape
Out[8]: (3,)

根据规则1,数组b的维数更少,所以我们用1填充在它的左边。

a.shape -> (3, 1)
b.shape -> (1, 3)

规则2告诉我们,我们将每一个是1的都升级,以匹配另一个数组的相应大小。

a.shape -> (3, 3)
b.shape -> (3, 3)

现在可以相加了,验证下:

In [9]: (a + b).shape
Out[9]: (3, 3)

下面看一个满足规则3的例子:

In [15]: M = np.ones((3, 2))
In [16]: a = np.arange(3)

In [16]: M.shape
Out[16]: (3, 2)
In [17]: a.shape
Out[17]: (3,) 

根据规则1,

M.shape -> (3, 2)
a.shape -> (1, 3)

根据规则2,a的第一个维度被拉伸到与M匹配:

M.shape -> (3, 2)
a.shape -> (3, 3)

现在根据规则3,如果我们进行加的操作,会出现错误,验证下:

In [18]: M + a
Traceback (most recent call last):

  File "<ipython-input-18-8cac1d547906>", line 1, in <module>
    M + a

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

注意这里可能出现的混淆:你可以想象出a和M的兼容性,比方说,用1在右边而不是左边填充a。但这不是广播规则的工作方式!还要注意的是,虽然我们一直在关注+运算符,但是这些广播规则适用于任何二元ufunc。

参考:

《Python Data Science Handbook》

 https://docs.scipy.org/doc/numpy-dev/user/basics.broadcasting.html

阅读更多

没有更多推荐了,返回首页