NumPy實(shí)現(xiàn)廣播機(jī)制與廣播規(guī)則的示例
在 NumPy 中,廣播(Broadcasting)是一組形狀匹配規(guī)則,用于支持逐元素運(yùn)算在不同形狀數(shù)組之間自動(dòng)對齊,從而在不編寫 Python 循環(huán)、不顯式復(fù)制數(shù)據(jù)的前提下,實(shí)現(xiàn)高效的向量化計(jì)算。
一、什么是廣播?
我們知道,當(dāng)兩個(gè)數(shù)組形狀相同,二元運(yùn)算會(huì)逐元素執(zhí)行:
import numpy as np a = np.array([0, 1, 2])b = np.array([5, 5, 5]) a + b
輸出:array([5, 6, 7])
廣播允許對不同形狀的數(shù)組執(zhí)行類似的逐元素運(yùn)算。
例如,可以將一個(gè)標(biāo)量(可以將其視為一個(gè) 0 維數(shù)組)加到數(shù)組上:
a + 5
輸出:array([5, 6, 7])
可以將其理解為將數(shù)值 5 “拉伸”或“復(fù)制”為 [5, 5, 5] 后再進(jìn)行相加。
但需要強(qiáng)調(diào)的是,NumPy 并不會(huì)創(chuàng)建 [5, 5, 5] 再相加,而是在計(jì)算過程中將標(biāo)量“廣播”到數(shù)組的每個(gè)元素。
這種機(jī)制不僅適用于標(biāo)量,也適用于更高維的數(shù)組,只要滿足一定規(guī)則。
觀察一維數(shù)組與二維數(shù)組相加的結(jié)果:
M = np.ones((3, 3))M
輸出:array([[1., 1., 1.], [1., 1., 1.], [1., 1., 1.]])
再執(zhí)行:
M + a
輸出:array([[1., 2., 3.], [1., 2., 3.], [1., 2., 3.]])
此處,一維數(shù)組 a 被“拉伸”或廣播到第二個(gè)維度,以匹配 M 的形狀。
這些示例較為直觀。但在更復(fù)雜的情況下,兩個(gè)數(shù)組都可能發(fā)生廣播。請看下例:
a = np.arange(3)b = np.arange(3)[:, np.newaxis] print(a)print(b)
輸出:[0 1 2][[0] [1] [2]]
當(dāng)執(zhí)行:a + b
輸出:array([[0, 1, 2], [1, 2, 3], [2, 3, 4]])
正如前述例子中將一個(gè)值“拉伸”以匹配另一個(gè)數(shù)組的形狀一樣,在這里,a 和 b 都被“拉伸”到一個(gè)共同形狀,結(jié)果是一個(gè)二維數(shù)組。
下圖展示了這些示例的幾何結(jié)構(gòu)。

