在科學(xué)計(jì)算與數(shù)據(jù)分析領(lǐng)域,計(jì)算效率與數(shù)據(jù)結(jié)構(gòu)同樣重要。NumPy 通過(guò)引入統(tǒng)一類型的多維數(shù)組,將數(shù)據(jù)表示與批量運(yùn)算結(jié)合起來(lái),使大規(guī)模數(shù)值計(jì)算成為可能。
一、為什么需要數(shù)組計(jì)算
在純 Python 中,我們通常使用 list 存儲(chǔ)一組數(shù)據(jù):
nums = [1, 2, 3, 4]這種結(jié)構(gòu)適合通用數(shù)據(jù)容器,但并不適合大規(guī)模數(shù)值計(jì)算。原因在于:
? 列表中的元素是對(duì)象引用,而不是連續(xù)數(shù)值塊
? 每個(gè)元素可以是不同類型
? 運(yùn)算依賴 Python 解釋器逐個(gè)循環(huán)執(zhí)行
比如:
result = [x * 2 for x in nums] # Python 層循環(huán)在數(shù)值規(guī)模較大時(shí),這種執(zhí)行會(huì)產(chǎn)生兩個(gè)問(wèn)題:
(1)內(nèi)存布局分散,緩存利用率低
(2)運(yùn)算在解釋器層逐元素執(zhí)行,無(wú)法批量?jī)?yōu)化
而科學(xué)計(jì)算的核心需求是:
? 同類型數(shù)值的緊湊存儲(chǔ)
? 對(duì)規(guī)則內(nèi)存布局的高效訪問(wèn)
? 批量執(zhí)行能力
? 向量化計(jì)算支持
NumPy 的 ndarray 正是在這一背景下被設(shè)計(jì)出來(lái)的。
二、ndarray 的結(jié)構(gòu)構(gòu)成
在 NumPy 中,幾乎所有數(shù)值計(jì)算都圍繞一個(gè)核心類型展開(kāi):
numpy.ndarray它是“n-dimensional array”的縮寫(xiě),即“n 維數(shù)組”。
ndarray 是一個(gè)類(class),其對(duì)象實(shí)例表示一個(gè) n 維數(shù)組。
每一個(gè) ndarray 實(shí)例都包含以下關(guān)鍵結(jié)構(gòu)信息:
(1)底層數(shù)據(jù)緩沖區(qū)
(2)數(shù)據(jù)類型描述(dtype 屬性)
(3)形狀信息(shape 屬性)
(4)維度數(shù)量(ndim 屬性)
(5)元素總數(shù)(size 屬性)
(6)步長(zhǎng)信息(strides 屬性)
這些屬性共同決定這塊連續(xù)內(nèi)存如何被解釋為一個(gè)多維數(shù)值結(jié)構(gòu)。
![]()
ndarray 以底層數(shù)據(jù)緩沖區(qū)(Buffer)和一組描述該數(shù)據(jù)如何解釋的元數(shù)據(jù)(metadata)構(gòu)成。很多數(shù)組是連續(xù)存儲(chǔ)的,但數(shù)組視圖不一定總是內(nèi)存連續(xù)。
三、dtype:數(shù)組元素的類型
在 Python 列表中:
lst = [1, 2.5, "abc"]元素類型可以完全不同。
而在 ndarray 中:
arr = np.array([1, 2, 3]) # 返回 ndarray 對(duì)象ndarray 中的元素會(huì)以統(tǒng)一的 dtype 存儲(chǔ)和解釋。
NumPy 會(huì)強(qiáng)制轉(zhuǎn)換為同一 dtype,并不是要求輸入同一類型。
dtype 是 ndarray 對(duì)象的一個(gè)屬性,用于描述數(shù)組中每個(gè)元素的數(shù)據(jù)類型。
查看類型:
print(arr.itemsize) # 每個(gè)元素占用字節(jié)數(shù)在多數(shù) 64 位系統(tǒng)上輸出:
8表示 arr 數(shù)組中的每個(gè)元素是一個(gè)占 8 字節(jié)的整數(shù)。
常見(jiàn)的 dtype 數(shù)據(jù)類型有:
? 整數(shù):int32 / int64
? 浮點(diǎn)數(shù):float32 / float64
? 布爾型:bool
? 復(fù)數(shù):complex128
可以在創(chuàng)建數(shù)組時(shí)手動(dòng)指定元素的類型:
print(arr.itemsize) # 每個(gè)元素占用字節(jié)數(shù)NumPy 還會(huì)根據(jù)輸入推斷一個(gè)“可兼容”的統(tǒng)一類型:
print(arr.dtype) # float64統(tǒng)一元素?cái)?shù)據(jù)類型具有以下意義:
? 決定每個(gè)元素占用的字節(jié)數(shù)(影響內(nèi)存)
? 決定數(shù)值精度(影響計(jì)算結(jié)果)
? 決定運(yùn)算行為(整數(shù)運(yùn)算或浮點(diǎn)運(yùn)算等)
dtype 是 ndarray 的類型系統(tǒng)基礎(chǔ)。
四、shape:數(shù)組的結(jié)構(gòu)信息
shape 是 ndarray 的屬性,返回一個(gè)元組,表示數(shù)組在每個(gè)維度上的長(zhǎng)度。
示例:
print(arr.shape) # (2, 3)表示數(shù)組第 0 維的長(zhǎng)度為 2,第 1 維的長(zhǎng)度為 3,這是一個(gè) 2 行 3 列的二維數(shù)組。
ndarray 數(shù)組還提供了其他屬性來(lái)查看相關(guān)結(jié)構(gòu)信息:
.ndim:數(shù)組的維度數(shù)量
.size:數(shù)組的元素總數(shù)
print(arr.size) # 6 表示元素總數(shù) 2*3NumPy 使用統(tǒng)一的 ndarray 結(jié)構(gòu)描述任意維度的數(shù)據(jù)。
![]()
從數(shù)學(xué)對(duì)象的角度看,不同維度的 ndarray 通常可以這樣理解:
? 0 維 ndarray:可看作標(biāo)量(Scalar)的數(shù)組化表示
? 1 維 ndarray:通常可表示向量(Vector)
? 2 維 ndarray:通常可表示矩陣(Matrix)
? 3 維及以上 ndarray:通常可表示更高階張量(Tensor)
五、創(chuàng)建 ndarray的方法
與 Python 的 list 不同,ndarray 沒(méi)有專屬字面量語(yǔ)法(如 {} 或 [])。它必須通過(guò) NumPy 提供的函數(shù)構(gòu)造。
這些函數(shù)都可以指定 dtype,并返回 ndarray 對(duì)象。
若未指定 dtype,NumPy 會(huì)根據(jù)輸入數(shù)據(jù)自動(dòng)推斷;某些初始化函數(shù)(如 zeros、ones)默認(rèn) dtype 為 float64。
1、從序列創(chuàng)建
np.array() 主要用于將序列(列表、元組及嵌套序列等)轉(zhuǎn)換為 ndarray。
np.array(object, dtype=None)示例:
arr = np.array([1, 2, 3]) # 返回 ndarray提示:
由于集合(set)不能保證順序、字典(dict)只會(huì)取鍵,因此不建議使用它們來(lái)轉(zhuǎn)換為 ndarray。
2、區(qū)間創(chuàng)建
np.arange()生成等間隔數(shù)值序列,返回 ndarray。
np.arange(start, stop, step, dtype=None)示例:
arr = np.arange(0, 10, 2) # [0 2 4 6 8]np.linspace() 可按給定區(qū)間和數(shù)量生成等距數(shù)值,返回 ndarray。
np.linspace(start, stop, num, dtype=None)示例:
arr = np.linspace(1, 9, 5) # 默認(rèn) float64np.linspace() 默認(rèn)結(jié)果通常為浮點(diǎn)類型。
3、初始化函數(shù)
np.zeros() 可返回元素全是 0 的 ndarray 數(shù)組。
np.zeros(shape, dtype=None) 示例:
arr = np.zeros((2, 3))np.ones() 可返回元素全是 1 的 ndarray 數(shù)組。
np.ones(shape, dtype=None) 示例:
arr = np.ones((2, 2, 3)) # 返回一個(gè)三維數(shù)組np.full() 可返回元素全是指定值的 ndarray 數(shù)組。
np.full(shape, fill_value, dtype=None)示例:
arr = np.full((2, 3), 5) # 返回全是 5 的兩行三列的二維數(shù)組np.eye() 默認(rèn)可創(chuàng)建主對(duì)角線為 1、其余為 0 的二維數(shù)組;最常見(jiàn)情形是單位矩陣。
np.eye(N, M=None, k=0, dtype=float)示例:
arr = np.eye(5) # 返回一個(gè) 5 行 5 列的單位矩陣從結(jié)構(gòu)層面看,這些函數(shù)都會(huì)分配一塊連續(xù)內(nèi)存緩沖區(qū),并為其附加 dtype、shape 等元數(shù)據(jù),最終構(gòu)造一個(gè) ndarray 實(shí)例。
要注意的是,當(dāng)直接打印創(chuàng)建好的 ndarray 實(shí)例:
print(arr)輸出形式通常為:
[3 4]]這是“字符串表示”,不是語(yǔ)法結(jié)構(gòu)。
特點(diǎn):
? 元素之間以空格分隔(不是逗號(hào))
? 多維結(jié)構(gòu)使用嵌套方括號(hào)表示
六、基礎(chǔ)索引與切片
雖然 ndarray 沒(méi)有字面量語(yǔ)法,但它支持與列表類似的索引和切片語(yǔ)法。
1、索引
(1)一維索引
使用 [ ] 選取單個(gè)位置,通常返回一個(gè)標(biāo)量值。
arr[0](2)多維索引
使用逗號(hào)分隔維度。
arr[0, 1]雖然 arr[0][1] 也是合法表達(dá)式,但它會(huì)先返回一個(gè)中間數(shù)組對(duì)象,再進(jìn)行索引。推薦使用 arr[0, 1] 這種多維索引元組形式。
2、切片
在 ndarray 中,切片語(yǔ)法沿用 Python 的基本切片表達(dá)式形式:
start : stop : step對(duì)于一維數(shù)組而言,切片方式幾乎是一樣:
arr = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8])arr[::2] # [0 2 4 6 8]不過(guò),NumPy 支持“多維同時(shí)切片”,并且每個(gè)維度的切片表達(dá)式使用逗號(hào)分隔。
一般形式為:
arr[維度0切片, 維度1切片, ..., 維度N切片]此處的“維度n切片”可以是:
? 整數(shù)(選取該維度的某個(gè)位置)
? 切片表達(dá)式(start:stop:step)
? 冒號(hào) :(表示該維度全部)
? 省略號(hào) ...(表示剩余所有維度)
示例:
[7, 8, 9]])對(duì)于二維數(shù)組而言,維度切片表達(dá)式 arr[a, b] 中,第 0 個(gè)位置對(duì)應(yīng)第 0 維(通常理解為“行”),第 1 個(gè)位置對(duì)應(yīng)第 1 維(通常理解為“列”)。
但從機(jī)制上看,NumPy 并不是“先選行再選列”,而是同時(shí)對(duì)兩個(gè)維度進(jìn)行索引。
比如,選取第 0 列:
col = arr[:, 0] # [1 4 7]第 0 維使用 : 表示選取所有行。第 1 維使用 0 表示選取第 0 列。
選取前兩行、后兩列:
sub = arr[0:2, 1:3]0:2 表示選取第 0 行、第 1 行。1:3 表示選取第 1 列、第 2 列。
要強(qiáng)調(diào)的是,在多數(shù)基本切片情況下(不包含高級(jí)索引),返回的是原數(shù)組的“視圖”(通常共享內(nèi)存)。
七、數(shù)組運(yùn)算的統(tǒng)一模型
NumPy 數(shù)組支持逐元素運(yùn)算。
a + b結(jié)果:
[5 7 9]運(yùn)算由底層 C 實(shí)現(xiàn)的 ufunc(通用函數(shù))執(zhí)行,在連續(xù)內(nèi)存上進(jìn)行逐元素批量計(jì)算。
這種逐元素批量計(jì)算模式通常稱為向量化(vectorization),是 NumPy 獲得高性能的重要原因之一。
小結(jié)
ndarray 是由底層數(shù)據(jù)緩沖區(qū)與結(jié)構(gòu)元數(shù)據(jù)共同構(gòu)成的多維數(shù)值數(shù)組對(duì)象。其 dtype、shape、strides 等屬性用于解釋內(nèi)存布局,實(shí)現(xiàn)統(tǒng)一類型與向量化計(jì)算。這種結(jié)構(gòu)突破了 Python 列表的對(duì)象模型限制,是科學(xué)計(jì)算與機(jī)器學(xué)習(xí)的基礎(chǔ)數(shù)據(jù)結(jié)構(gòu)。
“點(diǎn)贊有美意,贊賞是鼓勵(lì)”
特別聲明:以上內(nèi)容(如有圖片或視頻亦包括在內(nèi))為自媒體平臺(tái)“網(wǎng)易號(hào)”用戶上傳并發(fā)布,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.