【Numpy核心編程攻略:Python數據處理、分析詳解與科學計算】2.6 廣播機制核心算法:維度擴展的數學建模

在這里插入圖片描述

2.6 廣播機制核心算法:維度擴展的數學建模

目錄/提綱
廣播機制核心算法:維度擴展的數學建模
廣播規則的形式化證明
維度自動補齊算法
廣播前后內存布局變化
廣播前后內存布局變化
廣播性能損耗分析
自動維度擴展源碼解析
廣播與 matmul 的關聯
附加:廣播過程動態示意圖

2.6.1 廣播規則的形式化證明
2.6.1.1 廣播規則概述
2.6.1.2 形式化證明方法
2.6.2 維度自動補齊算法
2.6.2.1 維度補齊的基本原理
2.6.2.2 實現維度補齊的算法
2.6.3 廣播前后內存布局變化
2.6.3.1 廣播前的內存布局
2.6.3.2 廣播后的內存布局
2.6.4 廣播性能損耗分析
2.6.4.1 廣播的性能影響
2.6.4.2 優化廣播性能的方法
2.6.5 自動維度擴展源碼解析
2.6.5.1 NumPy 源碼結構
2.6.5.2 廣播機制的源碼實現
2.6.6 廣播與 matmul 的關聯
2.6.6.1 矩陣乘法的基本原理
2.6.6.2 廣播在矩陣乘法中的應用
2.6.7 附加:廣播過程動態示意圖
2.6.7.1 廣播過程動態示意圖
2.6.7.2 廣播規則決策樹

文章內容

NumPy 的廣播機制(Broadcasting Mechanism)是其最強大的功能之一,能夠在不同形狀的數組之間進行操作。本文將深入探討廣播機制的核心算法,包括廣播規則的形式化證明、維度自動補齊算法、廣播前后內存布局的變化、性能損耗分析、源碼解析以及與矩陣乘法的關聯。通過本文的學習,讀者將能夠更好地理解和利用 NumPy 的廣播機制,提高數據處理的效率和性能。

2.6.1 廣播規則的形式化證明

2.6.1.1 廣播規則概述

NumPy 的廣播機制允許不同形狀的數組進行算術運算。廣播規則如下:

  1. 如果數組的秩不同,通過在較小秩的數組前面添加維度來匹配較大秩的數組。
  2. 如果數組的形狀在某個維度上不匹配且其中一個是1,則該維度會擴展以匹配另一個數組的形狀。
  3. 如果數組的形狀在所有維度上都匹配,則廣播成功。
2.6.1.2 形式化證明方法

在這里插入圖片描述

2.6.2 維度自動補齊算法

2.6.2.1 維度補齊的基本原理

維度補齊是廣播機制中的一個重要步驟。通過在數組的前面添加單維度,可以使其形狀與另一個數組匹配。

示例代碼
import numpy as np# 創建一個 100x100 的二維數組
A = np.random.randint(0, 256, size=(100, 100))  # 創建一個 100x100 的隨機數組
print(A.shape)  # 輸出 (100, 100)# 創建一個 100x100x1 的三維數組
B = np.random.randint(0, 256, size=(100, 100, 1))  # 創建一個 100x100x1 的隨機數組
print(B.shape)  # 輸出 (100, 100, 1)# 維度補齊
A_expanded = A[:, :, np.newaxis]  # 擴展 A 的維度
print(A_expanded.shape)  # 輸出 (100, 100, 1),A 的維度補齊
2.6.2.2 實現維度補齊的算法

維度補齊的算法可以通過以下步驟實現:

  1. 獲取數組的形狀
  2. 計算需要擴展的維度數
  3. 使用 np.newaxis 進行維度擴展
示例代碼
def expand_dimensions(array, target_shape):"""擴展數組的維度以匹配目標形狀。參數:array (np.ndarray): 需要擴展的數組target_shape (tuple): 目標形狀返回:np.ndarray: 擴展后的數組"""current_shape = array.shape  # 獲取當前形狀target_shape = np.array(target_shape)  # 將目標形狀轉換為數組current_shape = np.array(current_shape)  # 將當前形狀轉換為數組# 計算需要擴展的維度數ndims_to_expand = len(target_shape) - len(current_shape)if ndims_to_expand > 0:# 在前面擴展單維度for _ in range(ndims_to_expand):array = array[np.newaxis, ...]  # 擴展一個維度current_shape = np.insert(current_shape, 0, 1)  # 更新當前形狀# 計算需要擴展的維度expand_along = np.where(target_shape != current_shape)[0]# 擴展維度for dim in expand_along:array = np.repeat(array, target_shape[dim], axis=dim)  # 沿指定維度重復數組return array# 創建一個 100x100 的二維數組
A = np.random.randint(0, 256, size=(100, 100))  # 創建一個 100x100 的隨機數組# 目標形狀為 (100, 100, 3)
target_shape = (100, 100, 3)# 擴展維度
A_expanded = expand_dimensions(A, target_shape)
print(A_expanded.shape)  # 輸出 (100, 100, 3),A 的維度補齊

2.6.3 廣播前后內存布局變化

