什么是Broadcasting

2018-12-09 11:17 更新

Broadcasting

術(shù)語(yǔ) Broadcasting 描述了在算術(shù)運(yùn)算中 numpy 如何處理不同形狀的數(shù)組.在受到某些約束的情況下,較小的數(shù)組在較大的數(shù)組上“broadcasting”,以便它們具有兼容的形狀.broadcasting 提供了一種向量化數(shù)組操作的方法,使循環(huán)發(fā)生在 C 而不是 Python 中.這樣做不會(huì)造成不必要的數(shù)據(jù)副本,通常會(huì)導(dǎo)致高效的算法實(shí)現(xiàn).但是,在有些情況下,broadcasting 是一個(gè)壞主意,因?yàn)樗鼤?huì)導(dǎo)致內(nèi)存使用效率低下,從而減慢計(jì)算速度.

NumPy 操作通常是在每個(gè)元素的基礎(chǔ)上在數(shù)組對(duì)上完成的.在最簡(jiǎn)單的情況下,兩個(gè)數(shù)組必須具有完全相同的形狀,如下例所示:

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

當(dāng)數(shù)組的形狀滿足一定的約束時(shí),NumPy 的 broadcasting 規(guī)則放松了這個(gè)約束.最簡(jiǎn)單的 broadcasting 示例是在一個(gè)操作中組合一個(gè)數(shù)組和一個(gè)標(biāo)量值時(shí)發(fā)生的:

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

這個(gè)結(jié)果等同于前面的例子,其中 b 是一個(gè)數(shù)組.我們可以認(rèn)為標(biāo)量 b 在算術(shù)運(yùn)算過程中被拉伸成與 a 形狀相同的數(shù)組,b 中的新元素只是原始標(biāo)量的副本.拉伸的比喻只是概念上的.NumPy 足夠聰明,可以使用原始標(biāo)量值,而不需要實(shí)際制作副本,因此 broadcasting 操作盡可能具有記憶效率和計(jì)算效率.

第二個(gè)例子中的代碼比第一個(gè)例子中的代碼效率更高,因?yàn)樵诔朔?b是一個(gè)標(biāo)量而不是一個(gè)數(shù)組)中,廣播移動(dòng)的內(nèi)存較少.

一般broadcasting規(guī)則

在兩個(gè)數(shù)組上操作時(shí),NumPy 按照元素比較它們的形狀.它從尾隨的維度開始,并朝著前進(jìn)的方向前進(jìn).兩個(gè)維度是兼容的:

  1. 他們是相等的;
  2. 其中有一個(gè)是1

如果不滿足這些條件, 則會(huì)引發(fā)異常,ValueError: frames are not aligned,表明數(shù)組具有不兼容的形狀.結(jié)果數(shù)組的大小是沿輸入數(shù)組的每個(gè)維度的最大大小.

數(shù)組不需要有相同數(shù)量的維度.例如,如果您有一個(gè) 256x256x3的 RGB 值的數(shù)組,并且您想通過不同的值縮放圖像中的每個(gè)顏色,則可以將圖像乘以一個(gè)具有3個(gè)值的一維數(shù)組.根據(jù) broadcasting 規(guī)則排列這些數(shù)組尾隨軸的大小,表明它們是兼容的:

Image  (3d array): 256 x 256 x 3
Scale  (1d array):             3
Result (3d array): 256 x 256 x 3

當(dāng)比較的任何一個(gè)維度時(shí),使用另一個(gè)維度.換句話說,維度為1的維度被拉伸或“復(fù)制”以匹配另一維度.

在以下示例中,在 broadcasting 操作期間A,B數(shù)組都具有長(zhǎng)度為1的軸,這些軸在廣播操作期間展開為較大的大?。?/p>

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

以下是一些例子:

A      (2d array):  5 x 4
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

以下是不能 broadcasting 的形狀的示例:

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

 broadcasting 實(shí)踐中的一個(gè)例子:

>>> 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
<type 'exceptions.ValueError'>: shape mismatch: objects cannot be broadcast to a single shape

>>> 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.]])

 broadcasting 為兩個(gè)數(shù)組的外部產(chǎn)品(或任何其他外部操作)提供了一種方便的方法.以下示例顯示了兩個(gè)一維數(shù)組的外部附加操作:

>>> 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.]])

這里的 newaxis 索引操作符將一個(gè)新的軸插入到 a 中,使其成為一個(gè)二維 4x1 數(shù)組.將 4x1 數(shù)組與 b 組合在一起,它有形狀(3,),生成一個(gè)4x3數(shù)組.

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)