人工智能之數據分析 numpy
第八章 數組廣播
(文章目錄)
前言
NumPy 的 廣播(Broadcasting) 是其最強大、也最容易被誤解的特性之一。它允許不同形狀的數組之間進行逐元素運算,而無需顯式複製數據,既節省內存又提升性能。
一、什麼是廣播?
廣播:NumPy 在執行算術運算時,自動將形狀不同的數組“擴展”為兼容形狀的機制。
✅ 核心優勢:
- 避免創建不必要的副本(內存高效)
- 代碼簡潔(無需手動
reshape或tile) - 運算速度接近 C 語言
二、廣播規則(必須全部滿足)
當兩個數組 A 和 B 進行運算時,從最後一個維度開始向前對齊,每個維度需滿足以下之一:
- 維度相等,或
- 其中一個維度為 1,或
- 其中一個數組缺少該維度(即維度數更少)
如果所有維度都滿足,則廣播成功;否則報錯:ValueError: operands could not be broadcast together...
三、廣播示例詳解
示例 1:標量與數組(最簡單)
import numpy as np
a = np.array([1, 2, 3])
b = 10 # 標量 → 視為 shape ()
result = a + b # [11 12 13]
a.shape = (3,)b.shape = ()→ 自動擴展為(1,)→ 再廣播為(3,)
示例 2:一維與二維(經典場景)
A = np.array([[1, 2, 3],
[4, 5, 6]]) # shape (2, 3)
v = np.array([10, 20, 30]) # shape (3,)
C = A + v
print(C)
# [[11 22 33]
# [14 25 36]]
廣播過程:
- 對齊維度:
A: (2, 3)vsv: (3,)→ 補全為(1, 3) - 比較各維度:
- 第 1 維:
2vs1→ 允許(1 可擴展為 2) - 第 2 維:
3vs3→ 相等
- 第 1 維:
- 結果形狀:
(2, 3)
💡
v被“複製”到每一行,但沒有實際複製內存!
示例 3:列向量與行向量
row = np.array([1, 2, 3]) # shape (3,)
col = np.array([[10], [20]]) # shape (2, 1)
result = row + col
print(result)
# [[11 12 13]
# [21 22 23]]
廣播過程:
row: (3,) → (1, 3)col: (2, 1)- 對齊後:
- 第 1 維:
1vs2→ 擴展為 2 - 第 2 維:
3vs1→ 擴展為 3
- 第 1 維:
- 結果:
(2, 3)
🔥 這是生成網格座標的基礎!
示例 4:三維廣播
A = np.ones((3, 4, 5))
B = np.ones((4, 5))
C = A + B # 成功!B 被廣播到 (1,4,5) → (3,4,5)
四、廣播失敗的案例
❌ 維度不兼容
a = np.array([1, 2]) # (2,)
b = np.array([[1, 2, 3]]) # (1, 3)
# a + b → 報錯!
# 維度對齊:(1,2) vs (1,3)
# 最後一維:2 ≠ 3,且都不為1 → 無法廣播
❌ 中間維度衝突
A = np.random.rand(2, 3, 4)
B = np.random.rand(2, 5, 4)
# A + B → 報錯!
# 第2維:3 vs 5 → 無法廣播
五、廣播的實際應用
📌 應用 1:標準化數據(Z-score)
data = np.random.rand(100, 5) # 100個樣本,5個特徵
# 計算每列均值和標準差
mean = data.mean(axis=0) # shape (5,)
std = data.std(axis=0) # shape (5,)
# 標準化:(data - mean) / std
normalized = (data - mean) / std # 廣播自動對每行操作
📌 應用 2:生成二維網格(用於繪圖)
x = np.linspace(-2, 2, 5) # [-2 -1 0 1 2] → (5,)
y = np.linspace(-1, 1, 3) # [-1 0 1] → (3,)
# 轉為列向量和行向量
X = x[np.newaxis, :] # shape (1, 5)
Y = y[:, np.newaxis] # shape (3, 1)
# 廣播生成網格
grid_sum = X + Y
print(grid_sum)
# [[-3. -2. -1. 0. 1.]
# [-2. -1. 0. 1. 2.]
# [-1. 0. 1. 2. 3.]]
✅ 這正是
np.meshgrid()的底層原理!
📌 應用 3:批量矩陣偏移
# 10 個 3x3 矩陣
matrices = np.random.rand(10, 3, 3)
# 一個公共偏移向量(加到每行)
offset = np.array([10, 20, 30]) # (3,)
# 廣播:offset 自動應用到每個矩陣的每一行
result = matrices + offset # shape (10, 3, 3)
六、如何避免意外廣播?
有時廣播會導致邏輯錯誤(如本想矩陣乘法卻做了逐元素乘)。
防禦性編程建議:
- 顯式檢查形狀
assert a.shape == b.shape or ... # 根據業務邏輯 - 使用
np.newaxis明確維度# 確保 v 是列向量 v = v[:, np.newaxis] - 慎用高維自動廣播
# 如果不確定,先 reshape 到預期形狀 b = b.reshape(1, -1)
七、廣播 vs np.tile / np.repeat
| 方法 | 內存 | 速度 | 推薦 |
|---|---|---|---|
| 廣播 | 不復制數據 | 極快 | ✅ 首選 |
np.tile |
創建完整副本 | 慢 | ❌ 僅調試用 |
np.repeat |
創建副本 | 慢 | ❌ |
# 不推薦(浪費內存)
A = np.array([[1, 2], [3, 4]])
B = np.tile([10, 20], (2, 1)) # 顯式複製
C = A + B
# 推薦(廣播)
C = A + [10, 20] # 自動廣播,無內存開銷
八、總結:廣播速查表
| 操作 | 是否廣播 | 結果形狀 |
|---|---|---|
(3,) + () |
✅ | (3,) |
(2,3) + (3,) |
✅ | (2,3) |
(2,1) + (3,) |
✅ | (2,3) |
(2,3) + (2,1) |
✅ | (2,3) |
(2,3) + (3,2) |
❌ | 報錯 |
(4,1,3) + (2,3) |
✅ | (4,2,3) |
🧠 記憶口訣:從右往左對齊,1 可擴,等則留,否則錯。
後續
本文主要講述了numpy數組廣播。python過渡項目部分代碼已經上傳至gitee,後續會逐步更新,主要受時間原因限制,當然自己也可以克隆到本地學習拓展。
資料關注
公眾號:咚咚王 gitee:https://gitee.com/wy18585051844/ai_learning
《Python編程:從入門到實踐》 《利用Python進行數據分析》 《算法導論中文第三版》 《概率論與數理統計(第四版) (盛驟) 》 《程序員的數學》 《線性代數應該這樣學第3版》 《微積分和數學分析引論》 《(西瓜書)周志華-機器學習》 《TensorFlow機器學習實戰指南》 《Sklearn與TensorFlow機器學習實用指南》 《模式識別(第四版)》 《深度學習 deep learning》伊恩·古德費洛著 花書 《Python深度學習第二版(中文版)【純文本】 (登封大數據 (Francois Choliet)) (Z-Library)》 《深入淺出神經網絡與深度學習+(邁克爾·尼爾森(Michael+Nielsen)》 《自然語言處理綜論 第2版》 《Natural-Language-Processing-with-PyTorch》 《計算機視覺-算法與應用(中文版)》 《Learning OpenCV 4》 《AIGC:智能創作時代》杜雨+&+張孜銘 《AIGC原理與實踐:零基礎學大語言模型、擴散模型和多模態模型》 《從零構建大語言模型(中文版)》 《實戰AI大模型》 《AI 3.0》