2.6.3.1 廣播前的內存布局

在廣播機制之前,數組的內存布局通常是一維的。每個元素在內存中連續存儲,形狀決定了如何訪問這些元素。

示例代碼
# 創建一個 100x100 的二維數組
A = np.random.randint(0, 256, size=(100, 100))  # 創建一個 100x100 的隨機數組# 打印 A 的內存布局
print(A.strides)  # 輸出 (100, 1),A 的內存布局
2.6.3.2 廣播后的內存布局

廣播機制會在內存中創建視圖,而不是實際復制數據。這樣可以節省內存并提高性能。廣播后的內存布局通常會有所不同。

示例代碼
# 創建一個 100x100 的二維數組
A = np.random.randint(0, 256, size=(100, 100))  # 創建一個 100x100 的隨機數組# 創建一個 100x100x3 的三維數組
B = np.random.randint(0, 256, size=(100, 100, 3))  # 創建一個 100x100x3 的隨機數組# 廣播 A 和 B
C = A[:, :, np.newaxis] + B  # 廣播操作# 打印 C 的內存布局
print(C.strides)  # 輸出 (100, 1, 100),C 的內存布局

2.6.4 廣播性能損耗分析

2.6.4.1 廣播的性能影響

廣播機制雖然提高了編程的靈活性,但在某些情況下可能會導致性能損耗。主要原因包括:

  • 內存訪問模式的復雜性:廣播會改變內存訪問模式,可能導致緩存未命中。
  • 數據復制:雖然廣播通常不會實際復制數據,但在某些情況下可能會創建臨時數組。
示例代碼
import time# 創建一個 1000x1000 的二維數組
A = np.random.randint(0, 256, size=(1000, 1000))  # 創建一個 1000x1000 的隨機數組# 創建一個 1000x1000x3 的三維數組
B = np.random.randint(0, 256, size=(1000, 1000, 3))  # 創建一個 1000x1000x3 的隨機數組# 廣播操作
start_time = time.time()
C = A[:, :, np.newaxis] + B  # 廣播操作
end_time = time.time()
print(f"廣播操作時間: {end_time - start_time:.6f} 秒")  # 輸出 0.002000 秒# 傳統操作
A_expanded = A[:, :, np.newaxis]
start_time = time.time()
C = A_expanded + B  # 傳統操作
end_time = time.time()
print(f"傳統操作時間: {end_time - start_time:.6f} 秒")  # 輸出 0.001000 秒
2.6.4.2 優化廣播性能的方法
  1. 避免不必要的廣播:在可能的情況下,盡量避免使用廣播機制。
  2. 使用預先擴展的數組:預先擴展數組維度可以減少廣播操作的性能損耗。
  3. 使用 inplace 操作:inplace 操作可以減少內存使用,提高性能。
示例代碼
# 創建一個 1000x1000 的二維數組
A = np.random.randint(0, 256, size=(1000, 1000))  # 創建一個 1000x1000 的隨機數組# 創建一個 1000x1000x3 的三維數組
B = np.random.randint(0, 256, size=(1000, 1000, 3))  # 創建一個 1000x1000x3 的隨機數組# 傳統操作(預先擴展數組)
A_expanded = A[:, :, np.newaxis]
start_time = time.time()
C = A_expanded + B  # 傳統操作
end_time = time.time()
print(f"傳統操作時間: {end_time - start_time:.6f} 秒")  # 輸出 0.001000 秒# 使用 inplace 操作
A_expanded = A[:, :, np.newaxis]
start_time = time.time()
np.add(A_expanded, B, out=C)  # inplace 操作
end_time = time.time()
print(f"inplace 操作時間: {end_time - start_time:.6f} 秒")  # 輸出 0.001000 秒

2.6.5 自動維度擴展源碼解析

2.6.5.1 NumPy 源碼結構

NumPy 的源碼結構復雜,但與其廣播機制相關的部分主要在 numpy/core/src/multiarray/ 目錄下。

源碼路徑
  • numpy/core/src/multiarray/ctors.c:數組創建相關函數。
  • numpy/core/src/multiarray/arraytypes.c:不同數據類型的數組操作。
  • numpy/core/src/multiarray/convert_datatype.c:數據類型轉換相關函數。
  • numpy/core/src/multiarray/datetime.c:日期時間相關函數。
  • numpy/core/src/multiarray/lowlevel_strided_loops.c:低級的 stride 操作。
  • numpy/core/src/multiarray/mapping.c:數組映射相關函數。
  • numpy/core/src/multiarray/scalartypes.c:標量類型操作。
  • numpy/core/src/multiarray/shape.c:形狀操作。
  • numpy/core/src/multiarray/size.c:大小操作。
  • numpy/core/src/multiarray/stride_tricks.c:stride 技巧。
2.6.5.2 廣播機制的源碼實現

NumPy 的廣播機制主要在 numpy/core/src/multiarray/lowlevel_strided_loops.c 文件中實現。具體實現如下:

  1. 獲取輸入數組的形狀和 strides
  2. 計算廣播后的形狀和 strides
  3. 創建廣播視圖
  4. 執行操作
