NumPy

**NumPy** 是 Python 語言的一個擴充程式庫。支援高階大規模的多維陣列與矩陣運算，此外也針對陣列運算提供大量的數學函式函式庫。NumPy 的前身 **Numeric** 最早是由 Jim Hugunin 與其它協作者共同開發，2005 年，Travis Oliphant 在 Numeric 中結合了另一個同性質的程式庫 Numarray 的特色，並加入了其它擴充功能而開發了 NumPy。NumPy 為開放原始碼並且由許多協作者共同維護開發。

## 歷史

### Matrix-sig

儘管很早就受到了科學界和工業界的關注，但 Python 最初並不是為數值計算設計的。1995 年，特殊興趣小組（Special Interest Group，SIG）Matrix-sig 成立，其目的是設計一個陣列計算包。Matrix-sig 的成員中有 Python 的設計者和維護者吉多・范羅蘇姆，他擴充了 Python 的語法（特別是索引語法），使陣列計算更容易。

### Numeric

矩陣包 Numeric 由 Jim Fulton 實現，並由 Jim Hugunin 推廣， (也稱 Numerical Python extensions 或 NumPy)。Jim Hugunin 是麻省理工學院的研究生， 於 1997 年加入國家研究計劃公司從事 JPython 的研發，勞倫斯利弗莫爾國家實驗室的 Paul Dubois 接任維護者。其他早期貢獻者包括 David Ascher, Konrad Hinsen 和 Travis Oliphant。

### Numarray

Numarray 是作為 Numeric 的替代品被開發出來的，現已廢棄。相比於 Numeric，Numarray 處理大陣列速度較快，然而處理小陣列速度較慢，因此有一段時間這兩個包被並列使用於不同情況。Numeric 的最後一個版本（v24.2）於 2005 年 11 月 11 日釋出；Numarray 的最後一個版本（v1.5.2）於 2006 年 8 月 24 日釋出。

有人希望將 Numeric 納入 Python 標準庫，但吉多・范羅蘇姆認為，在當時的情況下，代碼難以維護。

### NumPy

2005 年初，NumPy 的開發者 Travis Oliphant 希望社群的不同陣列包可以統一。他將 Numarray 的功能移植到 Numeric 上，並於 2006 將結果作為 NumPy 1.0 釋出。這個新專案是 SciPy 的一部分。為了避免在只需陣列計算的情況下安裝龐大的 SciPy 包，新包以 NumPy 的名義被分離出來。2011 年，NumPy 的 1.5.0 版本加入了對 Python 3 的支援。

2011 年，PyPy 開始開發 NumPy API，但它尚未與 NumPy 完全相容。

## 特色

NumPy 參考 CPython（一個使用位元組碼的直譯器），而在這個 Python 實作直譯器上所寫的數學演算法程式碼通常遠比編譯過的相同程式碼要來得慢。為了解決這個難題，NumPy 引入了多維陣列以及可以直接有效率地操作多維陣列的函式與運算子。因此在 NumPy 上只要能被表示為針對陣列或矩陣運算的演算法，其執行效率幾乎都可以與編譯過的等效 C 語言程式碼一樣快。

NumPy 提供了與 MATLAB 相似的功能與操作方式，因為兩者皆為直譯語言，並且都可以讓使用者在針對陣列或矩陣運算時提供較純量運算更快的效能。兩者相較之下，MATLAB 提供了大量的擴充工具箱（例如 Simulink）；而 NumPy 則是根基於 Python 這個更現代、完整並且開放原始碼的程式語言之上。此外 NumPy 也可以結合其它的 Python 擴充函式庫。例如 SciPy，這個函式庫提供了更多與 MATLAB 相似的功能；以及 Matplotlib，這是一個與 MATLAB 內建繪圖功能類似的函式庫。而從本質上來說，NumPy 與 MATLAB 同樣是利用 BLAS 與 LAPACK 來提供高效率的線性代數運算。

### ndarray 資料結構

NumPy 的核心功能是 ndarray（即 _n_-dimensional array，多維陣列）資料結構。這是一個表示多維度、同質並且固定大小的陣列物件。而由一個與此陣列相關聯的資料型態物件來描述其陣列元素的資料格式（例如其字元組順序、在記憶體中佔用的字元組數量、整數或者浮點數等等）。

### 局限性

在陣列中插入或追加元素並不像 Python 的 list 一樣簡單。`np.pad(...)` 實際上建立了新的具有目標形狀和填充值的陣列，將給定陣列的值複製到新陣列中並返回新陣列。`np.concatenate([a1,a2])` 並沒有直接連接兩個陣列，而是返回新的陣列，該陣列填充了兩個原陣列的值。用 `np.reshape(...)` 改變陣列的維度只有在陣列中元素數量不變的情況下才能實現。造成以上情況的原因是 NumPy 的陣列必須占用連續的記憶體空間。Blaze 包嘗試克服這個限制。

未經向量化的演算法通常執行緩慢，因為它們必須用純 Python 方法實現；由於需要建立和輸入等大的臨時陣列，部分操作的向量化可能會增長其空間複雜度（例如由常數增長到線性）。部分小組通過執行時編譯（Runtime compilation of numerical code）避免這一問題。可與 NumPy 整合的開源解決方案包括 numexpr 和 Numba。Cython 和 Pythran 是靜態編譯的解決方案。

許多現代大型科學計算應用的要求超出了 NumPy 陣列的能力。例如，NumPy 陣列通常載入到電腦的記憶體中，然而記憶體可能沒有足夠的容量；此外，NumPy 僅在單個 CPU 上進行操作，而許多線性代數算子可以通過 CPU 的叢集和其它特殊硬體（例如 GPU、TPU，部分深度學習應用也依賴於這些特殊硬體）來加速。因此，近期在 Python 的生態中出現了許多其它工具，例如用於分散式陣列的 Dask、用於 GPU 計算的 TensorFlow 和 JAX 等。這些庫通常實現或模仿 NumPy 的部分 API，因此使用者不需大量改動就可以部署原先使用 NumPy 的程式。近期出現的由 Nvidia 的 CUDA 架構加速的 CuPy 庫展示了快速計算的潛力，是 NumPy 的直接替代品。

## 語法

**格點**

**基本運算**

**全域方法**

**線性代數**

## 參考資料

## 擴充閱讀

* Bressert, Eli. Scipy and Numpy: An Overview for Developers. O'Reilly Media. 2012. ISBN 978-1-4493-0546-8.
* McKinney, Wes. Python for Data Analysis: Data Wrangling with Pandas, NumPy, and IPython 2nd. Sebastopol: O'Reilly. 2017. ISBN 978-1-4919-5766-0.
* VanderPlas, Jake. Introduction to NumPy. Python Data Science Handbook: Essential Tools for Working with Data. O'Reilly. 2016: 33–96. ISBN 978-1-4919-1205-8.

## 外部連結

* 官方網站
* History of NumPy（頁面存檔備份，存於網際網路檔案館）