簡介
廣播描述的是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
如果上面的兩個條件不滿足的話,就會丟擲異常: 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/
最通俗的解讀,最深刻的乾貨,最簡潔的教程,眾多你不知道的小技巧等你來發現!
歡迎關注我的公眾號:「程式那些事」,懂技術,更懂你!