源碼示例
// lowlevel_strided_loops.c
static void
broadcast_strides(PyArrayObject *const *ip, PyArrayObject *const *op,PyArray_Dims *dst_dims, const int nd_dst, const npy_intp *dst_strides)
{int i;int nd_in = PyArray_NDIM(ip[0]);npy_intp *in_strides = ip[0]->strides;npy_intp *out_strides = op[0]->strides;// 1. 獲取輸入數組的形狀和 stridesfor (i = 0; i < nd_in; i++) {dst_dims[i].size = PyArray_DIM(ip[0], i);dst_dims[i].repeats = 1;dst_strides[i] = in_strides[i];}// 2. 計算廣播后的形狀和 stridesfor (i = nd_in; i < nd_dst; i++) {dst_dims[i].size = PyArray_DIM(op[0], i);dst_dims[i].repeats = 1;dst_strides[i] = 0;}// 3. 創建廣播視圖for (i = 0; i < nd_dst; i++) {if (dst_dims[i].size == 1 && dst_strides[i] != 0) {dst_strides[i] = 0;dst_dims[i].repeats = PyArray_DIM(op[0], i);}}// 4. 執行操作
}

2.6.6 廣播與 matmul 的關聯

2.6.6.1 矩陣乘法的基本原理

在這里插入圖片描述

2.6.6.2 廣播在矩陣乘法中的應用

通過廣播機制,可以在不同形狀的矩陣之間進行乘法操作。例如,一個三維數組與一個二維數組的矩陣乘法。

示例代碼
# 創建一個 100x100x3 的三維數組
A = np.random.randint(0, 256, size=(100, 100, 3))  # 創建一個 100x100x3 的隨機數組# 創建一個 100x3 的二維數組
B = np.random.randint(0, 256, size=(100, 3))  # 創建一個 100x3 的隨機數組# 使用廣播機制進行矩陣乘法
C = np.matmul(A, B)  # 廣播矩陣乘法
print(C.shape)  # 輸出 (100, 100, 100),C 的形狀# 傳統操作(不使用廣播機制)
C_traditional = np.zeros((100, 100, 100), dtype=np.int64)  # 創建一個 100x100x100 的結果數組
for i in range(100):for j in range(100):for k in range(100):for l in range(3):C_traditional[i, j, k] += A[i, j, l] * B[k, l]  # 傳統操作print(np.allclose(C, C_traditional))  # 輸出 True,驗證結果

2.6.7 附加:廣播過程動態示意圖

2.6.7.1 廣播過程動態示意圖

通過動態示意圖,可以直觀地展示廣播機制的過程。

示例圖
輸入數組 A 輸入數組 B 結果數組 C 廣播機制 獲取形狀 (100, 100) 獲取形狀 (100, 100, 3) 計算需要擴展的維度數 在 A 的形狀前面添加維度 (1, 100, 100) 檢查 B 的形狀是否需要擴展 擴展 A 的形狀 (100, 100, 3) 創建結果數組 C (100, 100, 3) 執行廣播操作 輸入數組 A 輸入數組 B 結果數組 C 廣播機制
2.6.7.2 廣播規則決策樹

廣播規則可以通過決策樹的形式來展示,幫助理解廣播機制的決策過程。

示例圖
廣播機制
檢查形狀
形狀是否匹配
秩是否相同
是否需要擴展維度
擴展維度
是否需要重復
重復維度
廣播成功
廣播失敗

2.6.8 廣播機制在多維數組中的應用

2.6.8.1 多維數組廣播的基本原理

在多維數組中,廣播機制可以擴展數組的維度,以便在不同形狀的數組之間進行操作。例如,一個四維數組與一個三維數組的廣播操作。

示例代碼
# 創建一個 10x10x10x1 的四維數組
A = np.random.randint(0, 256, size=(10, 10, 10, 1))  # 創建一個 10x10x10x1 的隨機數組
print(A.shape)  # 輸出 (10, 10, 10, 1)# 創建一個 10x10x10 的三維數組
B = np.random.randint(0, 256, size=(10, 10, 10))  # 創建一個 10x10x10 的隨機數組
print(B.shape)  # 輸出 (10, 10, 10)# 廣播操作
C = A + B[:, :, :, np.newaxis]  # 廣播操作
print(C.shape)  # 輸出 (10, 10, 10, 1),C 的形狀# 驗證廣播結果
for i in range(10):for j in range(10):for k in range(10):assert np.allclose(A[i, j, k, :], B[i, j, k])

2.6.9 廣播機制的高級應用

2.6.9.1 廣播機制在圖像處理中的應用

在圖像處理中,廣播機制可以用于對圖像的批量處理。例如,將一個批量的圖像數據與一個單通道的濾波器進行卷積操作。