淺色區(qū)域表示被廣播的值。再次強(qiáng)調(diào),這些額外內(nèi)存在實(shí)際計(jì)算中并未真正分配,但在概念上進(jìn)行這樣的想象有助于理解什么是“廣播”。
要注意的是,廣播只發(fā)生在:
- 逐元素 ufunc
- 運(yùn)算符重載運(yùn)算
不會(huì)發(fā)生在:
- 矩陣乘法 @ 和 matmul
- 點(diǎn)積 dot
二、廣播規(guī)則
NumPy 中的廣播遵循一套嚴(yán)格規(guī)則和步驟來確定兩個(gè)數(shù)組之間如何交互。
廣播比較是從最后一維(尾維)開始對齊,正確廣播后的結(jié)果形狀等于“各維度取最大值”。
- 規(guī)則 1:如果兩個(gè)數(shù)組的維度數(shù)不同,則在維度較少的數(shù)組形狀左側(cè)補(bǔ) 1。
- 規(guī)則 2: 若在某一維上(從最后一維開始)兩個(gè)數(shù)組的形狀不相同,則該維度中長度等于 1 的數(shù)組會(huì)被擴(kuò)展至與另一數(shù)組匹配。
- 規(guī)則 3: 如果在任意維度上兩個(gè)數(shù)組的大小不同,且長度都不等于 1,則拋出錯(cuò)誤。
下面通過具體示例說明。
廣播示例 1:將二維數(shù)組與一維數(shù)組相加
M = np.ones((2, 3))a = np.arange(3)
數(shù)組形狀為:
M.shape = (2, 3)a.shape = (3,)
根據(jù)規(guī)則 1,對 a 的形狀左側(cè)補(bǔ) 1:
M.shape -> (2, 3)a.shape -> (1, 3)
根據(jù)規(guī)則 2,第一維不一致,因此將其擴(kuò)展:
M.shape -> (2, 3)a.shape -> (2, 3)
形狀匹配,結(jié)果形狀為 (2, 3):
M + a
輸出:array([[1., 2., 3.], [1., 2., 3.]])
廣播示例 2:兩個(gè)數(shù)組都需要廣播
a = np.arange(3).reshape((3, 1))b = np.arange(3)
形狀:
a.shape = (3, 1)b.shape = (3,)
首先按照規(guī)則 1,數(shù)組 b 的形狀左側(cè)補(bǔ) 1:
a.shape -> (3, 1)b.shape -> (1, 3)
然后按照規(guī)則 2,先后擴(kuò)展數(shù)組 a 的形狀和數(shù)組 b 的形狀:
a.shape -> (3, 3)b.shape -> (3, 3)
由于最終形狀一致,因此這兩個(gè)數(shù)組的形狀是兼容的。下面可以看到這一點(diǎn):
a + b
輸出:array([[0, 1, 2], [1, 2, 3], [2, 3, 4]])
廣播示例 3:不兼容的情形
M = np.ones((3, 2))a = np.arange(3)
形狀:
M.shape = (3, 2)a.shape = (3,)
首先按照規(guī)則 1,數(shù)組 a 的形狀左側(cè)補(bǔ) 1:
M.shape -> (3, 2)a.shape -> (1, 3)
然后按照規(guī)則 2,第二維比較時(shí)發(fā)現(xiàn) 2 ≠ 3 且均不為 1,此時(shí)觸發(fā)規(guī)則 3,最終形狀不一致,因此不兼容。
當(dāng)執(zhí)行:
M + a
會(huì)產(chǎn)生:ValueError: operands could not be broadcast together with shapes (3,2) (3,)
需要注意的是,不能假設(shè)右側(cè)補(bǔ) 1。廣播規(guī)則只允許在左側(cè)補(bǔ) 1。若需要右側(cè)補(bǔ) 1,必須顯式 reshape:
a.reshape(3, 1)# (3, 1)
或者:
a[:, np.newaxis]# 等價(jià)于a[:, None]
當(dāng)執(zhí)行:
M + a[:, np.newaxis]
輸出:array([[1., 1.], [2., 2.], [3., 3.]])
廣播規(guī)則適用于所有二元通用函數(shù)(ufunc)。例如:
np.logaddexp(M, a[:, np.newaxis])
array([[1.31326169, 1.31326169], [1.69314718, 1.69314718], [2.31326169, 2.31326169]])
logaddexp(x, y) 計(jì)算 log(exp(x) + exp(y)),并以更高數(shù)值精度實(shí)現(xiàn)。
三、NumPy 廣播的實(shí)際應(yīng)用
1、數(shù)據(jù)中心化
假設(shè)有 10 條觀測數(shù)據(jù),每條包含 3 個(gè)特征,存儲(chǔ)為 10×3 數(shù)組:
X = np.random.random((10, 3))
計(jì)算每個(gè)特征的均值:
Xmean = X.mean(0)# array([0.56171119, 0.37035172, 0.56328698])
中心化數(shù)據(jù):
X_centered = X - Xmean
驗(yàn)證均值是否接近 0:
X_centered.mean(0)# array([ 5.55111512e-17, -4.44089210e-17, -7.77156117e-17])
結(jié)果在機(jī)器精度范圍內(nèi)接近 0。
2、繪制二維函數(shù)
廣播在生成二維函數(shù)圖像時(shí)非常有用。
x = np.linspace(0, 5, 50)y = np.linspace(0, 5, 50)[:, np.newaxis] z = np.sin(x) ** 10 + np.cos(10 + y * x) * np.cos(x)
x 與 y 自動(dòng)廣播生成 50×50 網(wǎng)格。
使用 Matplotlib 可視化:
import matplotlib.pyplot as plt plt.imshow(z, origin='lower', extent=[0, 5, 0, 5], cmap='viridis')plt.colorbar()

廣播使二維函數(shù)的計(jì)算無需顯式雙重循環(huán)。
小結(jié)
廣播是一組嚴(yán)格規(guī)則,用于支持不同形狀數(shù)組之間的逐元素運(yùn)算:
- 維度不足時(shí)在左側(cè)補(bǔ) 1
- 從右向左逐維比較,每一維必須“相等或存在 1”
- 不滿足條件則報(bào)錯(cuò)
廣播機(jī)制是 NumPy 向量化計(jì)算的重要基礎(chǔ),廣泛應(yīng)用于科學(xué)計(jì)算、機(jī)器學(xué)習(xí)與數(shù)據(jù)分析中。
到此這篇關(guān)于NumPy實(shí)現(xiàn)廣播機(jī)制與廣播規(guī)則的示例的文章就介紹到這了,更多相關(guān)NumPy 廣播機(jī)制與廣播規(guī)則內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
關(guān)于keras.layers.Conv1D的kernel_size參數(shù)使用介紹
這篇文章主要介紹了關(guān)于keras.layers.Conv1D的kernel_size參數(shù)使用介紹,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-05-05
python?pandas處理excel表格數(shù)據(jù)的常用方法總結(jié)
在計(jì)算機(jī)編程中,pandas是Python編程語言的用于數(shù)據(jù)操縱和分析的軟件庫,下面這篇文章主要給大家介紹了關(guān)于python?pandas處理excel表格數(shù)據(jù)的常用方法,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-07-07

