天天看點

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/

最通俗的解讀,最深刻的幹貨,最簡潔的教程,衆多你不知道的小技巧等你來發現!

歡迎關注我的公衆号:「程式那些事」,懂技術,更懂你!