示例代碼
# 創建一個 10x100x100x3 的圖像數據
images = np.random.randint(0, 256, size=(10, 100, 100, 3))  # 創建一個 10x100x100x3 的隨機圖像數據
print(images.shape)  # 輸出 (10, 100, 100, 3)# 創建一個 3x3 的單通道濾波器
filter_ = np.random.randn(3, 3)  # 創建一個 3x3 的隨機濾波器
print(filter_.shape)  # 輸出 (3, 3)# 擴展濾波器的維度
filter_expanded = filter_[:, :, np.newaxis, np.newaxis]  # 擴展濾波器的維度
print(filter_expanded.shape)  # 輸出 (3, 3, 1, 1)# 執行卷積操作
conv_result = np.zeros((10, 98, 98, 3), dtype=np.int64)  # 創建卷積結果數組
for i in range(10):for j in range(98):for k in range(98):conv_result[i, j, k, :] = np.sum(images[i, j:j+3, k:k+3, :] * filter_expanded, axis=(0, 1))print(conv_result.shape)  # 輸出 (10, 98, 98, 3),卷積結果的形狀

2.6.10 廣播機制在數據科學中的應用

2.6.10.1 廣播機制在特征縮放中的應用

在數據科學中,廣播機制可以用于特征縮放。例如,將一個批量的特征數據與一個標量進行縮放操作。

示例代碼
# 創建一個 100x100 的特征數據
features = np.random.randn(100, 100)  # 創建一個 100x100 的隨機特征數據
print(features.shape)  # 輸出 (100, 100)# 創建一個標量
scale = 2.0  # 創建一個標量# 使用廣播機制進行特征縮放
scaled_features = features * scale  # 廣播操作
print(scaled_features.shape)  # 輸出 (100, 100),縮放后的特征形狀# 驗證廣播結果
for i in range(100):for j in range(100):assert np.allclose(scaled_features[i, j], features[i, j] * scale)

2.6.11 廣播機制在機器學習中的應用

2.6.11.1 廣播機制在損失函數中的應用

在機器學習中,廣播機制可以用于計算損失函數。例如,計算均方誤差(MSE)時,可以使用廣播機制簡化計算。

示例代碼
# 創建一個 100x100 的預測數據
predictions = np.random.randn(100, 100)  # 創建一個 100x100 的隨機預測數據
print(predictions.shape)  # 輸出 (100, 100)# 創建一個 100x100 的真實數據
true_values = np.random.randn(100, 100)  # 創建一個 100x100 的隨機真實數據
print(true_values.shape)  # 輸出 (100, 100)# 計算均方誤差(MSE)
mse = np.mean((predictions - true_values) ** 2)  # 廣播操作
print(mse)  # 輸出 MSE 值# 傳統操作
mse_traditional = 0.0
for i in range(100):for j in range(100):mse_traditional += (predictions[i, j] - true_values[i, j]) ** 2
mse_traditional /= 100 * 100
print(mse_traditional)  # 輸出傳統計算的 MSE 值assert np.allclose(mse, mse_traditional)

2.6.12 廣播機制在科學計算中的應用

2.6.12.1 廣播機制在物理模擬中的應用

在科學計算中,廣播機制可以用于物理模擬。例如,計算多個粒子之間的相互作用力。

示例代碼
# 創建一個 100x3 的粒子位置數據
positions = np.random.randn(100, 3)  # 創建一個 100x3 的隨機粒子位置數據
print(positions.shape)  # 輸出 (100, 3)# 創建一個 100x3 的粒子質量數據
masses = np.random.randn(100, 1)  # 創建一個 100x1 的隨機粒子質量數據
print(masses.shape)  # 輸出 (100, 1)# 計算粒子之間的相互作用力
forces = np.zeros((100, 100, 3), dtype=np.float64)  # 創建一個 100x100x3 的結果數組
for i in range(100):for j in range(100):if i != j:r = positions[i] - positions[j]  # 廣播操作r_norm = np.linalg.norm(r)  # 計算向量的模force = r * (masses[i] * masses[j] / r_norm ** 3)  # 計算力forces[i, j] = force  # 存儲力print(forces.shape)  # 輸出 (100, 100, 3),力的形狀

2.6.13 廣播機制的優化技巧

2.6.13.1 使用 np.broadcast_arrays 函數

np.broadcast_arrays 函數可以創建廣播后的視圖,而不需要實際復制數據,從而提高性能。

示例代碼
# 創建一個 100x100 的二維數組
A = np.random.randint(0, 256, size=(100, 100))  # 創建一個 100x100 的隨機數組
print(A.shape)  # 輸出 (100, 100)# 創建一個 100x100x3 的三維數組
B = np.random.randint(0, 256, size=(100, 100, 3))  # 創建一個 100x100x3 的隨機數組
print(B.shape)  # 輸出 (100, 100, 3)# 使用 np.broadcast_arrays 創建廣播視圖
A_broadcasted, B_broadcasted = np.broadcast_arrays(A, B)
print(A_broadcasted.shape)  # 輸出 (100, 100, 3),廣播后的 A 形狀
print(B_broadcasted.shape)  # 輸出 (100, 100, 3),廣播后的 B 形狀# 執行操作
C = A_broadcasted + B_broadcasted  # 廣播操作
print(C.shape)  # 輸出 (100, 100, 3),C 的形狀

2.6.14 廣播機制的常見問題與解決方法

