NumPy for Matlab users¶
Introduction¶
MATLAB和NumPy / SciPy有很多共同点。但是有很多区别。NumPy和SciPy被创建为使用Python以最自然的方式进行数值和科学计算,而不是MATLAB®克隆。此页面旨在描述两者的差异,主要是为了帮助精通MATLAB®的用户成为熟练的NumPy和SciPy用户的目的。
Some Key Differences¶
在MATLAB®中,基本数据类型是双精度浮点数的多维数组。大多数表达式使用这样的数组并返回这样的数组。这些阵列的2-D实例上的操作被设计为或多或少地像线性代数中的矩阵操作。 | 在NumPy中,基本类型是多维array 。在包括2D的所有维度中对这些阵列的操作是元素操作。然而,存在用于进行线性代数的特殊matrix 类型,其仅仅是array 类的子类。矩阵类数组的操作是线性代数运算。 |
MATLAB®使用基于1(一)的索引。使用(1)找到序列的初始元素。See note INDEXING | Python使用基于0(零)的索引。使用[0]找到序列的初始元素。 |
MATLAB®的脚本语言是为做线性代数而创建的。基本矩阵操作的语法是好的和干净的,但是用于添加GUI和创建完整应用程序的API或多或少是事后的想法。 | NumPy基于Python,它从一开始就被设计成一个优秀的通用编程语言。虽然Matlab的一些数组操作的语法比NumPy更紧凑,NumPy(由于是Python的附加组件)可以做许多事情,Matlab不能,例如子类化主数组类型做数组和矩阵数学干净。 |
在MATLAB®中,数组具有按值传递语义,使用惰性写时复制方案来防止实际创建副本,直到它们实际需要。切片操作复制数组的部分。 | 在NumPy数组中有传递引用语义。切片操作是数组中的视图。 |
'数组'或'矩阵'?Which should I use?¶
除了np.ndarray
,NumPy还提供了一个Matrix类型,您可能在某些现有代码中使用。使用哪一个?
Short answer¶
使用数组。
- 它们是numpy的标准向量/矩阵/张量类型。许多numpy函数返回数组,而不是矩阵。
- 在元素方面的操作和线性代数运算之间存在明显的区别。
- 你可以有标准向量或行/列向量如果你喜欢。
使用数组类型的唯一缺点是你必须使用dot
而不是*
来乘以(减少)两个张量(标量积,矩阵向量乘法等))。
Long answer¶
NumPy包含array
类和matrix
类。array
类旨在用于许多种类的数值计算的通用n维数组,而matrix
旨在特别促进线性代数计算。在实践中,两者之间只有少数关键差异。
- 运算符
*
,dot()
和multiply()
:- 对于
array
,'``*``'表示元素级乘法,而dot()
用于矩阵乘法 - 对于
matrix
,'``*``'表示矩阵乘法,而multiply()
用于元素乘法
- 对于
- 处理向量(一维数组)
- 对于
array
,向量形状1xN,Nx1和N都是不同的东西。像A[:,1]
的操作返回形状N的一维数组,而不是形状Nx1的二维数组。在一维array
上转置不执行任何操作。 - 对于
matrix
,,一维数组总是上变频为1xN或Nx1矩阵(行或列向量)。A[:,1]
返回形状为Nx1的二维矩阵。
- 对于
- 高维数组的处理(ndim> 2)
array
对象可以具有多个维度> 2;matrix
对象总是有两个维度。
- 便利属性
array
有一个.T属性,它返回数据的转置。matrix
也有.H,.I和.A属性,它返回矩阵的共轭转置,逆和asarray()
- 方便构造函数
array
构造函数使用(嵌套)Python序列作为初始化器。如,array([[1,2,3],[4,5,6]])
。matrix
构造函数另外采用一个方便的字符串初始化器。如matrix("[1 2 3; 4 5 6]")
。
有使用两者的优点和缺点:
array
:)
您可以将一维数组视为行或列向量。dot(A,v)
treatsv
as a column vector, whiledot(v,A)
treatsv
as a row vector. 这可以避免很多转置操作。<:(
dot()
用于实现array的矩阵乘法, –dot(dot(A,B),C)用于实现矩阵乘法
vs.A*B*C
用于实现元素级算法.:)
元素级乘法:A*B
。:)
array
:)
在可以处理任何数量的维度的数据。:)
如果你熟悉的话,靠近语义到张量代数。:)
所有操作(*
,/
,+
,-
等)是元素级的实现
matrix
:\\
行为更类似于MATLAB®矩阵。<:(
最大二维。要保存三维数据,您需要array
或可能是matrix
的Python列表。<:(
最小二维。你不能有向量。它们必须被转换为单列或单行矩阵。<:(
Sincearray
is the default in NumPy, some functions may return anarray
even if you give them amatrix
as an argument. 这不应该发生与NumPy函数(如果它是一个错误),但基于NumPy的第三方代码可能不会像NumPy那样荣誉类型保存。:)
A*B
是矩阵乘法,因此对于线性代数更方便。<:(
Element-wise multiplication requires calling a function,multipy(A,B)
.<:(
)运算符重载的使用有点不合逻辑:*
不是按元素而是/
因此,使用array
更为明智。
Facilities for Matrix Users¶
NumPy有一些功能,方便使用matrix
类型,这希望使事情更容易Matlab转换。
- A
matlib
module has been added that contains matrix versions of common array constructors likeones()
,zeros()
,empty()
,eye()
,rand()
,repmat()
, etc. 通常这些函数返回array
s,但matlib
版本返回matrix
对象。 mat
has been changed to be a synonym forasmatrix
, rather thanmatrix
, thus making it a concise way to convert anarray
to amatrix
without copying the data.- 某些顶级函数已删除。例如
numpy.rand()
现在需要作为numpy.random.rand()
访问。或者使用matlib
模块中的rand()
。但是“numpythonic”方法是使用numpy.random.random()
,它接受一个元组的形状,像其他numpy函数。
Table of Rough MATLAB-NumPy Equivalents¶
下表给出了一些常见MATLAB®表达式的粗略等价形式。这些不是完全等同的,而是应该被视为提示,让你走正确的方向。有关更多详细信息,请阅读NumPy函数的内置文档。
在编写以数组或矩阵作为参数的函数时,需要注意一些 - 如果你期待一个array
,并给出一个matrix
,反之亦然,乘法)会给你意想不到的结果。你可以在数组和矩阵之间来回转换使用
asarray
:总是返回类型为array
的对象asmatrix
或mat
:总是返回类型matrix
asanyarray
:总是返回一个array
对象或从中派生的子类,具体取决于输入。例如,如果你传入matrix
,它会返回一个matrix
。
这些函数都接受数组和矩阵(尤其是像Python列表),因此在编写应该接受任何数组类对象的函数时非常有用。
在下面的表中,假设你在Python中执行了以下命令:
from numpy import *
import scipy.linalg
还假设在下面,如果Notes谈论“矩阵”的参数是二维实体。
General Purpose Equivalents¶
MATLAB | numpy | 备注 |
---|---|---|
help func |
info(func) 或help(func) 或func? (在Ipython) |
获取函数func的帮助 |
其中 func |
请参阅注意HELP | 找出func在哪里定义 |
键入 func |
source(func) 或func?? (在Ipython) |
打印源为func(如果不是本机函数) |
a &amp;&amp; b |
a 和 b |
短路逻辑AND运算符(Python本地运算符);标量参数 |
a || b |
a 或 b |
短路逻辑OR运算符(Python本地运算符);标量参数 |
1*i ,1*j ,1i ,1j |
1j |
复数 |
eps |
np.spacing(1) |
1和最近的浮点数之间的距离。 |
ode45 |
scipy.integrate.ode(f).set_integrator('dopri5') |
将ODE与Runge-Kutta 4,5集成 |
ode15s |
scipy.integrate.ode(f).set_integrator('vode', method ='bdf', order = 5) / t0> |
将ODE与BDF方法集成 |
Linear Algebra Equivalents¶
MATLAB | NumPy | 笔记 |
---|---|---|
ndims(a) |
ndim(a) 或a.ndim |
获取数组的维数 |
numel(a) |
size(a) 或a.size |
获取数组的元素数 |
size(a) |
shape(a) 或a.shape |
得到矩阵的“大小” |
size(a,n) |
a.shape[n-1] |
得到数组a 的第n维的元素数。(请注意,MATLAB®使用基于1的索引,而Python使用基于0的索引,请参见注释INDEXING) |
[ 1 2 3; 4 t6> 6 ] |
数组([[1.,2.,3. ], [4.,5.,6.。]]) |
2x3矩阵文字 |
[ a b; c d t6> |
vstack([hstack([a,b]), hstack([c,d])]) 或bmat('a b; c d')A |
构造来自块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] |
第1到第3行和第5到第九列a 。这提供只读访问。 |
a([2,4,5],[1,3]) |
a[ix_([1,3,4],[0,2])] |
行2,4和5以及列1和3。这允许矩阵被修改,并且不需要规则切片。 |
a(3:2:21,:) |
a [ 2:21:2,:] |
a 的每隔一行,从第三个开始到第二十一个 |
a(1:2:end,:) |
a [ :: 2,:] |
每隔一行a ,从第一个开始 |
a(end:-1:1,:) 或flipud(a) |
a [ ::-1,:] |
a 以相反的顺序排列 |
a([1:end 1],:) |
a[r_[:len(a),0]] |
a ,第一行的副本附加到结尾 |
a.' |
a.transpose() 或a.T |
转置a |
a' |
a.conj().transpose() 或a.conj().T |
a 的共轭转置 |
a * b |
a.dot(b) |
矩阵乘法 |
a 。 b |
a * b |
元素级乘法 |
a./b |
a/b |
元素分化 |
a.^3 |
a**3 |
元素取幂 |
(a>0.5) |
(a>0.5) |
矩阵,其第i个第j个元素是(a_ij> 0.5)。Matlab结果是一个0和1的数组。NumPy结果是布尔值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 |
a(:,find(v>0.5)) |
a[:,v.T>0.5] |
提取a 的列,其中列向量v> 0.5 |
a(a<0.5)=0 |
a[a<0.5]=0 |
a 中小于0.5的元素清零 |
a 。 (a> 0.5) |
a * (a> 0.5) |
乘于a 中小于0.5的元素 |
a(:) = 3 |
a [:] = 3 |
将所有值设置为相同的标量值3 |
y=x |
y = x.copy() |
numpy按引用分配 |
y=x(2,:) |
y = x [1,:] copy() |
numpy切片通过引用 |
y=x(:) |
y = x.flatten() |
将数组转换成向量(注意,这迫使一个副本) |
1:10 |
arange(1.,11.) 或r_[1.:11.] 或r_[1:10:10j] |
创建增量向量(请参见RANGES) |
0:9 |
arange(10.) 或r_[:10.] 或r_[:9:10j] |
创建增量向量(请参见RANGES) |
[1:10]' |
arange(1.,11. )[:, newaxis] |
创建列向量 |
zeros(3,4) |
zeros((3,4)) |
3x4二维数组充满64位浮点零 |
zeros(3,4,5) |
zeros((3,4,5)) |
3x4x5三维数组充满了64位浮点零 |
ones(3,4) |
ones((3,4)) |
3x4二维数组充满了64位浮点数1 |
eye(3) |
eye(3) |
3x3单位矩阵 |
diag(a) |
diag(a) |
a 的对角元素向量 |
diag(a,0) |
diag(a,0) |
正方形对角矩阵,其非零值是a 的元素 |
rand(3,4) |
random.rand(3,4) |
随机3x4矩阵 |
linspace(1,3,4) |
linspace(1,3,4) |
4个等间隔样本,1和3之间,包括1和3 |
[x,y]=meshgrid(0:8,0:5) |
mgrid[0:9.,0:6.] 或meshgrid(r_[0:9.],r_[0:6.] |
两个二维数组:x值中的一个,y值中的另一个 |
ogrid[0:9.,0:6.] 或ix_(r_[0:9.],r_[0:6.] |
在网格上eval函数的最好方法 | |
[x,y]=meshgrid([1,2,4],[2,4,5]) |
meshgrid([1,2,4],[2,4,5]) |
|
ix_([1,2,4],[2,4,5]) |
在网格上eval函数的最好方法 | |
repmat(a, m, n) |
tile(a, (m, n)) |
使用a 创建m个副本 |
[a b] |
concatenate((a,b),1) 或hstack((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 (具有ndims(a) |
max(a) |
a.max(0) |
矩阵的每一列的最大元素a |
max(a,[],2) |
a.max(1) |
矩阵的每一行的最大元素a |
max(a,b) |
maximum(a, b) |
按元素比较a 和b ,并返回每对的最大值 |
norm(v) |
sqrt(dot(v,v)) 或np.linalg.norm(v) |
L2范数的向量v |
a &amp; b |
logical_and(a,b) |
元素与元素AND运算符(NumPy ufunc)See note LOGICOPS |
a | b |
logical_or(a,b) |
元素by元素OR运算符(NumPy ufunc)See note LOGICOPS |
bitand(a,b) |
a &amp; b |
按位AND运算符(Python本地和NumPy ufunc) |
bitor(a,b) |
a | b |
按位或运算符(Python本地和NumPy ufunc) |
inv(a) |
linalg.inv(a) |
方阵的倒数a |
pinv(a) |
linalg.pinv(a) |
矩阵a 的伪逆 |
rank(a) |
linalg.matrix_rank(a) |
矩阵a 的矩阵秩 |
a\b |
linalg.solve(a,b) if a 是正方形; linalg.lstsq(a,b) |
a的x = b的解 |
b/a |
求解a.T x.T = b.T | x a = b的解 |
[U,S,V]=svd(a) |
U, S, Vh = linalg.svd(a), t5 > V = Vh.T |
a 的奇异值分解 |
chol(a) |
linalg.cholesky(a).T |
matlab中的矩阵(chol(a) )的cholesky因式分解返回上三角矩阵,但linalg.cholesky(a) 返回下三角矩阵) |
[V,D]=eig(a) |
D,V = linalg.eig(a) |
a 的特征值和特征向量 |
[V,D]=eig(a,b) |
V,D = np.linalg.eig(a,b) |
a ,b 的特征值和特征向量 |
[V,D]=eigs(a,k) |
找到a 的k 个最大特征值和特征向量, |
|
[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)==转置(P(numpy))) |
conjgrad |
scipy.sparse.linalg.cg |
共轭梯度求解器 |
fft(a) |
fft(a) |
a 的傅立叶变换 |
ifft(a) |
ifft(a) |
a 的逆傅里叶变换 |
sort(a) |
sort(a) 或a.sort() |
排序矩阵 |
[b,I] = sortrows(a,i) |
I = argsort(a [:,i]), b = a [I,:] t4 > |
对矩阵的行进行排序 |
regress(y,X) |
linalg.lstsq(X,y) |
多线性回归 |
抽取(x, q) |
scipy.signal.resample(x, len(x)/ q) |
使用低通滤波进行下采样 |
unique(a) |
unique(a) |
|
squeeze(a) |
a.squeeze() |
Notes¶
子矩阵:可以使用ix_
命令对索引列表进行子矩阵分配。例如,对于2d数组a
,可以这样做:ind=[1,3]; a[np.ix_(ind,ind)]+=100
。
HELP:没有直接等效的MATLAB which
命令,但命令help
和source
函数所在的文件名。Python还有一个inspect
模块(do import inspect
),它提供了一个getfile
。
INDEXING:MATLAB®使用基于索引的索引,因此序列的初始元素具有索引1。Python使用基于零的索引,因此序列的初始元素具有索引0。混乱和flamewars出现,因为每个都有优点和缺点。基于索引的索引与常见的人类语言使用一致,其中序列的“第一”元素具有索引1。基于零的索引简化索引。另见由prof.dr.的文本。 Edsger W. Dijkstra。
RANGES: In MATLAB®, 0:5
can be used as both a range literal and a ‘slice’ index (inside parentheses); however, in Python, constructs like 0:5
can only be used as a slice index (inside square brackets). 因此,创建了稍微古怪的r_
对象,以允许numpy具有类似的简洁范围构造机制。注意,r_
不像函数或构造函数那样被调用,而是使用方括号来索引,这允许在参数中使用Python的slice语法。
LOGICOPS:&或|在NumPy中是按位AND / OR,而在Matlab中和|是逻辑AND / OR。任何具有重大编程经验的人应该清楚这一区别。两者可能似乎工作相同,但有重要的区别。如果你会使用Matlab的或者运算符,你应该使用NumPy ufuncs logical_and / logical_or。Matlab和NumPy的&和|之间的显着差异运算符是:
- 非逻辑{0,1}输入:NumPy的输出是输入的按位AND。Matlab将任何非零值视为1,并返回逻辑AND。例如,NumPy中的(3和4)为0,而在Matlab中,3和4都被认为是逻辑真,(3和4)返回1。
- 优先级:NumPy的&运算符比逻辑运算符更高的优先级; Matlab的是相反的。
如果你知道你有布尔参数,你可以使用NumPy的位运算符,但要注意括号,像这样:z =(x> 1)&(x没有NumPy运算符形式的logical_and和logical_or是Python设计的一个不幸的后果。
RESHAPE和LINEAR INDEXING:Matlab总是允许使用标量或线性索引访问多维数组,NumPy不允许。线性指数在Matlab程序中是常见的,例如。 find()在一个矩阵返回他们,而NumPy的find行为不同。当转换Matlab代码时,可能需要首先将矩阵重塑成线性序列,执行一些索引操作,然后重新整形。由于重塑(通常)在同一存储上产生视图,因此应该可以相当有效地进行。请注意,NumPy中重塑所使用的扫描顺序默认为“C”顺序,而Matlab使用Fortran顺序。如果你只是转换为线性序列,后面这没关系。但是如果你正在从Matlab代码转换重构依赖于扫描顺序,那么这个Matlab代码:z = reshape(x,3,4);应该在NumPy中变为z = x.reshape(3,4,order ='F')。copy()。
Customizing Your Environment¶
在MATLAB®中,您可用于定制环境的主要工具是使用您喜欢的函数的位置修改搜索路径。你可以把这样的自定义到一个启动脚本,MATLAB将在启动时运行。
NumPy,或者Python,有类似的设施。
- 要修改Python搜索路径以包括自己的模块的位置,请定义
PYTHONPATH
环境变量。 - 要在交互式Python解释器启动时执行特定的脚本文件,请定义
PYTHONSTARTUP
环境变量以包含启动脚本的名称。
与MATLAB不同的是,你的路径上的任何东西都可以立即调用,你需要首先做一个'import'语句,使特定文件中的函数可访问。
例如你可以创建一个类似这样的启动脚本(注意:这只是一个例子,而不是“最佳实践”的语句):
# Make all numpy available via shorter 'num' prefix
import numpy as num
# 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 num.transpose(A,**kwargs).conj()
# Make some shorcuts for transpose,hermitian:
# num.transpose(A) --> T(A)
# hermitian(A) --> H(A)
T = num.transpose
H = hermitian
Links¶
另一个MATLAB®/ NumPy交叉引用参见http://mathesaurus.sf.net/。
使用python进行科学工作的工具的详细列表可以在主题软件页中找到。
MATLAB®和SimuLink®是MathWorks的注册商标。