NumPy與 Matlab 比較

介紹

MATLAB?和NumPy / SciPy有很多共同之處。但是有很多不同之處。創(chuàng)建NumPy和SciPy是為了用Python最自然的方式進(jìn)行數(shù)值和科學(xué)計算,而不是MATLAB?克隆。本頁面旨在收集有關(guān)差異的智慧,主要是為了幫助熟練的MATLAB?用戶成為熟練的NumPy和SciPy用戶。

一些關(guān)鍵的差異

MATLAB NumPy
在MATLAB?中,基本數(shù)據(jù)類型是雙精度浮點(diǎn)數(shù)的多維數(shù)組。大多數(shù)表達(dá)式采用這樣的數(shù)組并返回這樣的數(shù) 對這些數(shù)組的2-D實(shí)例的操作被設(shè)計成或多或少地像線性代數(shù)中的矩陣運(yùn)算。 在NumPy中,基本類型是多維的array。包括2D在內(nèi)的所有維度中對這些數(shù)組的操作是逐元素操作。人們需要使用線性代數(shù)的特定函數(shù)(盡管對于矩陣乘法,可以@在python 3.5及更高版本中使用運(yùn)算符)。
MATLAB?使用基于1(一)的索引。使用(1)找到序列的初始元素。 請參閱備注 Python使用基于0(零)的索引。使用[0]找到序列的初始元素。
MATLAB?的腳本語言是為執(zhí)行線性代數(shù)而創(chuàng)建的?;揪仃嚥僮鞯恼Z法很好而且干凈,但是用于添加GUI和制作完整應(yīng)用程序的API或多或少都是事后的想法。 NumPy基于Python,它從一開始就被設(shè)計成一種優(yōu)秀的通用編程語言。雖然Matlab的一些數(shù)組操作的語法比NumPy更緊湊,但NumPy(由于是Python的附加組件)可以做許多Matlab不能做的事情,例如正確處理矩陣堆棧。
在MATLAB?中,數(shù)組具有按值傳遞的語義,并具有惰性寫入時復(fù)制方案,以防止在實(shí)際需要之前實(shí)際創(chuàng)建副本。切片操作復(fù)制數(shù)組的一部分。 在NumPy數(shù)組中有傳遞引用語義。切片操作是對數(shù)組的視圖。

'array'或'matrix'?我應(yīng)該使用哪個?

從歷史上看,NumPy提供了一種特殊的矩陣類型 np.matrix ,它是ndarray的子??類,它使二進(jìn)制運(yùn)算成為線性代數(shù)運(yùn)算。您可能會在某些現(xiàn)有代碼中看到它而不是 np.array 。那么,使用哪一個?

簡答

使用數(shù)組。

  • 它們是numpy的標(biāo)準(zhǔn)矢量/矩陣/張量類型。許多numpy函數(shù)返回數(shù)組,而不是矩陣。
  • 元素操作和線性代數(shù)操作之間有明顯的區(qū)別。
  • 如果您愿意,可以使用標(biāo)準(zhǔn)向量或行/列向量。

在Python 3.5之前,使用數(shù)組類型的唯一缺點(diǎn)是你必須使用dot而不是*乘法(減少)兩個張量(標(biāo)量乘積,矩陣向量乘法等)。從Python 3.5開始,您可以使用矩陣乘法@運(yùn)算符。

鑒于上述情況,我們打算matrix最終棄用。

長答案

