【Python进阶】你真的明白NumPy中的ndarray吗?
歡迎來到專欄《Python進階》。在這個專欄中,我們會講述Python的各種進階操作,包括Python對文件、數據的處理,Python各種好用的庫如NumPy、Scipy、Matplotlib、Pandas的使用等等。我們的初心就是帶大家更好的掌握Python這門語言,讓它能為我所用。
今天是《Python進階》專欄的第三期,在本期中,我們將主要介紹Numpy的一些進階知識。
作者&編輯 | 湯興旺
如果你想掌握Python,那么NumPy是你必須要精通的。NumPy實際上是Python語言的一個擴展程序庫,支持高維數組與矩陣運算,提供了大量的數學函數庫。
1 ndarray內存機制
我們知道NumPy最重要的一個特點是其N維數組對象ndarray。通常ndarray內部由以下內容組成。
數據指針:一個指向實際數據的指針;
數據類型(dtype):描述了數組中每個元素所占的字節(jié)數;
維度(shape):一個表示數組形狀(各維度大小)的元組。
跨度(strides):一個表示從當前元素前進到下一個元素需要跨過的字節(jié)數。
我們通過下面的代碼看下ndarray的內容:
import numpy as np
a = np.arange(1,25).reshape((2,2,2,3))
print(type(a))
print(a.shape)
print(a.dtype)
print(a.strides)
這里的shape是指每個維度元素的個數。這里的四維數組每個維度的元素個數分別為2、2、2和3。咦,這好像不對呀!2+2+2+3=9,這不等于24呀!難道我分析錯了嗎?
當然不是,我們首先將a輸出來,結果如下:
這里最里面一層[ ]可以代表1個一維數組,里面有3個元素。加粗的紅色一對[ ]代表二維數組,它里面有二個[ ],即二維數組中有2個一維數組。所以認為第三維度中元素個數為2;加粗的紫色一對[ ]代表三維數組,它里面有二個[ ],即三維數組中有2個二維數組。所以認為第二維度中元素個數為2。同理,第一維度中元素個數為2。
相信你現在應該明白了shape中的元組為啥是(2,2,2,3)了吧。
說完shape,我們再來看下dtype,它是指數組元素類型,注意,這里的數組元組就是指1,2,...,23,24這樣的元素。另外數組中每個元素的類型都是相同的,在這個數組中,數組中每個元素類型都為int32。
最后我們再分析下跨度(strides)。它是指從當前元素前進到下一個元素需要跨過的字節(jié)數。
我們可以看出上面例子中的strides=(48,24,12,4)。那么這四個數是怎么來的呢?
我們在上面的四維數組中,dtype 為 int,而int 占 4個字節(jié)。而第四維度里面有3個元素,總字節(jié)數為12,所以從第四度跨到第三維度需要跨過的字節(jié)數為12;第三維度里面有2個元素(一維數組),每個一維數組的總字節(jié)數為12,所以從第三維度跨到第二維度需要跨過的字節(jié)數為24。同理,從第二維度跨到第一維度的字節(jié)數為48。
所以上面例子中的四維數組的跨度為(48,24,12,4),它在內存中的表示如下圖所示:
從上圖可以明顯的看出從要想到達第三維度(軸2),必須跨過第四維度(軸3),需要跨過3個元素,字節(jié)數為12;要想到達第一維度(軸0),必須跨過第二、三、四維度,總共12個元素,字節(jié)數為12*4=48。
這也就是在NumPy 中數據存儲的方式。它存儲在一個均勻連續(xù)的內存塊中,可以這么理解,NumPy 將多維數組在內部以一維數組的方式存儲,我們只要知道了每個元素所占的字節(jié)數(dtype)以及每個維度中元素的個數(shape),就可以快速定位到任意維度的任意一個元素。
2 NumPy高維數組索引與轉置
2.1 索引
當提到索引時,你可能覺得很簡單,不就是通過索引獲取某個元素嗎?道理的確是這樣的。但是在面對高維數組時,通過索引來獲取某個元素還是比較麻煩的。
下面我們通過一個案例來分析下一個四維數組的索引。
如果我想取得上圖中17這個元素,應該怎么辦呢?
首先將這個四維數組用上圖的軸的形式來表示。我們可以先把它看成四個塊,其中第0軸和第1軸確定某個塊的位置,第2軸和第3軸確定塊中某個元素具體的位置。
圖中的17在第3塊,如下圖的黃色部分,用0軸和1軸來表示的話,索引就是[1,0]。
現在塊的位置確定了,接下來我們確定塊中元素的位置。如下圖所示:
17這個元素在上圖中的索引為[1,1]。接下來我們只需要把確定塊的索引[1,0]和確定塊中元素的索引[]按照[第0軸,第1軸,第2軸,第3軸]這樣的格式合并即可,在這個案例中,合并后17的索引為[1,0,1,1]。
當然,你可以用下面的代碼確認下,我們的分析是否正確。
import numpy as np? ?
a = np.arange(1,25).reshape((2,2,2,3))
print(a[1,0,1,1])??
這個就是高維數組的索引,你已經明白了嗎?
2.2 高維數組轉置
高維數組的轉置一直是學習NumPy的一個難點,盡管在NumPy中只需要調用numpy.transpose就可以完成轉置操作,但是你真的能分析清楚為什么結果是這樣的嗎?尤其是高維數組。下面我們就舉一個比較簡單的例子來分析下。如下:
上圖是原數組,我們經過下面的代碼進行轉置,會得到如下的結果:
import numpy as np
b = a.transpose((1,0,2))
轉置后的結果:
相信你已經看出了具體的差別了,那就是軸的索引順序的互換。因為在代碼中我們要求0軸和1軸互換,因此轉置后的結果實際上就是a[1,0]會變成原數組a[0,1];a[0,1]會變成原數組a[1,0]。如果用圖表示,就如下圖所示:
相信你已經明白了其中的原理了,接下來留一個思考題,如下:
請問,從左到右怎么轉置才能得到!
總結
本期我們介紹了ndarray的內存機制及高維數組的索引和轉置。NumPy的知識還有很多,上面介紹的只是NumPy中比較難理解的幾個問題,若想更加系統的學習NumPy及知道上面思考題的分析過程和答案,請移步我們的知識星球!
下期預告:Python庫Scipy的高級應用
有三AI編程與開源框架知識星球
有三AI編程與開源框架知識星球創(chuàng)建了,歡迎加入,希望大家能借助這個平臺,扎實自己的編程基礎。
轉載文章請后臺聯系
侵權必究
往期精選
【Python進階】Python進階專欄、編程與開源框架知識星球上線,等你來follow
【Python進階】實戰(zhàn)Python圖像文件操作基本編程
【雜談】菜鳥誤入linux會有哪些慘痛的經歷
【TensorFlow2.0】TensorFlow2.0專欄上線,你來嗎?
【TensorFlow2.0】以后我們再也離不開Keras了?
【TensorFlow2.0】數據讀取與使用方式
【TensorFlow2.0】如何搭建網絡模型
總結
以上是生活随笔為你收集整理的【Python进阶】你真的明白NumPy中的ndarray吗?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【图像分类】从数据集和经典网络开始
- 下一篇: 【知乎直播】千奇百怪的CNN网络架构等你