Numpy 的數組運算與廣播
廣播,是指 Numpy 在算術運算期間處理不同形狀的數組的能力。
對數組的算術運算通常在相應的元素上進行。 如果兩個陣列具有完全相同的形狀,則這些操作被無縫執行,這一小節將通過數組的運算來展示廣播的一些特征。
1. 常見的兩種廣播途徑
1.1 相同大小的數組計算
如果兩個數組的維度完全一致,那么運算過程是兩個數組相應元素的逐個計算。
案例
定義兩個完全一致的數組:
arr0 = np.array([[1, 2, 3], [4, 5, 6]])
arr1 = np.array([[5, 5, 5], [5, 5, 5]])
查看數組結構:
arr0
out:
array([[1, 2, 3],
[4, 5, 6]])
arr1
out:
array([[5, 5, 5],
[5, 5, 5]])
查看加法運算的結果:
arr0 + arr1
out:
array([[ 6, 7, 8],
[ 9, 10, 11]])
查看乘法運算的結果:
arr0 * arr1
out:
array([[ 5, 10, 15],
[20, 25, 30]])
可以看到,如果數組的維度一致,那么廣播則是對應位置的元素運算。
1.2 數組與標量的計算
廣播機制的存在,允許運算發生在不同維度的數組之間,其中最典型的場景,是數組的標量的計算。所謂的標量,我們可以簡單地將之視為是0維的數組。
案例
對于加法運算:
arr0 + 5
out:
array([[ 6, 7, 8],
[ 9, 10, 11]])
對于乘法運算
arr0 * 5
out:
array([[ 5, 10, 15],
[20, 25, 30]])
對于冪運算:
arr0 ** 5
out:
array([[ 1, 32, 243],
[1024, 3125, 7776]], dtype=int32)
可以發現,對于上述效果,是數組每個元素分別與標量進行運算的結果。
直觀地,我們發現,標量在這個二維數組上發生了傳播(廣播),標量沿著數組的兩個維度擴散,直至擴散的結果和待計算的二維數組一致,最后進行計算。
2. 不同維度的數組運算
2.1 沿著一個維度進行廣播
一種簡單的場景是,兩個數組有一定的相似性,即數組(n×m)和數組(1,m)。
案例
arr2 = np.array([[10, 20, 30]])
arr2
out:
array([[10, 20, 30]])
觀察不同大小的數組的廣播規則:
arr0 + arr2
out:
array([[11, 22, 33],
[14, 25, 36]])
arr0 * arr2
out:
array([[ 10, 40, 90],
[ 40, 100, 180]])
觀察發現,arr2沿著arr0的第二個維度擴展了,擴展到二者相匹配,再進行了對應的計算。
可以用一張簡圖來進行描述相加的過程:
2.2沿著兩個維度同時廣播
涉及到兩個維度同時廣播,則相對復雜一些。
案例
arr3 = np.array([[10], [20], [30]])
arr3
out:
array([[10],
[20],
[30]])
觀察沿著2個方向同時廣播的過程:
arr2 + arr3
out:
array([[20, 30, 40],
[30, 40, 50],
[40, 50, 60]])
上述廣播的過程可以按照如下示意進行描述:
2.3 廣播的規則
所以根據上述案例,可以把廣播規則簡單總結如下:
- 讓所有輸入數組都向其中形狀最長的數組看齊,形狀中不足的部分都通過在前面加 1 補齊;
- 輸出數組的形狀是輸入數組形狀的各個維度上的最大值;
- 如果輸入數組的某個維度和輸出數組的對應維度的長度相同或者其長度為 1 時,這個數組能夠用來計算,否則出錯;
- 當輸入數組的某個維度的長度為 1 時,沿著此維度運算時都用此維度上的第一組值。
3. 小結
本節以數組的運算為基礎,介紹了數組在算術運算期間的廣播規則。在實際使用中,廣播的規則強大且靈活,當條件不滿足時,則會拋出 ValueError: frames are not aligned
異常,需要注意。