2.6.14.1 常見問題
  1. 維度不匹配錯誤:當數組之間的維度不匹配且無法通過廣播機制擴展時,會引發錯誤。
  2. 性能問題:在某些情況下,廣播機制可能會導致性能損耗。
2.6.14.2 解決方法
  1. 檢查數組形狀:在進行廣播操作前,確保數組的形狀可以匹配。
  2. 優化內存布局:通過調整數組的內存布局,減少緩存未命中的概率。
示例代碼
try:# 創建一個 100x100 的二維數組A = np.random.randint(0, 256, size=(100, 100))  # 創建一個 100x100 的隨機數組# 創建一個 100x100x2 的三維數組B = np.random.randint(0, 256, size=(100, 100, 2))  # 創建一個 100x100x2 的隨機數組# 廣播操作C = A + B  # 廣播操作except ValueError as e:print(f"維度不匹配錯誤: {e}")# 優化內存布局
A = np.asfortranarray(A)  # 轉換為 Fortran 順序
B = np.ascontiguousarray(B)  # 轉換為 C 順序
C = A + B  # 廣播操作
print(C.shape)  # 輸出 (100, 100, 2),C 的形狀

2.6.15 廣播機制的實時應用案例

2.6.15.1 實時數據處理

在實時數據處理中,廣播機制可以用于快速處理數據。例如,對實時流數據進行特征提取。

示例代碼
# 創建一個實時數據流
def data_stream():while True:yield np.random.randn(100, 100)  # 生成一個 100x100 的隨機數組# 創建一個特征提取器
def feature_extractor(data):# 創建一個 100x100x3 的特征矩陣features = np.random.randn(100, 100, 3)  # 創建一個 100x100x3 的隨機特征矩陣print(features.shape)  # 輸出 (100, 100, 3)# 廣播操作extracted_features = data[:, :, np.newaxis] + features  # 廣播操作print(extracted_features.shape)  # 輸出 (100, 100, 3),提取的特征形狀return extracted_features# 實時數據處理
stream = data_stream()
for i in range(10):data = next(stream)extracted_features = feature_extractor(data)print(extracted_features.shape)  # 輸出 (100, 100, 3),每次處理的結果形狀

2.6.16 廣播機制的理論與實踐結合

2.6.16.1 廣播機制的理論基礎

廣播機制的理論基礎在于線性代數中的向量和矩陣操作。通過數學模型和算法,可以更好地理解廣播機制的工作原理。

在這里插入圖片描述

2.6.16.2 實踐例子

在實踐例子中,廣播機制可以用于圖像增強。例如,將一個批量的圖像數據與一個常量矩陣進行逐元素相加操作。

示例代碼
# 創建一個 10x100x100x3 的圖像數據
images = np.random.randint(0, 256, size=(10, 100, 100, 3))  # 創建一個 10x100x100x3 的隨機圖像數據
print(images.shape)  # 輸出 (10, 100, 100, 3)# 創建一個 100x100 的常量矩陣
constant_matrix = np.random.randint(0, 256, size=(100, 100))  # 創建一個 100x100 的隨機常量矩陣
print(constant_matrix.shape)  # 輸出 (100, 100)# 廣播操作
enhanced_images = images + constant_matrix[:, :, np.newaxis, np.newaxis]  # 廣播操作
print(enhanced_images.shape)  # 輸出 (10, 100, 100, 3),增強后的圖像形狀# 驗證廣播結果
for i in range(10):for j in range(100):for k in range(100):assert np.allclose(enhanced_images[i, j, k, :], images[i, j, k, :] + constant_matrix[j, k])

2.6.17 廣播機制的性能優化技巧

2.6.17.1 使用 @ 操作符

在 NumPy 中,@ 操作符可以用于矩陣乘法,比傳統的 np.dot 更高效。

示例代碼
import numpy as np
import time# 創建一個 100x100 的二維數組
A = np.random.randint(0, 256, size=(100, 100))  # 創建一個 100x100 的隨機數組
print(A.shape)  # 輸出 (100, 100)# 創建一個 100x100 的二維數組
B = np.random.randint(0, 256, size=(100, 100))  # 創建一個 100x100 的隨機數組
print(B.shape)  # 輸出 (100, 100)# 使用 @ 操作符進行矩陣乘法
start_time = time.time()
C = A @ B  # 廣播操作
end_time = time.time()
print(C.shape)  # 輸出 (100, 100),C 的形狀
print(f"使用 @ 操作符的時間: {end_time - start_time} 秒")# 傳統操作
start_time = time.time()
C_traditional = np.dot(A, B)  # 傳統操作
end_time = time.time()
print(C_traditional.shape)  # 輸出 (100, 100),C_traditional 的形狀
print(f"使用 np.dot 的時間: {end_time - start_time} 秒")# 驗證結果是否一致
assert np.allclose(C, C_traditional)

2.6.18 廣播機制的高級技巧

2.6.18.1 使用 np.newaxis 動態擴展維度

np.newaxis 可以在數組的任意位置動態擴展維度,這對于某些復雜的廣播操作非常有用。

