1. 程式人生 > >NumPy 學習 第三篇:向量化和廣播

NumPy 學習 第三篇:向量化和廣播

向量化

向量化是指用陣列表示式替換顯式的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" 異常。

 

參考文件:

NumPy 向量化

NumPy 廣播

Array Broadcasting in N