NumPy包含array類和matrix類。所述
array類旨在是對許多種數(shù)值計算的通用n維數(shù)組中,而matrix意在具體促進(jìn)線性代數(shù)計算。在實(shí)踐中,兩者之間只有少數(shù)關(guān)鍵差異。

  • 運(yùn)算符*@函數(shù)dot(),以及multiply()
    • 對于數(shù)組,*表示逐元素乘法,而 @ 表示矩陣乘法; 它們具有相關(guān)的函數(shù) multiply()dot() 。(在python 3.5之前,@ 不存在,并且必須使用dot() 進(jìn)行矩陣乘法)。
    • 對于矩陣,* 表示矩陣乘法,對于逐元素乘法,必須使用 multiply() 函數(shù)。
  • 矢量處理(一維數(shù)組)
    • 對于數(shù)組,向量形狀1xN,Nx1和N都是不同的東西。 像 A[:, 1] 這樣的操作返回形狀N的一維數(shù)組,而不是形狀Nx1的二維數(shù)組。 在一維數(shù)組上轉(zhuǎn)置什么都不做。
    • 對于矩陣,一維數(shù)組總是被上變頻為1xN或Nx1矩陣(行或列向量)。A[:, 1] 返回形狀為Nx1的二維矩陣。
  • 處理更高維數(shù)組(ndim> 2)
    • 數(shù)組對象的維數(shù)可以 > 2 ;
    • 矩陣對象總是有兩個維度。
  • 便利屬性
    • array 有一個.T屬性,它返回數(shù)據(jù)的轉(zhuǎn)置。
    • matrix 還有.H,.I和.A屬性,分別返回共軛轉(zhuǎn)置,反轉(zhuǎn)和asarray()矩陣。
  • 便利構(gòu)造函數(shù)
    • array構(gòu)造采用(嵌套)的Python序列初始化。如:array([[1,2,3],[4,5,6]])。
    • matrix構(gòu)造還需要一個方便的字符串初始化。如:matrix("[1 2 3; 4 5 6]")。