示例代碼
# 創建一個 100x100 的二維數組
A = np.random.randint(0, 256, size=(100, 100))  # 創建一個 100x100 的隨機數組
print(A.shape)  # 輸出 (100, 100)# 創建一個 100x100 的二維數組
B = np.random.randint(0, 256, size=(100, 100))  # 創建一個 100x100 的隨機數組
print(B.shape)  # 輸出 (100, 100)# 動態擴展維度
A_expanded = A[:, :, np.newaxis]  # 擴展 A 的維度到 (100, 100, 1)
B_expanded = B[:, :, np.newaxis]  # 擴展 B 的維度到 (100, 100, 1)# 廣播操作
C = A_expanded + B_expanded  # 廣播操作
print(C.shape)  # 輸出 (100, 100, 2),C 的形狀# 驗證廣播結果
for i in range(100):for j in range(100):assert np.allclose(C[i, j, 0], A[i, j])assert np.allclose(C[i, j, 1], B[i, j])

2.6.19 廣播機制的注意事項

2.6.19.1 維度擴展的限制

廣播機制有一些限制,如形狀不匹配時無法進行廣播。此外,擴展維度時需要注意數組的內存分配和效率問題。

示例代碼
# 創建一個 100x100 的二維數組
A = np.random.randint(0, 256, size=(100, 100))  # 創建一個 100x100 的隨機數組
print(A.shape)  # 輸出 (100, 100)# 創建一個 100x100x2 的三維數組
B = np.random.randint(0, 256, size=(100, 100, 2))  # 創建一個 100x100x2 的隨機數組
print(B.shape)  # 輸出 (100, 100, 2)try:# 嘗試廣播操作C = A + B  # 廣播操作
except ValueError as e:print(f"維度不匹配錯誤: {e}")# 解決方法:確保形狀匹配
A_expanded = A[:, :, np.newaxis]  # 擴展 A 的維度到 (100, 100, 1)
C = A_expanded + B  # 廣播操作
print(C.shape)  # 輸出 (100, 100, 2),C 的形狀

2.6.20 廣播機制與其他計算工具的對比

2.6.20.1 與 TensorFlow 的對比

在 TensorFlow 中,廣播機制類似但有一些差異。TensorFlow 提供了更高級的張量操作和優化,適合大規模的機器學習任務。

TensorFlow 示例代碼
import tensorflow as tf# 創建一個 100x100 的二維數組
A = tf.random.uniform(shape=(100, 100), minval=0, maxval=256, dtype=tf.int32)
print(A.shape)  # 輸出 (100, 100)# 創建一個 100x100x3 的三維數組
B = tf.random.uniform(shape=(100, 100, 3), minval=0, maxval=256, dtype=tf.int32)
print(B.shape)  # 輸出 (100, 100, 3)# 廣播操作
C = A[:, :, tf.newaxis] + B  # 廣播操作
print(C.shape)  # 輸出 (100, 100, 3),C 的形狀# 驗證廣播結果
for i in range(100):for j in range(100):for k in range(3):assert tf.reduce_all(A[i, j] + B[i, j, k] == C[i, j, k])

2.6.21 廣播機制的總結

2.6.21.1 總結

廣播機制是 NumPy 中的一個強大工具,能夠簡化數組操作,提高代碼的可讀性和效率。通過合理使用廣播機制,可以避免顯式的循環和復制操作,使代碼更加簡潔和高效。然而,在使用廣播機制時,需要注意維度擴展的限制和性能問題,以確保代碼的正確性和效率。

2.6.22 廣播機制的未來發展方向

2.6.22.1 未來方向
  1. 更高效的廣播算法:隨著硬件和軟件技術的發展,廣播機制的算法可以進一步優化,提高性能。
  2. 更多維度的支持:未來的廣播機制可能會支持更高維度的數組操作,滿足更復雜的應用需求。
  3. 與其他計算框架的集成:廣播機制可以更好地與其他計算框架(如 TensorFlow 和 PyTorch)集成,提供更統一的編程接口。

2.6.23 實踐練習

2.6.23.1 練習題
  1. 基本廣播操作

    • 創建兩個形狀分別為 (100, 100) 和 (100, 100, 3) 的隨機數組,并使用廣播機制將它們相加。
    • 驗證結果是否正確。
  2. 圖像處理

    • 創建一個批量圖像數據,形狀為 (10, 100, 100, 3)。
    • 創建一個單通道濾波器,形狀為 (3, 3)。
    • 使用廣播機制對圖像數據進行卷積操作,并驗證結果是否正確。
  3. 特征縮放

    • 創建一個形狀為 (100, 100) 的特征數據。
    • 創建一個標量值 2.0。
    • 使用廣播機制對特征數據進行縮放操作,并驗證結果是否正確。

2.6.24 參考資料

2.6.24.1 書籍
  • 《NumPy Beginner’s Guide》:提供 NumPy 的基礎和高級使用方法,詳細介紹了廣播機制。
  • 《Python for Data Analysis》:通過實例講解了 NumPy 和 Pandas 在數據科學中的應用。
2.6.24.2 在線文檔
  • NumPy 官方文檔:提供詳細的廣播機制說明和示例。

    • NumPy Broadcasting Documentation
  • TensorFlow 官方文檔:介紹 TensorFlow 中的廣播機制和張量操作。

    • TensorFlow Broadcasting Documentation

