術(shù)語(yǔ)廣播描述了 numpy 在算術(shù)運(yùn)算期間如何處理具有不同形狀的數(shù)組。受限于某些限制,較小的陣列在較大的陣列上“廣播”,以便它們具有兼容的形狀。廣播提供了一種向量化數(shù)組操作的方法,以便循環(huán)發(fā)生在 C 而不是 Python 中。它不會(huì)制作不必要的數(shù)據(jù)副本,并且通常會(huì)導(dǎo)致高效的算法實(shí)現(xiàn)。然而,在某些情況下,廣播是一個(gè)壞主意,因?yàn)樗鼤?huì)導(dǎo)致內(nèi)存使用效率低下,從而減慢計(jì)算速度。
NumPy 操作通常在逐個(gè)元素的基礎(chǔ)上對(duì)成對(duì)的數(shù)組進(jìn)行。在最簡(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 的廣播規(guī)則會(huì)放寬此約束。最簡(jiǎn)單的廣播示例發(fā)生在將數(shù)組和標(biāo)量值組合在一個(gè)操作中時(shí):
>>> a = np.array([1.0, 2.0, 3.0])
>>> b = 2.0
>>> a * b
array([ 2., 4., 6.])
結(jié)果等同于前面的例子,其中b
是一個(gè)數(shù)組。我們可以想象在算術(shù)運(yùn)算期間標(biāo)量b
被拉伸成一個(gè)與 形狀相同的數(shù)組a
。中的新元素?b
只是原始標(biāo)量的副本。拉伸類比只是概念上的。NumPy 足夠聰明,可以使用原始標(biāo)量值而無(wú)需實(shí)際制作副本,以便廣播操作盡可能具有內(nèi)存和計(jì)算效率。
第二個(gè)示例中的代碼比第一個(gè)示例中的代碼更高效,因?yàn)閺V播在乘法期間移動(dòng)的內(nèi)存更少(b
是標(biāo)量而不是數(shù)組)。
在對(duì)兩個(gè)數(shù)組進(jìn)行操作時(shí),NumPy 按元素比較它們的形狀。它從尾隨(即最右邊)尺寸開(kāi)始并向左工作。當(dāng)兩個(gè)維度兼容時(shí)
如果不滿足這些條件,?則會(huì)拋出異常,表明數(shù)組具有不兼容的形狀。結(jié)果數(shù)組的大小是沿著輸入的每個(gè)軸不為 1 的大小。ValueError:?operands?could?not?be?broadcast?together
陣列不需要有相同數(shù)量的尺寸。例如,如果您有一個(gè)256x256x3
RGB 值數(shù)組,并且您想用不同的值縮放圖像中的每種顏色,您可以將圖像乘以具有 3 個(gè)值的一維數(shù)組。根據(jù)廣播規(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è)。換句話說(shuō),尺寸為 1 的維度被拉伸或“復(fù)制”以匹配另一個(gè)。
在以下示例中,A
和B
數(shù)組都具有長(zhǎng)度為 1 的軸,這些軸在廣播操作期間擴(kuò)展為更大的尺寸:
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
以下是不廣播的形狀示例:
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
實(shí)踐中的廣播示例:
>>> 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.]])
廣播提供了一種獲取兩個(gè)數(shù)組的外積(或任何其他外操作)的便捷方法。以下示例顯示了兩個(gè)一維數(shù)組的外加運(yùn)算:
>>> 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
索引運(yùn)算符將一個(gè)新軸插入到 中a
,使其成為二維4x1
數(shù)組。將4x1
數(shù)組與b
具有 shape 的 組合(3,)
產(chǎn)生一個(gè)4x3
數(shù)組。
更多建議: