歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux綜合 >> Linux資訊 >> 更多Linux

使用 Numeric 軟件包和 Numarray 軟件包

  Numerical Python (通常稱為 NumPy) 是一個廣為應用的 Python 擴展庫,用於快速處理任意維數的固定類型數組。由於底層代碼是充分優化的 C 語言代碼,因而對數組的主要操作在 NumPy 調用中執行時,速度不再受到 Python 解釋器的限制。因為 NumPy 已經取得了這樣的成功,所以 NumPy 的開發者將用一個叫做 Numarray 的新模塊來取代 NumPy,新模塊基本上 (但並不是完全) 與 NumPy 兼容。在本文中,David 介紹了 NumPy 的一般功能,以及 Numarray 將要帶來的一些特殊改進。    要了解 Numerical Python 軟件包的第一件事情是,Numerical Python 不會讓您去做標准 Python 不能完成的任何工作。它只是讓您 以快得多的速度 去完成標准 Python 能夠完成的相同任務。實際上不僅僅如此;許多數組操作用 Numeric 或者 Numarray 來表達比起用標准 Python 數據類型和語法來表達要優雅得多。不過,驚人的速度才是吸引用戶使用 Numerical Python 的主要原因。    其實,Numerical Python 只是實現了一個新的數據類型:數組。與可以包含不同類型元素的列表、元組和詞典不同的是,Numarray 數組只能包含同一類型的數據。Numarray 數組的另一個優點是,它可以是多維的 -- 但是數組的維度與列表的簡單嵌套稍有不同。Numerical Python 借鑒了程序員的實踐經驗(尤其是那些有科學計算背景的程序員,他們抽象出了 APL、FORTRAN、MATLAB 和 S 等語言中數組的最佳功能),創建了可以靈活改變形狀和維度的數組。我們很快會回來繼續這一話題。    在 Numerical Python 中對數組的操作是 按元素 進行的。雖然二維數組與線性代數中的矩陣類似,但是對它們的操作 (比如乘) 與線性代數中的操作 (比如矩陣乘) 是完全不同的。    讓我們來看一個關於上述問題的的具體例子。在純 Python 中,您可以這樣創建一個“二維列表”:    清單 1. Python 的嵌套數組  >>> pyarr = [[1,2,3],  ...     [4,5,6],  ...     [7,8,9]]  >>> print pyarr  [[1, 2, 3], [4, 5, 6], [7, 8, 9]]  >>> pyarr[1][1] = 0  >>> print pyarr  [[1, 2, 3], [4, 0, 6], [7, 8, 9]]    很好,但是您對這種結構所能做的只是通過單獨的 (或者多維的) 索引來設置和檢索元素。與此相比,Numarray 數組要更靈活:    清單 2. Numerical Python 數組  >>> from numarray import *  >>> numarr = array(pyarr)  >>> print numarr  [[1 2 3]  [4 0 6]  [7 8 9]]    改變並不大,但是使用 Numarray 進行的操作如何呢? 下面是一個例子:    清單 3. 元素操作  >>> numarr2 = numarr * 2  >>> print numarr2  [[ 2 4 6]  [ 8 0 12]  [14 16 18]]  >>> print numarr2 + numarr  [[ 3 6 9]  [12 0 18]  [21 24 27]]    改變數組的形狀:    清單 4. 改變形狀  >>> numarr2.shape = (9,)  >>> print numarr2  [ 2 4 6 8 0 12 14 16 18]    Numeric 與 Numarray 之間的區別  總體來看,新的 Numarray 軟件包與早期的 Numeric 是 API 兼容的。不過,開發者基於用戶經驗進行了一些與 Numric 並不兼容的改進。開發者沒有破壞任何依賴於 Numeric 的應用程序,而是開創了一個叫做 Numarray 的新項目。在完成本文時,Numarray 還缺少 Numeric 的一些功能,但是已計劃實現這些功能。    Numarray 所做的一些改進:    以分層的類結構來組織元素類型,以支持 isinstance() 檢驗。Numeric 在指定數據類型時只使用字符類型編碼 (但是 Numarray 中的初始化軟件仍然接受老的字符編碼)。  改變了類型強制規則,以保持數組(更為常見)中的類型 ,而不是轉換為 Python 標量的類型。  出現了附加的數組屬性 (不再只有 getter 和 setter)。  實現了更靈活的異常處理。    新用戶不必擔心這些變化,就這一點來說,最好一開始就使用 Numarray 而不是 Numeric。    計時的例子  讓我們來感受一下在 Numerical Python 中的操作相對於標准 Python 的速度優勢。作為一個“演示任務”,我們將創建一個數字序列,然後使它們加倍。首先是標准 Python 方法的一些變體:    清單 5. 對純 Python 操作的計時  def timer(fun, n, comment=""):  from time import clock  start = clock()  print comment, len(fun(n)), "elements",  print "in %.2f seconds" % (clock()-start)  def double1(n): return map(lambda n: 2*n, xrange(n))  timer(double1, 5000000, "Running map() on xrange iterator:")  def double2(n): return [2*n for n in xrange(n)]  timer(double2, 5000000, "Running listcomp on xrange iter: ")  def double3(n):  double = []  for n in xrange(n):  double.append(2*n)  return double  timer(double3, 5000000, "Building new list from iterator: ")    我們可以看出 map() 方法、list comprehension 和傳統循環方法之間的速度差別。那麼,需要同類元素類型的標准 array 模塊呢?它可能會更快一些:    清單 6. 對標准 array 模塊的計時  import array  def double4(n): return [2*n for n in array.array('i',range(n))]  timer(double4, 5000000, "Running listcomp on array.array: ")    最後我們來看 Numarray 的速度如何。作為額外對照,我們來看如果必須要將數組還原為一個標准的列表時,它是否同樣具有優勢:    清單 7. 對 Numarray 操作的計時  from numarray import *  def double5(n): return 2*arange(n)  timer(double5, 5000000, "Numarray scalar multiplication: ")  def double6(n): return (2*arange(n)).tolist()  timer(double6, 5000000, "Numarray mult, returning list:  ")    現在運行它:    清單 8. 比較結果  $ python2.3 timing.py  Running map() on xrange iterator: 5000000 elements in 13.61 seconds  Running listcomp on xrange iter: 5000000 elements in 16.46 seconds  Building new list from iterator: 5000000 elements in 20.13 seconds  Running listcomp on array.array: 5000000 elements in 25.58 seconds  Numarray scalar multiplication:  5000000 elements in 0.61 seconds  Numarray mult, returning list:  5000000 elements in 3.70 seconds    處理列表的不同技術之間的速度差異不大,也許還是值得注意,因為這是嘗試標准的 array 模塊時的方法問題。但是 Numarray 一般用不到 1/20 的時間內就可以完成操作。將數組還原為標准列表損失了很大的速度優勢。    不應通過這樣一個簡單的比較就得出結論,但是這種加速可能是典型的。對大規模科學計算來說,將計算的時間由幾個月下降到幾天或者從幾天下降到幾個小時,是非常有價值的。    系統建模  Numerical Python 的典型用例是科學建模,或者可能是相關領域,比如圖形處理和旋轉,或者信號處理。我將通過一個比較實際的問題來說明 Numarray 的許多功能。假設您有一個參量可變的三維物理空間。抽象地說,任何參數化空間,不論有多少維,Numarray 都適用。實際上很容易想像,比如一個房間,它的各個點的溫度是不同的。我在 New England 的家已經到了冬天,因而這個問題似乎更有現實意義。    為簡單起見,下面我給出的例子中使用的是較小的數組(雖然這可能是顯然的,但是還是有必要明確地指出來)。不過,即使是處理有上百萬個元素而不僅僅是幾十個元素的數組,Numarray 也還是很快;前者可能在真正的科學模型中更為常見。    首先,我們來創建一個“房間”。有很多方法可以完成這項任務,但是最常用的還是使用可調用的 array() 方法。使用這個方法,我們可以生成具有多種初始化參數 (包括來自任何 Python 序列的初始數據) 的 Numerical 數組。不過對於我們的房間來說,用 zeros() 函數就可以生成一個溫度均勻的寒冷房間:    清單 9. 初始化房間的溫度  >>> from numarray import *  >>> room = zeros((4,3,5),Float)  >>> print room  [[[ 0. 0. 0. 0. 0.]  [ 0. 0. 0. 0. 0.]  [ 0. 0. 0. 0. 0.]]    [[ 0. 0. 0. 0. 0.]  [ 0. 0. 0. 0. 0.]  [ 0. 0. 0. 0. 0.]]    [[ 0. 0. 0. 0. 0.]  [ 0. 0. 0. 0. 0.]  [ 0. 0. 0. 0. 0.]]    [[ 0. 0. 0. 0. 0.]  [ 0. 0. 0. 0. 0.]  [ 0. 0. 0. 0. 0.]]]    自上而下每一個二維的“矩陣”代表三維房間的一個水平層面。    首先,我們將整個房間的溫度提高到比較舒適的 70 華氏度 (大約是 20 攝氏度):    清單 10. 打開加熱器  >>> room += 70  >>> print room  [[[ 70. 70. 70. 70. 70.]  [ 70. 70. 70. 70. 70.]  [ 70. 70. 70. 70. 70.]]    [[ 70. 70. 70. 70. 70.]  [ 70. 70. 70. 70. 70.]  [ 70. 70. 70. 70. 70.]]    [[ 70. 70. 70. 70. 70.]  [ 70. 70. 70. 70. 70.]  [ 70. 70. 70. 70




Copyright © Linux教程網 All Rights Reserved