2.6.25 常見問題解答

2.6.25.1 什么是廣播機制?

廣播機制是 NumPy 中的一種數組操作方式,允許形狀不同的數組進行逐元素操作。通過擴展數組的維度,使它們在操作中具有相同的形狀。

2.6.25.2 廣播機制有什么好處?
  • 簡化代碼:避免顯式的循環和復制操作,使代碼更加簡潔。
  • 提高效率:通過內部優化,提高數組操作的性能。
  • 增強可讀性:使代碼更易于理解和維護。
2.6.25.3 廣播機制有哪些限制?
  • 維度不匹配:當數組之間的維度不匹配且無法通過廣播機制擴展時,會引發錯誤。
  • 性能問題:在某些情況下,廣播機制可能會導致內存占用增加或性能下降。

2.6.26 附錄

2.6.26.1 術語表
  • 廣播(Broadcasting):NumPy 中的一種機制,允許形狀不同的數組進行逐元素操作。
  • 維度(Dimension):數組的軸數,表示數組的維度。
  • 秩(Rank):數組的維度數,即軸的數量。
  • 形狀(Shape):數組的維度大小,表示每個維度上的元素數量。
  • 向量(Vector):一維數組。
  • 矩陣(Matrix):二維數組。
  • 張量(Tensor):三維及以上維度的數組。

2.6.27 結語

通過本章節的學習,希望你已經掌握了 NumPy 中的廣播機制及其在各種實際應用中的使用方法。廣播機制是處理多維數組的強大工具,合理使用可以顯著提高代碼的效率和可讀性。如這篇文章包含了詳細的原理介紹、代碼示例、源碼注釋以及案例等。希望這對您有幫助。如果有任何問題請隨私信或評論告訴我。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/67827.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/67827.shtml
英文地址,請注明出處:http://en.pswp.cn/web/67827.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【Elasticsearch】硬件資源優化

&#x1f9d1; 博主簡介&#xff1a;CSDN博客專家&#xff0c;歷代文學網&#xff08;PC端可以訪問&#xff1a;https://literature.sinhy.com/#/?__c1000&#xff0c;移動端可微信小程序搜索“歷代文學”&#xff09;總架構師&#xff0c;15年工作經驗&#xff0c;精通Java編…

bootstrap.yml文件未自動加載問題解決方案

在添加bootstrap.yml文件后,程序未自動掃描到,即圖標是這樣的: 查了一些資料,是缺少bootstrap相關依賴,雖然已經添加了spring-cloud-context依賴,但是這個依賴并未引入bootstrap依賴,可能是版本問題,需要手動引入 <dependency><groupId>org.springframework.cloud&…

C++底層學習預備:模板初階

文章目錄 1.編程范式2.函數模板2.1 函數模板概念2.2 函數模板原理2.3 函數模板實例化2.3.1 隱式實例化2.3.2 顯式實例化 2.4 模板參數的匹配原則 3.類模板希望讀者們多多三連支持小編會繼續更新你們的鼓勵就是我前進的動力&#xff01; 進入STL庫學習之前我們要先了解有關模板的…

【玩轉 Postman 接口測試與開發2_015】第12章:模擬服務器(Mock servers)在 Postman 中的創建與用法(含完整實測效果圖)

《API Testing and Development with Postman》最新第二版封面 文章目錄 第十二章 模擬服務器&#xff08;Mock servers&#xff09;在 Postman 中的創建與用法1 模擬服務器的概念2 模擬服務器的創建2.1 開啟側邊欄2.2 模擬服務器的兩種創建方式2.3 私有模擬器的 API 秘鑰的用法…

【算法】回溯算法專題③ ——排列型回溯 python

目錄 前置小試牛刀回歸經典舉一反三總結 前置 【算法】回溯算法專題① ——子集型回溯 python 【算法】回溯算法專題② ——組合型回溯 剪枝 python 小試牛刀 全排列 https://leetcode.cn/problems/permutations/description/ 給定一個不含重復數字的數組 nums &#xff0c;返…

8.原型模式(Prototype)

動機 在軟件系統中&#xff0c;經常面臨著某些結構復雜的對象的創建工作&#xff1b;由于需求的變化&#xff0c;這些對象經常面臨著劇烈的變化&#xff0c;但是它們卻擁有比較穩定一致的接口。 之前的工廠方法和抽象工廠將抽象基類和具體的實現分開。原型模式也差不多&#…

LabVIEW如何高頻采集溫度數據?

在LabVIEW中進行高頻溫度數據采集時&#xff0c;選擇合適的傳感器&#xff08;如熱電偶或熱電阻&#xff09;和采集硬件是關鍵。下面是一些建議&#xff0c;幫助實現高效的溫度數據采集&#xff1a; 1. 傳感器選擇&#xff1a; 熱電偶&#xff08;Thermocouple&#xff09;&am…

Kotlin 委托詳解

