官术网_书友最值得收藏!

1.4 深入探究NumPy世界

NumPy提供了高性能的數組類型,以及在Python中操作這些數組的例程。這些數組對于處理性能至關重要的大型數據集非常有用。NumPy構成了Python中數值和科學計算的基礎。在底層,NumPy利用底層庫來處理向量和矩陣,如基本線性代數子程序(Basic Linear Algebra Subprogram, BLAS,以加速計算。

傳統上,將NumPy包以較短的別名np導入,可以通過以下導入語句來完成:

這種約定在NumPy文檔和更廣泛的科學Python生態系統(如SciPy、pandas等)中都得到了應用。

NumPy庫提供的基本數據類型是ndarray(以下稱為NumPy數組)。通常情況下,你不會創建自己的ndarray實例,而是使用諸如array這樣的輔助例程來正確設置類型。array例程利用類似數組的對象來創建NumPy數組,該對象通常是數字列表或列表的列表。例如,我們可以通過提供包含所需元素的列表來創建一個簡單的數組:

NumPy數組類型(ndarray)是圍繞底層C數組結構的Python封裝。數組操作是用C語言實現的,并針對性能進行了優化。NumPy數組必須由同質數據(所有元素具有相同的類型)組成,盡管這種類型可能是指向任意Python對象的指針。如果沒有使用dtype關鍵字顯式指定數據類型,NumPy將在創建過程中推斷出合適的數據類型:

NumPy為許多C類型提供了類型說明符,這些類型可以傳遞到dtype參數中,例如,先前使用的np.float32。一般來說,這些類型說明符的形式為namexx,其中name是類型的名稱(例如int、float或complex),而xx是位數,例如8、16、32、64、128。通常,NumPy在為給定的輸入選擇適當的數據類型方面做得相當不錯,但偶爾你可能會想要覆蓋它。前面的例子就是一個很好的例子,如果沒有dtype=np.float32參數,則NumPy會假定它的類型為int64。

在底層,任何形狀的NumPy數組都可以被看作包含原始數據和附加元數據集合的緩沖區,其中原始數據是展平的(一維)數組,附加元數據集合用于指定諸如元素類型等詳細信息。

創建后,可以使用數組的dtype屬性訪問數據類型。修改dtype屬性會產生不良后果,因為構成數組數據的原始字節將被簡單地重新解釋為新的數據類型。例如,如果使用Python整數創建數組,NumPy會將這些整數轉換為數組中的64位整數。更改dtype值將導致NumPy將這些64位整數重新解釋為新的數據類型:

每個64位整數都被重新解釋為兩個32位浮點數,這顯然會得到無意義的值。相反,如果你希望在創建后更改數據類型,請使用astype方法指定新類型。更改數據類型的正確方法如下所示:

NumPy還提供了許多用于創建各種標準數組的例程。zeros例程會創建一個指定形狀的數組,數組中的每個元素都是0,ones例程則會創建一個元素都是1的數組。

1.4.1 元素訪問

NumPy數組支持getitem協議,因此可以像訪問列表一樣訪問數組中的元素,并支持所有逐元素執行的算術運算。這意味著我們可以使用索引符號和索引位置從指定的數組中檢索元素,如下所示:

它還可以用于從現有數組中提取數據數組的常用切片語法。數組的切片還是一個數組,其中包含由切片指定的元素。例如,我們可以檢索ary數組的前兩個元素,或者檢索ary數組的偶數索引處的元素,如下所示:

切片的語法為start:stop:step。我們可以省略start和stop參數中的一個或兩個,分別從所有元素的開頭或結束處檢索元素。我們還可以省略step參數,在這種情況下,我們還可以刪除尾隨的冒號“:”。step參數描述了應該選擇選定范圍內的元素。step值為1表示選擇每個元素,或者如示例所示,step值為2表示每隔一個元素選擇一次(從0開始選擇偶數索引號的元素)。此語法與Python列表的切片語法相同。

1.4.2 數組的算術運算和函數

NumPy提供了許多通用函數(ufuncs),這些函數可以高效地對NumPy數組類型進行操作。特別地,在1.3節中討論的所有基本數學函數在NumPy中都有類似的函數,可以用來對NumPy數組進行操作。通用函數還可以執行廣播(broadcasting),以使它們能夠在形狀不同但兼容的數組上進行操作。

對NumPy數組的算術運算是逐元素進行的。以下示例最能說明這一點:

請注意,這里的數組必須具有相同的形狀,也就是說,它們必須具有相同的長度。對不同形狀的數組進行算術運算將會拋出ValueError異常。數組與單個數字進行加法、減法、乘法或除法運算將生成一個數組,相應運算作用于數組的每個元素。例如,我們可以使用以下命令將數組中的所有元素乘以2:

正如我們所見,輸出的數組包含數字2、4、6和8,它們是原始數組中的各元素乘以2得到的結果。

在1.4.3節中,除了我們在這里使用的np.array例程外,我們還將研究創建NumPy數組的各種方法。

1.4.3 有用的數組創建例程

要在兩個給定端點之間以規律間隔生成數組,可以使用arange例程或lins-pace例程。這兩個例程的區別在于,linspace在兩個端點之間生成等間隔的一定數量(默認為50個)的數值,生成的數組包括兩個端點,而arange以給定的步長生成數值,最大值不包括右端點。linspace例程在閉區間axb內生成數值,而arange例程則在半開區間axb內生成數值:

請注意,使用linspace生成的數組正好有5個點,這是由第三個參數指定的,這5個點中包括兩個端點0和1。而使用arange生成的數組有4個點,不包括右端點1,如果再加一個步長0.3,則將等于1.2,這就大于1了。

1.4.4 高維數組

NumPy可以創建任意維數的數組,使用的是與創建簡單一維數組相同的array例程。數組的維數由提供給array例程的嵌套列表的數量指定。例如,我們可以通過提供列表的列表來創建二維數組,其中內層列表的每個元素都是數字,如下所示:

NumPy數組具有shape屬性,該屬性描述了每個維度中元素的排列方式。對于二維數組,shape可以解釋為數組的行數和列數。

三維或三維以上的數組有時稱為張量。事實上,可以將任何大小的數組稱為張量:向量(一維數組)是1-張量;二維數組是2-張量或矩陣——請參閱1.5節。常見的機器學習(ML)框架,如TensorFlow和PyTorch,都實現了它們自己的張量類,這些張量類的操作方式總是與NumPy數組類似。

NumPy將形狀存儲為array對象上的shape屬性,該屬性是一個元組。該元組中的元素數量就是數組的維數:

由于NumPy數組中的數據存儲在一個展平的(一維)數組中,因此通過簡單地更改關聯的元數據,可以很容易地重塑數組。這一過程可以使用NumPy數組的reshape方法來完成:

請注意,元素的總數必須保持不變。矩陣mat最初的形狀是(2,2),總共有4個元素,而重塑后的數組是一個形狀為(4,)的一維數組,同樣有4個元素。如果在元素的總數不匹配時進行數組重塑,將導致ValueError錯誤。

要創建更高維度的數組,只需添加更多級別的嵌套列表。為了更清晰地說明這一點,在下面的例子中,我們在構建數組之前分離出第三維中每個元素的列表:

注意

數組形狀的第一個元素是最外層的,最后一個元素是最內層的。

這意味著向數組添加維度只需提供相關的元數據即可。使用array例程,shape元數據由參數中每個列表的長度來描述。最外層列表的長度定義該維度的相應shape參數,以此類推。

NumPy數組在內存中的大小在很大程度上并不取決于維度的數量,而僅取決于元素的總數,即shape參數的乘積。然而,請注意,在高維數組中,元素的總數往往更大。

要訪問多維數組中的元素,可以使用通常的索引表示法,但是與提供單個數字不同,你需要在每個維度中提供索引。對于2×2矩陣,這意味著指定所需元素的行和列:

索引表示法還支持在每個維度中進行切片,因此我們可以通過使用切片mat[:,0]來提取單個列的所有元素,如下所示:

請注意,切片的結果是一維數組。

數組創建函數zeros和ones可以通過簡單地指定具有多個維度參數的形狀來創建多維數組。

在1.5節中,我們將研究二維NumPy數組的特殊情況,在Python中它們可以用作矩陣。

主站蜘蛛池模板: 长春市| 麻栗坡县| 林芝县| 四平市| 满城县| 庐江县| 久治县| 海安县| 仪陇县| 叶城县| 宁远县| 湄潭县| 务川| 通山县| 韶关市| 山丹县| 巩义市| 汶川县| 淅川县| 措勤县| 桂林市| 宜川县| 万州区| 旌德县| 滁州市| 木里| 电白县| 鸡泽县| 嘉义县| 陕西省| 永兴县| 德惠市| 长治县| 新闻| 奉化市| 丰县| 景泰县| 阿勒泰市| 平舆县| 洪泽县| 滕州市|