使用兩者有利有弊:

  • array
    • :) 元素乘法很容易:A*B。
    • :( 你必須記住,矩陣乘法有自己的運(yùn)算符@
    • :) 可以將一維數(shù)組視為行向量或列向量。 A @ vv 視為列向量,而 v @ Av 視為行向量。這可以節(jié)省您鍵入許多轉(zhuǎn)置。
    • :) array 是“默認(rèn)”NumPy類型,因此它獲得的測試最多,并且是使用NumPy的第三方代碼最有可能返回的類型。
    • :) 非常擅長處理任何維度的數(shù)據(jù)。
    • :) 如果你熟悉那么語義學(xué)更接近張量代數(shù)。
    • :) 所有 操作(*,/+,-等)逐元素。
    • :( 稀疏矩陣scipy.sparse不與數(shù)組交互。
  • matrix
    • :\\ 行為更像MATLAB?矩陣。
    • <:( 最大二維。要保存您需要的三維數(shù)據(jù),array或者可能是Python列表matrix
    • <:( 最小二維。你不能有載體。它們必須作為單列或單行矩陣進(jìn)行轉(zhuǎn)換。
    • <:( 由于array是NumPy中的默認(rèn)值,因此array即使您將它們matrix作為參數(shù)給出,某些函數(shù)也可能返回。這不應(yīng)該發(fā)生在NumPy函數(shù)中(如果它確實(shí)是一個錯誤),但基于NumPy的第三方代碼可能不像NumPy那樣遵守類型保存。
    • :) A*B是矩陣乘法,所以它看起來就像你在線性代數(shù)中寫的那樣(對于Python> = 3.5普通數(shù)組與@運(yùn)算符具有相同的便利性)。
    • <:( 元素乘法需要調(diào)用函數(shù), multiply(A,B)
    • <:( 運(yùn)算符重載的使用有點(diǎn)不合邏輯:* 不能按元素操作,但 / 確實(shí)如此。
    • 與之互動scipy.sparse有點(diǎn)清潔。

因此,使用 數(shù)組(array) 要明智得多。事實(shí)上,我們打算最終廢除 矩陣(matrix)。

MATLAB 和 NumPy粗略的功能對應(yīng)表

下表給出了一些常見MATLAB?表達(dá)式的粗略等價物。這些不是確切的等價物,而應(yīng)該作為提示讓你朝著正確的方向前進(jìn)。有關(guān)更多詳細(xì)信息,請閱讀NumPy函數(shù)的內(nèi)置文檔。

在下表中,假設(shè)您已在Python中執(zhí)行以下命令:

from numpy import *
import scipy.linalg

另外如果下表中的注釋這一列的內(nèi)容是和 “matrix” 有關(guān)的話,那么參數(shù)一定是二維的形式。

一般功能的對應(yīng)表

MATLAB NumPy 注釋
help func info(func)或者h(yuǎn)elp(func)或func?(在IPython的) 獲得函數(shù)func的幫助
which func 請參閱備注 找出func定義的位置
type func source(func)或者func??(在Ipython中) func的打印源(如果不是本機(jī)函數(shù))
a && b a and b 短路邏輯AND運(yùn)算符(Python本機(jī)運(yùn)算符); 只有標(biāo)量參數(shù)
a
b
1*i,1*j, 1i,1j 1j 復(fù)數(shù)
eps np.spacing(1) 1與最近的浮點(diǎn)數(shù)之間的距離。
ode45 scipy.integrate.solve_ivp(f) 將ODE與Runge-Kutta 4,5集成
ode15s scipy.integrate.solve_ivp(f, method='BDF') 將ODE與BDF方法集成

線性代數(shù)功能對應(yīng)表

MATLAB NumPy 注釋
ndims(a) ndim(a) 要么 a.ndim 獲取數(shù)組的維數(shù)
numel(a) size(a) 要么 a.size 獲取數(shù)組的元素數(shù)
size(a) shape(a) 要么 a.shape 得到矩陣的“大小”
size(a,n) a.shape[n-1] 獲取數(shù)組第n維元素的數(shù)量a。(請注意,MATLAB?使用基于1的索引,而Python使用基于0的索引,請參閱備注
[ 1 2 3; 4 5 6 ] array([[1.,2.,3.], [4.,5.,6.]]) 2x3矩陣文字
[ a b; c d ] block([[a,b], [c,d]]) 從塊構(gòu)造一個矩陣a,b,c,和d
a(end) a[-1] 訪問1xn矩陣中的最后一個元素 a
a(2,5) a[1,4] 訪問第二行,第五列中的元素
a(2,:) a[1] 或者 a[1,:] a的第二行
a(1:5,:) a[0:5]或a[:5]或a[0:5,:] 前五行 a
a(end-4:end,:) a[-5:] a的最后五行
a(1:3,5:9) a[0:3][:,4:9] a的第一至第三行與第五至第九列交叉的元素。這提供了只讀訪問權(quán)限。
a([2,4,5],[1,3]) a[ix_([1,3,4],[0,2])] 第2,4,5行與第1,3列交叉的元素。這允許修改矩陣,并且不需要常規(guī)切片。
a(3:2:21,:) a[ 2:21:2,:] 返回a的第3行與第21行之間每隔一行的行,即第3行與第21行之間的a的奇數(shù)行
a(1:2:end,:) a[ ::2,:] 返回a的奇數(shù)行
a(end: -1:1,:) 要么 flipud(a) a[ ::-1,:] 以相反的順序排列的a的行
a([1:end 1],: ) a[r_[:len(a),0]] a 的第一行添加到a的末尾行的副本
a.' a.transpose() 要么 a.T 轉(zhuǎn)置 a
a' a.conj().transpose() 要么 a.conj().T 共軛轉(zhuǎn)置 a
a * b a @ b 矩陣乘法
a .* b a * b 元素乘法
a./b a/b 元素除法
a.^3 a**3 元素取冪
(a>0.5) (a>0.5) 其i,jth元素為(a_ij> 0.5)的矩陣。Matlab結(jié)果是一個0和1的數(shù)組。NumPy結(jié)果是布爾值的數(shù)組False和True。
find(a>0.5) nonzero(a>0.5) 找到a中所有大于0.5的元素的線性位置
a(:,find(v>0.5)) a[:,nonzero(v>0.5)[0]] 提取a中向量v> 0.5的對應(yīng)的列
a(:,find(v>0.5)) a[:,v.T>0.5] 提取a中向量v> 0.5的對應(yīng)的列
a(a<0.5)=0 a[a<0.5]=0 a中小于0.5的元素賦值為0
a .* (a>0.5) a * (a>0.5) 返回一個數(shù)組,若a中對應(yīng)位置元素大于0.5,取該元素的值;若a中對應(yīng)元素<=0.5,取值0
a(: ) = 3 a[:] = 3 將所有值設(shè)置為相同的標(biāo)量值
y=x y = x.copy() numpy通過引用分配
y=x(2,:) y = x[1,:].copy() numpy切片是參考
y=x(: ) y = x.flatten() 將數(shù)組轉(zhuǎn)換為向量(請注意,這會強(qiáng)制復(fù)制)
1:10 arange(1.,11.)或r_[1.:11.]或 r_[1:10:10j] 創(chuàng)建一個增加的向量,步長為默認(rèn)值1(參見備注
0:9 arange(10.)或 r_[:10.]或 r_[:9:10j] 創(chuàng)建一個增加的向量,步長為默認(rèn)值1(參見注釋范圍)
[1:10]' arange(1.,11.)[:, newaxis] 創(chuàng)建列向量
zeros(3,4) zeros((3,4)) 3x4二維數(shù)組,充滿64位浮點(diǎn)零
zeros(3,4,5) zeros((3,4,5)) 3x4x5三維數(shù)組,全部為64位浮點(diǎn)零
ones(3,4) ones((3,4)) 3x4二維數(shù)組,充滿64位浮點(diǎn)數(shù)
eye(3) eye(3) 3x3單位矩陣
diag(a) diag(a) 返回a的對角元素
diag(a,0) diag(a,0) 方形對角矩陣,其非零值是元素 a
rand(3,4) random.rand(3,4) 要么 random.random_sample((3, 4)) 隨機(jī)3x4矩陣
linspace(1,3,4) linspace(1,3,4) 4個等間距的樣本,介于1和3之間
[x,y]=meshgrid(0:8,0:5) mgrid[0:9.,0:6.] 要么 meshgrid(r_[0:9.],r_[0:6.] 兩個2D數(shù)組:一個是x值,另一個是y值
ogrid[0:9.,0:6.] 要么 ix_(r_[0:9.],r_[0:6.] 在網(wǎng)格上評估函數(shù)的最佳方法
[x,y]=meshgrid([1,2,4],[2,4,5]) meshgrid([1,2,4],[2,4,5])
ix_([1,2,4],[2,4,5]) 在網(wǎng)格上評估函數(shù)的最佳方法
repmat(a, m, n) tile(a, (m, n)) 用n份副本創(chuàng)建m a
[a b] concatenate((a,b),1)或者h(yuǎn)stack((a,b))或 column_stack((a,b))或c_[a,b] 連接a和的列b
[a; b] concatenate((a,b))或vstack((a,b))或r_[a,b] 連接a和的行b
max(max(a)) a.max() 最大元素a(對于matlab,ndims(a)<= 2)
max(a) a.max(0) 每列矩陣的最大元素 a
max(a,[],2) a.max(1) 每行矩陣的最大元素 a
max(a,b) maximum(a, b) 比較a和b逐個元素,并返回每對中的最大值
norm(v) sqrt(v @ v) 要么 np.linalg.norm(v) L2矢量的規(guī)范 v
a & b logical_and(a,b) 逐個元素AND運(yùn)算符(NumPy ufunc請參閱備注LOGICOPS
a b logical_or(a,b)
bitand(a,b) a & b 按位AND運(yùn)算符(Python native和NumPy ufunc)
bitor(a,b) a b
inv(a) linalg.inv(a) 方陣的逆 a
pinv(a) linalg.pinv(a) 矩陣的偽逆 a
rank(a) linalg.matrix_rank(a) 二維數(shù)組/矩陣的矩陣秩 a
a\b linalg.solve(a,b)如果a是正方形; linalg.lstsq(a,b) 除此以外 ax = b的解為x
b/a 解決aT xT = bT xa = b的解為x
[U,S,V]=svd(a) U, S, Vh = linalg.svd(a), V = Vh.T 奇異值分解 a
chol(a) linalg.cholesky(a).T 矩陣的cholesky分解(chol(a)在matlab中返回一個上三角矩陣,但linalg.cholesky(a)返回一個下三角矩陣)
[V,D]=eig(a) D,V = linalg.eig(a) 特征值和特征向量 a
[V,D]=eig(a,b) D,V = scipy.linalg.eig(a,b) 特征值和特征向量a,b
[V,D]=eigs(a,k)
找到k最大的特征值和特征向量a
[Q,R,P]=qr(a,0) Q,R = scipy.linalg.qr(a) QR分解
[L,U,P]=lu(a) L,U = scipy.linalg.lu(a) 要么 LU,P=scipy.linalg.lu_factor(a) LU分解(注:P(Matlab)==轉(zhuǎn)置(P(numpy)))
conjgrad scipy.sparse.linalg.cg 共軛漸變求解器
fft(a) fft(a) 傅立葉變換 a
ifft(a) ifft(a) 逆傅立葉變換 a
sort(a) sort(a) 要么 a.sort() 對矩陣進(jìn)行排序
[b,I] = sortrows(a,i) I = argsort(a[:,i]), b=a[I,:] 對矩陣的行進(jìn)行排序
regress(y,X) linalg.lstsq(X,y) 多線性回歸
decimate(x, q) scipy.signal.resample(x, len(x)/q) 采用低通濾波的下采樣
unique(a) unique(a)
squeeze(a) a.squeeze()

備注

子矩陣:使用該ix_命令可以使用索引列表完成對子矩陣的分配。例如,對于2D數(shù)組a,可能會做:ind=[1,3]; a[np.ix_(ind,ind)]+=100。

幫助:有MATLAB的沒有直接等價which的命令,但命令helpsource通常會列出其中函數(shù)所在的文件名。Python還有一個inspect模塊(do import inspect),它提供了一個getfile經(jīng)常工作的模塊。

索引:MATLAB?使用一個基于索引,因此序列的初始元素具有索引1.Python使用基于零的索引,因此序列的初始元素具有索引0.出現(xiàn)混淆和火焰,因為每個元素都有優(yōu)點(diǎn)和缺點(diǎn)。一種基于索引的方法與常見的人類語言使用一致,其中序列的“第一”元素具有索引1.基于零的索引簡化了索引

。另見prof.dr的文本。Edsger W. Dijkstra

。

范圍:在MATLAB?中,0:5可以用作范圍文字和“切片”索引(括號內(nèi)); 然而,在Python,構(gòu)建體等0:5可以 被用作切片指數(shù)(方括號內(nèi))。因此,r_創(chuàng)建了一些有點(diǎn)古怪的對象,以使numpy具有類似的簡潔范圍構(gòu)造機(jī)制。請注意,r_它不像函數(shù)或構(gòu)造函數(shù)那樣
被調(diào)用,而是
使用方括號進(jìn)行 索引 ,這允許在參數(shù)中使用Python的切片語法。

邏輯運(yùn)算:&或| 在NumPy中是按位AND / OR,而在Matlab&和|中 是邏輯AND / OR。任何具有重要編程經(jīng)驗的人都應(yīng)該清楚這種差異。這兩者似乎工作原理相同,但存在重要差異。如果您使用過Matlab的&或| 運(yùn)算符,您應(yīng)該使用NumPy ufuncs logical_and / logical_or。Matlab和NumPy的&和|之間的顯著差異 運(yùn)營商是:

  • 非邏輯{0,1}輸入:NumPy的輸出是輸入的按位AND。Matlab將任何非零值視為1并返回邏輯AND。例如,NumPy中的(3和4)是0,而在Matlab中,3和4都被認(rèn)為是邏輯真,而(3和4)返回1。
  • 優(yōu)先級:NumPy的&運(yùn)算符優(yōu)先于<和>之類的邏輯運(yùn)算符; Matlab是相反的。

如果你知道你有布爾參數(shù),你可以使用NumPy的按位運(yùn)算符,但要注意括號,如:z =(x> 1)&(x <2)。缺少NumPy運(yùn)算符形式的logical_and和logical_or是Python設(shè)計的一個不幸結(jié)果。

重塑與線性索引:Matlab總是允許使用標(biāo)量或線性索引訪問多維數(shù)組,而NumPy則不然。線性索引在Matlab程序中很常見,例如矩陣上的find()返回它們,而NumPy的查找行為則不同。在轉(zhuǎn)換Matlab代碼時,可能需要首先將矩陣重新整形為線性序列,執(zhí)行一些索引操作然后重新整形。由于重塑(通常)會在同一存儲上生成視圖,因此應(yīng)該可以相當(dāng)有效地執(zhí)行此操作。請注意,在NumPy中重新整形使用的掃描順序默認(rèn)為'C'順序,而Matlab使用Fortran順序。如果您只是簡單地轉(zhuǎn)換為線性序列,那么這無關(guān)緊要。但是如果要從依賴于掃描順序的Matlab代碼轉(zhuǎn)換重構(gòu),那么這個Matlab代碼:z = reshape(x,3,4) 應(yīng)該變成 z = x.reshape(3,4,order=’F’).copy() 。

自定義您的環(huán)境

在MATLAB?中,可用于自定義環(huán)境的主要工具是使用您喜歡的功能的位置修改搜索路徑。您可以將此類自定義項放入MATLAB將在啟動時運(yùn)行的啟動腳本中。

NumPy,或者更確切地說是Python,具有類似的功能。

  • 要修改Python搜索路徑以包含您自己的模塊的位置,請定義PYTHONPATH環(huán)境變量。
  • 要在啟動交互式Python解釋器時執(zhí)行特定的腳本文件,請定義PYTHONSTARTUP環(huán)境變量以包含啟動腳本的名稱。

與MATLAB?不同,可以立即調(diào)用路徑上的任何內(nèi)容,使用Python,您需要先執(zhí)行“import”語句,以使特定文件中的函數(shù)可訪問。

例如,您可能會創(chuàng)建一個如下所示的啟動腳本(注意:這只是一個示例,而不是“最佳實(shí)踐”的聲明):

# Make all numpy available via shorter 'np' prefix
import numpy as np
# Make all matlib functions accessible at the top level via M.func()
import numpy.matlib as M
# Make some matlib functions accessible directly at the top level via, e.g. rand(3,3)
from numpy.matlib import rand,zeros,ones,empty,eye
# Define a Hermitian function
def hermitian(A, **kwargs):
    return np.transpose(A,**kwargs).conj()
# Make some shortcuts for transpose,hermitian:
#    np.transpose(A) --> T(A)
#    hermitian(A) --> H(A)
T = np.transpose
H = hermitian

鏈接

有關(guān)另一個MATLAB?/ NumPy交叉引用,請參見http://mathesaurus.sf.net/

。

可以在主題軟件頁面中

找到用于python科學(xué)工作的廣泛工具列表。

MATLAB?和SimuLink?是The MathWorks的注冊商標(biāo)。

作者:柯廣的網(wǎng)絡(luò)日志 ? NumPy與 Matlab 比較


微信公眾號:Java大數(shù)據(jù)與數(shù)據(jù)倉庫