矢量化
矢量化是指用數組表達式替換顯式的for循環,在Python中循環數組或其他跟數組類似的數據結構時,使用循環會涉及很多開銷。NumPy中的矢量化操作把內部循環委托給高度優化的C和Fortran函數,從而實現更清晰,更快速的Python代碼。
矢量化是NumPy中的一種強大功能,可以把操作表達為“在整個數組上而不是在各個元素上”發生,Python內部隱式對數組的各個元素執行相同的操作。
矢量化對每個元素執行相同的操作,對於原生的Python代碼,舉一個簡單的例子,考慮將1維數組中的每個元素與相同長度的另一個序列中的相應元素相乘的情況。如果數據存儲在兩個Python 列表 a
和 b
中,我們可以迭代每個元素,如下所示:
c = [] for i in range(len(a)): c.append(a[i]*b[i])
當涉及到 ndarray 時,逐個元素的操作是“默認模式”:
c = a * b
廣播
兩個形狀相同的NumPy數組之間的操作是按元素操作的,對於大小不同的數組,按照廣播規則來進行。廣播(Broadcasting)描述了 numpy 如何在算術運算期間處理具有不同形狀的數組。
1,廣播的原理
NumPy 通常在數組的每個元素上執行相同的操作,在最簡單的情況下,兩個數組具有完全相同的形狀,如下例所示,a和b都是數組,對數組執行相乘操作,Python內部執行的操作是對位置相同的元素執行相乘操作:
>>> a = np.array([1.0, 2.0, 3.0]) >>> b = np.array([2.0, 2.0, 2.0]) >>> a * b array([ 2., 4., 6.])
當數組的形狀滿足某些約束時,NumPy的廣播規則放寬了這種約束。當一個數組和一個標量值在一個操作中組合時,會發生最簡單的廣播示例,a是數組,b是標量:
>>> a = np.array([1.0, 2.0, 3.0]) >>> b = 2.0 >>> a * b array([ 2., 4., 6.])
結果等同於前面的示例,在算術運算期間,想象b是被拉伸成跟
數組a的形狀相同的數組,數組b的每個元素都是2.0
。
拉伸類比只是概念性的,NumPy足夠聰明,可以使用原始標量值而無需實際構造數組。
2,廣播規則
為了進行廣播,在操作中兩個陣列的末尾維度的尺寸必須相同,或者必須有一個維度的尺寸是相同的。
舉個例子,數據a的shape是(4,3),數組b的shape是(1,3),兩個數組的末尾維度是2,形狀是兼容的:
技術細節:較小的數組會在較大的數組中“廣播”,以便它們具有兼容的形狀。
廣播規則:廣播使用以下2個規則處理具有不同形狀的兩個數組:
- 讓所有輸入數組都向其中形狀最長的數組看齊,形狀中不足的部分都通過在前面加 1 補齊。
- 當輸入數組的某個維度的長度為 1 時,沿着此維度運算時都用此維度上的第一組值,也就是說,在任何一個維度上,如果一個數組的維度為1,另一個數組的維度大於1,那么在該維度上,就好像是對第一個數組進行了復制。
簡單理解:對兩個數組,分別比較它們的每一個維度(若其中一個數組沒有當前維度則忽略),滿足以下三個條件:
- 數組擁有相同形狀。
- 當前維度的值相等。
- 當前維度的值有一個是 1。
若條件不滿足,拋出 "ValueError: frames are not aligned" 異常。
參考文檔: