写点什么

NumPy 之: 理解广播

发布于: 2021 年 05 月 12 日

简介

广播描述的是 NumPy 如何计算不同形状的数组之间的运算。如果是较大的矩阵和较小的矩阵进行运算的话,较小的矩阵就会被广播,从而保证运算的正确进行。

本文将会以具体的例子详细讲解 NumPy 中广播的使用。

基础广播

正常情况下,两个数组需要进行运算,那么每个数组的对象都需要有一个相对应的值进行计算才可以。比如下面的例子:

a = np.array([1.0, 2.0, 3.0])b = np.array([2.0, 2.0, 2.0])a * barray([ 2.,  4.,  6.])
复制代码

但是如果使用 Numpy 的广播特性,那么就不必须元素的个数准确对应。

比如,我们可以讲一个数组乘以常量:

a = np.array([1.0, 2.0, 3.0])>>> b = 2.0>>> a * barray([ 2.,  4.,  6.])
复制代码

下面的例子和上面的例子是等价的,Numpy 会自动将 b 进行扩展。

NumPy 足够聪明,可以使用原始标量值而无需实际制作副本,从而使广播操作尽可能地节省内存并提高计算效率。

第二个示例中的代码比第一个示例中的代码更有效,因为广播在乘法过程中移动的内存更少(b 是标量而不是数组)。

广播规则

如果两个数组操作,NumPy 会对两个数组的对象进行比较,从最后一个维度开始,如果两个数组的维度满足下面的两个条件,我们就认为这两个数组是兼容的,可以进行运算:

  1. 维度中的元素个数是相同的

  2. 其中一个维数是 1

如果上面的两个条件不满足的话,就会抛出异常: ValueError: operands could not be broadcast together。

维度中的元素个数是相同的,并不意味着要求两个数组具有相同的维度个数。

比如表示颜色的256x256x3 数组,可以和一个一维的 3 个元素的数组相乘:

Image  (3d array): 256 x 256 x 3Scale  (1d array):             3Result (3d array): 256 x 256 x 3
复制代码

相乘的时候,维度中元素个数是 1 的会被拉伸到和另外一个维度中的元素个数一致:

A      (4d array):  8 x 1 x 6 x 1B      (3d array):      7 x 1 x 5Result (4d array):  8 x 7 x 6 x 5
复制代码

上面的例子中,第二维的 1 被拉伸到 7,第三维的 1 被拉伸到 6,第四维的 1 被拉伸到 5。

还有更多的例子:

B      (1d array):      1Result (2d array):  5 x 4
A (2d array): 5 x 4B (1d array): 4Result (2d array): 5 x 4
A (3d array): 15 x 3 x 5B (3d array): 15 x 1 x 5Result (3d array): 15 x 3 x 5
A (3d array): 15 x 3 x 5B (2d array): 3 x 5Result (3d array): 15 x 3 x 5
A (3d array): 15 x 3 x 5B (2d array): 3 x 1Result (3d array): 15 x 3 x 5
复制代码

下面是不匹配的例子:

A      (1d array):  3B      (1d array):  4 # trailing dimensions do not match
A (2d array): 2 x 1B (3d array): 8 x 4 x 3 # second from last dimensions mismatched
复制代码

再举个实际代码的例子:

>>> x = np.arange(4)>>> xx = x.reshape(4,1)>>> y = np.ones(5)>>> z = np.ones((3,4))
>>> x.shape(4,)
>>> y.shape(5,)
>>> x + yValueError: operands could not be broadcast together with shapes (4,) (5,)
>>> xx.shape(4, 1)
>>> y.shape(5,)
>>> (xx + y).shape(4, 5)
>>> xx + yarray([[ 1., 1., 1., 1., 1.], [ 2., 2., 2., 2., 2.], [ 3., 3., 3., 3., 3.], [ 4., 4., 4., 4., 4.]])
>>> x.shape(4,)
>>> z.shape(3, 4)
>>> (x + z).shape(3, 4)
>>> x + zarray([[ 1., 2., 3., 4.], [ 1., 2., 3., 4.], [ 1., 2., 3., 4.]])
复制代码

广播还提供了一个非常方便的进行两个 1 维数组进行外部乘积的运算:

>>> a = np.array([0.0, 10.0, 20.0, 30.0])>>> b = np.array([1.0, 2.0, 3.0])>>> a[:, np.newaxis] + barray([[  1.,   2.,   3.],       [ 11.,  12.,  13.],       [ 21.,  22.,  23.],       [ 31.,  32.,  33.]])
复制代码

其中 a[:, np.newaxis] 将 1 维的数组转换成为 4 维的数组:

In [230]: a[:, np.newaxis]Out[230]:array([[ 0.],       [10.],       [20.],       [30.]])
复制代码

本文已收录于 http://www.flydean.com/07-python-numpy-broadcasting/

最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!

欢迎关注我的公众号:「程序那些事」,懂技术,更懂你!

发布于: 2021 年 05 月 12 日阅读数: 14
用户头像

关注公众号:程序那些事,更多精彩等着你! 2020.06.07 加入

最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧,尽在公众号:程序那些事!

评论

发布
暂无评论
NumPy之:理解广播