乐趣区

关于numpy:NumPy之理解广播

简介

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

本文将会以具体的例子具体解说 NumPy 中播送的应用。

根底播送

失常状况下,两个数组须要进行运算,那么每个数组的对象都须要有一个绝对应的值进行计算才能够。比方上面的例子:

a = np.array([1.0, 2.0, 3.0])
b = np.array([2.0, 2.0, 2.0])
a * b
array([2.,  4.,  6.])

然而如果应用 Numpy 的播送个性,那么就不必须元素的个数精确对应。

比方,咱们能够讲一个数组乘以常量:

a = np.array([1.0, 2.0, 3.0])
>>> b = 2.0
>>> a * b
array([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 3
Scale  (1d array):             3
Result (3d array): 256 x 256 x 3

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

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

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

还有更多的例子:

B      (1d array):      1
Result (2d array):  5 x 4

A      (2d array):  5 x 4
B      (1d array):      4
Result (2d array):  5 x 4

A      (3d array):  15 x 3 x 5
B      (3d array):  15 x 1 x 5
Result (3d array):  15 x 3 x 5

A      (3d array):  15 x 3 x 5
B      (2d array):       3 x 5
Result (3d array):  15 x 3 x 5

A      (3d array):  15 x 3 x 5
B      (2d array):       3 x 1
Result (3d array):  15 x 3 x 5

上面是不匹配的例子:

A      (1d array):  3
B      (1d array):  4 # trailing dimensions do not match

A      (2d array):      2 x 1
B      (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 + y
ValueError: operands could not be broadcast together with shapes (4,) (5,)

>>> xx.shape
(4, 1)

>>> y.shape
(5,)

>>> (xx + y).shape
(4, 5)

>>> xx + y
array([[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 + z
array([[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] + b
array([[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/

最艰深的解读,最粗浅的干货,最简洁的教程,泛滥你不晓得的小技巧等你来发现!

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

退出移动版