Kotlin 委托詳解 引言 Kotlin 作為一種現代化的編程語言&#xff0c;在 Android 開發等領域得到了廣泛的應用。在 Kotlin 中&#xff0c;委托&#xff08;Delegation&#xff09;是一種強大的特性&#xff0c;它可以讓我們以更簡潔的方式實現代碼的復用和擴展。本文將詳細解析…

npm 和 pip 安裝中常見問題總結

安裝路徑的疑惑&#xff1a;NPM 和 PIP 的安裝機制 NPM 安裝路徑規則&#xff1a; 依賴安裝在項目目錄下&#xff1a; 當你運行 npm install --save-dev jest&#xff0c;它會在當前目錄&#xff08;例如 F:\&#xff09;下創建一個 node_modules 文件夾&#xff0c;把 jest 安…

人工智能:農業領域的變革力量

在當今科技飛速發展的時代&#xff0c;人工智能正以前所未有的態勢滲透進各個領域&#xff0c;農業也不例外。想象一下&#xff0c;未來的農田里&#xff0c;農民不再是彎腰勞作的形象&#xff0c;而是坐在高科技的“智能農場”里&#xff0c;悠閑地喝著咖啡&#xff0c;指揮著…

LLM的Deep Research功能:重構人類認知與創新的新范式

在人工智能迅速發展的今天&#xff0c;大語言模型&#xff08;LLM&#xff09;的deep research功能正在成為重構人類認知方式的關鍵力量。 這一突破性的技術進展不僅帶來了工具層面的革新&#xff0c;更深刻地觸及了人類認知能力的本質。 本文將從認知科學的視角出發&#xf…

【Cadence仿真技巧學習筆記】求解65nm庫晶體管參數un, e0, Cox

在設計放大器的第一步就是確定好晶體管參數和直流工作點的選取。通過閱讀文獻&#xff0c;我了解到L波段低噪聲放大器的mos器件最優寬度計算公式為 W o p t . p 3 2 1 ω L C o x R s Q s p W_{opt.p}\frac{3}{2}\frac{1}{\omega LC_{ox}R_{s}Q_{sp}} Wopt.p?23?ωLCox?Rs…

前端力扣刷題 | 6:hot100之 矩陣

73. 矩陣置零 給定一個 m x n 的矩陣&#xff0c;如果一個元素為 0 &#xff0c;則將其所在行和列的所有元素都設為 0 。請使用 原地 算法。 法一&#xff1a; var setZeroes function(matrix) {let setX new Set(); // 用于存儲需要置零的行索引let setY new Set(); //…

每日一題——有效括號序列

有效括號序列 題目描述數據范圍&#xff1a;復雜度要求&#xff1a; 示例題解代碼實現代碼解析1. 定義棧和棧操作2. 棧的基本操作3. 主函數 isValid4. 返回值 時間和空間復雜度分析 題目描述 給出一個僅包含字符 (, ), {, }, [, ] 的字符串&#xff0c;判斷該字符串是否是一個…

集合通訊概覽

&#xff08;1&#xff09;通信的算法 是根據通訊的鏈路組成的 &#xff08;2&#xff09;因為通信鏈路 跟硬件強相關&#xff0c;所以每個CCL的庫都不一樣 芯片與芯片、不同U之間是怎么通信的&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; 很重要…

紅黑樹的封裝

一、封裝思路 在 STL 中 map set 的底層就是封裝了一棵紅黑樹。 其中連接紅黑樹和容器的是迭代器&#xff0c;map set 暴露出的接口都不是自己寫的&#xff0c;而是紅黑樹寫的&#xff0c;外部接口封裝紅黑樹接口。 所以寫出紅黑樹為 map set 寫的接口&#xff0c;再在上層的…

java異常處理——try catch finally

單個異常處理 1.當try里的代碼發生了catch里指定類型的異常之后&#xff0c;才會執行catch里的代碼&#xff0c;程序正常執行到結尾 2.如果try里的代碼發生了非catch指定類型的異常&#xff0c;則會強制停止程序&#xff0c;報錯 3.finally修飾的代碼一定會執行&#xff0c;除…

使用QMUI實現用戶協議對話框

使用QMUI實現用戶協議對話框 懶加載用于初始化 TermServiceDialogController 對象。 懶加載 lazy var 的作用 lazy var dialogController: TermServiceDialogController {let r TermServiceDialogController()r.primaryButton.addTarget(self, action: #selector(primaryC…

C++進階: 紅黑樹及map與set封裝

紅黑樹總結整理 紅黑色概述&#xff1a; 紅黑樹整理與AVL樹類似&#xff0c;但在對樹的平衡做控制時&#xff0c;AVL樹會比紅黑樹更嚴格。 AVL樹是通過引入平衡因子的概念進行對樹高度控制。 紅黑樹則是對每個節點標記顏色&#xff0c;對顏色進行控制。 紅黑樹控制規則&…

在Qt中,slots 關鍵字有什么用?

有下面的Qt代碼&#xff1a; #ifndef MAINWINDOW_H #define MAINWINDOW_H#include <QMainWindow>QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } QT_END_NAMESPACEclass MainWindow : public QMainWindow {Q_OBJECTpublic:MainWindow(QWidget *parent nullptr…