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) treats v as a column vector, while dot(v,A) treats v as a row vector. 这可以避免很多转置操作。
    • <:( dot() 用于实现array的矩阵乘法, – dot(dot(A,B),C)用于实现矩阵乘法 vs. A*B*C用于实现元素级算法.
    • :)元素级乘法:A*B
    • :) array
    • :)在可以处理任何数量的维度的数据。
    • :)如果你熟悉的话,靠近语义到张量代数。
    • :) 所有操作(*/+-等)是元素级的实现
  • matrix
    • :\\行为更类似于MATLAB®矩阵。
    • <:(最大二维。要保存三维数据,您需要array或可能是matrix的Python列表。
    • <:(最小二维。你不能有向量。它们必须被转换为单列或单行矩阵。
    • <:( Since array is the default in NumPy, some functions may return an array even if you give them a matrix 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 like ones(), zeros(), empty(), eye(), rand(), repmat(), etc. 通常这些函数返回array s,但matlib版本返回matrix对象。
  • mat has been changed to be a synonym for asmatrix, rather than matrix, thus making it a concise way to convert an array to a matrix 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的对象
  • asmatrixmat:总是返回类型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*i1*j1i1j 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 构造来自块abcd
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结果是布尔值FalseTrue的数组。
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] 连接ab的列
[a; b] concatenate((a,b))vstack((a,b))r_[a,b] 连接ab的行
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) 按元素比较ab,并返回每对的最大值
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) ab的特征值和特征向量
[V,D]=eigs(a,k)   找到ak个最大特征值和特征向量,
[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命令,但命令helpsource函数所在的文件名。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