NumPy面向MATLAB用户#
简介#
MATLAB® 和 NumPy 有很多共同点,但创建 NumPy 是为了与 Python 协作,而不是成为 MATLAB 的克隆.本指南将帮助 MATLAB 用户开始使用 NumPy.
一些主要区别#
在MATLAB中,即使对于标量,基本类型也是多维数组.除非您指定维度和类型,否则MATLAB中的数组赋值将存储为双精度浮点数的二维数组.这些数组的二维实例上的运算是根据线性代数中的矩阵运算建模的. |
在 NumPy 中,基本类型是多维 |
MATLAB 从 1 开始对索引编号; |
NumPy 和 Python 一样,从 0 开始对索引编号; |
MATLAB 的脚本语言是为线性代数创建的,因此某些数组操作的语法比 NumPy 更简洁.另一方面,添加 GUI 和创建功能齐全的应用程序的 API 或多或少是事后才想到的. |
NumPy基于通用语言Python. NumPy 的优势在于可以访问 Python 库,包括: SciPy , Matplotlib , Pandas , OpenCV 等.此外,Python 通常 embedded as a scripting language 在其他软件中,允许 NumPy 也被使用. |
MATLAB 数组切片使用传值语义,并采用延迟写入方案,以防止在需要之前创建副本.切片操作会复制数组的部分内容. |
NumPy 数组切片使用传引用,不会复制参数.切片操作是数组的视图. |
大致等价#
下表给出了一些常见 MATLAB 表达式的大致等价形式.这些是类似的表达式,并非完全等价.有关详细信息,请参见 documentation .
在下表中,假设您已在 Python 中执行以下命令:
import numpy as np
from scipy import io, integrate, linalg, signal
from scipy.sparse.linalg import cg, eigs
此外,假设如果注释中提到“矩阵”,则参数是二维实体.
通用等价#
MATLAB |
NumPy |
注释 |
|---|---|---|
|
|
获取有关函数 func 的帮助 |
|
找出 func 的定义位置 |
|
|
|
打印 func 的源代码(如果不是原生函数) |
|
|
用文本 |
for i=1:3
fprintf('%i\n',i)
end
|
for i in range(1, 4):
print(i)
|
使用 for 循环,用 |
|
|
短路逻辑 AND 运算符 ( Python native operator );仅限标量参数 |
|
|
短路逻辑 OR 运算符 ( Python native operator );仅限标量参数 |
>> 4 == 4
ans = 1
>> 4 == 5
ans = 0
|
>>> 4 == 4
True
>>> 4 == 5
False
|
Python 中的 boolean objects 是 |
a=4
if a==4
fprintf('a = 4\n')
elseif a==5
fprintf('a = 5\n')
end
|
a = 4
if a == 4:
print('a = 4')
elif a == 5:
print('a = 5')
|
创建一个 if-else 语句来检查 |
|
|
复数 |
|
|
双精度浮点数中,1 到下一个较大的可表示实数之间的距离 |
|
|
加载保存到文件 |
|
|
使用 Runge-Kutta 4,5 积分 ODE |
|
|
使用 BDF 方法积分 ODE |
线性代数等价#
MATLAB |
NumPy |
注释 |
|---|---|---|
|
|
数组 |
|
|
数组 |
|
|
数组 |
|
|
获取数组 |
|
|
定义一个2x3的二维数组 |
|
|
从块 |
|
|
访问 MATLAB 向量 (1xn 或 nx1) 或 1D NumPy 数组 |
|
|
访问二维数组 |
|
|
二维数组 |
|
|
二维数组 |
|
|
二维数组 |
|
|
二维数组 |
|
|
第2,4和5行以及第1和3列.这样可以修改矩阵,而不需要常规切片. |
|
|
|
|
|
|
|
|
行倒序的 |
|
|
|
|
|
|
|
|
|
|
|
矩阵乘法 |
|
|
元素乘法 |
|
|
元素除法 |
|
|
元素求幂 |
|
|
矩阵的第i,j个元素是(a_ij > 0.5).MATLAB结果是逻辑值0和1的数组.NumPy结果是布尔值 |
|
|
查找 ( |
|
|
提取向量 v > 0.5 的 |
|
|
提取 |
|
|
将 |
|
|
将 |
|
|
将所有值设置为相同的标量值 |
|
|
NumPy 通过引用赋值 |
|
|
NumPy 切片是通过引用 |
|
|
将数组转换为向量(请注意,这会强制复制). 要获得与 MATLAB 相同的的数据排序,请使用 |
|
|
创建一个递增的向量 (参见 RANGES 注释) |
|
|
创建一个递增的向量 (参见 RANGES 注释) |
|
|
创建一个列向量 |
|
|
3x4 的二维数组,填充 64 位浮点零 |
|
|
3x4x5 的三维数组,填充 64 位浮点零 |
|
|
3x4 的二维数组,填充 64 位浮点一 |
|
|
3x3 的单位矩阵 |
|
|
返回二维数组 |
|
|
返回一个方阵对角矩阵,其非零值是向量 |
rng(42,'twister')
rand(3,4)
|
from numpy.random import default_rng
rng = default_rng(42)
rng.random((3, 4))
或者旧版本: |
生成一个 3x4 的随机数组,使用默认的随机数生成器,并且 seed = 42 |
|
|
1 和 3 之间(包括 1 和 3)的 4 个等间距采样 |
|
|
两个二维数组:一个包含 x 值,另一个包含 y 值 |
|
在网格上评估函数的最佳方法 |
|
|
|
|
|
在网格上评估函数的最佳方法 |
|
|
|
创建 |
|
|
连接 |
|
|
连接 |
|
|
|
|
|
数组 |
|
|
数组 |
|
|
逐元素比较 |
|
|
向量 |
|
|
逐元素AND运算符 (NumPy ufunc) See note LOGICOPS |
|
|
逐元素OR运算符 (NumPy ufunc) See note LOGICOPS |
|
|
按位AND运算符 (Python native 和 NumPy ufunc) |
|
|
按位OR运算符 (Python native 和 NumPy ufunc) |
|
|
二维方阵 |
|
|
二维数组 |
|
|
二维数组 |
|
如果 |
求解 a x = b 中的 x |
|
求解 |
求解 x a = b 中的 x |
|
|
|
|
|
二维数组的 Cholesky 分解 |
|
|
|
|
|
|
|
|
找到二维数组 |
|
|
QR分解 |
|
|
具有部分旋转的LU分解(注意:P(MATLAB) == transpose(P(NumPy))) |
|
|
共轭梯度求解器 |
|
|
|
|
|
|
|
|
对二维数组 |
|
|
对二维数组 |
|
|
保存数组 |
|
|
执行 \(\mathbf{Zx}=\mathbf{y}\) 形式的线性回归 |
|
|
使用低通滤波进行降采样 |
|
|
数组 |
|
|
移除数组 |
注释#
子矩阵:可以使用索引列表将值赋给子矩阵.例如,对于 2D 数组 a ,可以这样做: ind=[1, 3]; a[np.ix_(ind, ind)] += 100 .
HELP: 没有与 MATLAB 的 which 命令直接对应的命令,但是 help 命令通常会列出函数所在的文件名.Python 还有一个 inspect 模块(执行 import inspect ),它提供了一个通常有效的 getfile .
INDEXING:MATLAB 使用从 1 开始的索引,因此序列的初始元素的索引为 1.Python 使用从 0 开始的索引,因此序列的初始元素的索引为 0.由于每种方式都有优点和缺点,因此会引起混淆和争论.从 1 开始的索引与常用的人类语言用法一致,即序列的“第一个”元素的索引为 1.从 0 开始的索引 simplifies indexing .另请参阅 a text by prof.dr. Edsger W. Dijkstra .
RANGES:在 MATLAB 中, 0:5 既可以用作范围文字,也可以用作“切片”索引(在括号内);但是,在 Python 中,诸如 0:5 之类的构造只能用作切片索引(在方括号内).因此,创建了有点古怪的 r_ 对象,以使 NumPy 具有类似简洁的范围构造机制.请注意, r_ 不像函数或构造函数那样被调用,而是使用方括号进行索引,这允许在参数中使用 Python 的切片语法.
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 < 2) .缺乏 NumPy 运算符形式的 logical_and 和 logical_or 是 Python 设计的一个不幸后果.
RESHAPE 和线性索引:MATLAB 始终允许使用标量或线性索引访问多维数组,NumPy 则不然.线性索引在 MATLAB 程序中很常见,例如,矩阵上的 find() 返回它们,而 NumPy 的 find 表现不同.在转换 MATLAB 代码时,可能需要首先将矩阵重塑为线性序列,执行一些索引操作,然后再重塑回来.由于 reshape(通常)产生对同一存储的视图,因此应该可以相对有效地执行此操作.请注意,NumPy 中 reshape 使用的扫描顺序默认为“C”顺序,而 MATLAB 使用 Fortran 顺序.如果您只是转换为线性序列然后再转换回来,这无关紧要.但是,如果您要从 MATLAB 代码转换依赖于扫描顺序的 reshapes,那么此 MATLAB 代码: z = reshape(x,3,4); 在 NumPy 中应变为 z = x.reshape(3,4,order='F').copy() .
‘array’ 还是 ‘matrix’?我应该使用哪个?#
从历史上看,NumPy 提供了一种特殊的矩阵类型 np.matrix ,它是 ndarray 的一个子类,它使二元运算成为线性代数运算.您可能会在一些现有代码中看到它,而不是 np.array .那么,应该使用哪一个呢?
简短回答#
使用数组.
它们支持 MATLAB 中支持的多维数组代数
它们是 NumPy 的标准向量/矩阵/张量类型.许多 NumPy 函数返回数组,而不是矩阵.
逐元素操作和线性代数操作之间有明显的区别.
如果您愿意,您可以拥有标准向量或行/列向量.
在 Python 3.5 之前,使用数组类型的唯一缺点是您必须使用 dot 而不是 * 来乘(约简)两个张量(标量积,矩阵向量乘法等).从 Python 3.5 开始,您可以使用矩阵乘法 @ 运算符.
鉴于以上所述,我们打算最终弃用 matrix .
长篇回答#
NumPy 包含一个 array 类和一个 matrix 类. array 类旨在成为用于多种数值计算的通用 n 维数组,而 matrix 旨在专门促进线性代数计算.实际上,两者之间只有少数几个关键差异.
运算符
*和@,函数dot()和multiply():对于
array,**表示逐元素乘法,而 *@表示矩阵乘法;它们具有相关的函数multiply()和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:)逐元素乘法很容易:AB.:(您必须记住,矩阵乘法有自己的运算符@.:)您可以将一维数组视为行向量或列向量.A @ v将v视为列向量,而v @ A将v视为行向量. 这样可以省去您键入大量转置的时间.:)array是 NumPy 的“默认”类型,因此它获得了最多的测试,并且是最有可能被使用 NumPy 的第三方代码返回的类型.:)非常擅长处理任意数量维度的数据.:)如果您熟悉张量代数,则在语义上更接近张量代数.:)所有操作(*,/,+,-等)都是逐元素的.:(来自scipy.sparse的稀疏矩阵与数组的交互效果不佳.
matrix:\\行为更像 MATLAB 矩阵.<:(最多二维. 要保存三维数据,您需要array或许是matrix的 Python 列表.<:(至少二维. 您不能有向量. 它们必须强制转换为单列或单行矩阵.<:(由于array是 NumPy 中的默认值,因此即使您给它们一个matrix作为参数,某些函数也可能会返回一个array. NumPy 函数不应发生这种情况(如果确实发生了,那就是一个错误),但是基于 NumPy 的第三方代码可能不会像 NumPy 那样遵守类型保留.:)AB是矩阵乘法,因此它看起来就像您在线性代数中编写的那样(对于 Python >= 3.5,普通数组使用@运算符具有相同的便利性).<:(逐元素乘法需要调用函数multiply(A,B).<:(运算符重载的使用有点不合逻辑:*不起逐元素作用,但/起.与
scipy.sparse的交互更加简洁.
因此,更建议使用 array . 实际上,我们打算最终弃用 matrix .
自定义您的环境#
在 MATLAB 中,用于自定义环境的主要工具是使用您喜欢的函数的位置修改搜索路径. 您可以将此类自定义项放入 MATLAB 启动时将运行的启动脚本中.
NumPy,或者更确切地说是 Python,具有类似的功能.
要修改您的 Python 搜索路径以包含您自己的模块的位置,请定义
PYTHONPATH环境变量.要使特定的脚本文件在交互式 Python 解释器启动时执行,请定义
PYTHONSTARTUP环境变量以包含您的启动脚本的名称.
与 MATLAB 不同,在 MATLAB 中可以立即调用路径上的任何内容,而在 Python 中,您需要先执行“import”语句,才能访问特定文件中的函数.
例如,您可以制作一个如下所示的启动脚本(注意:这只是一个示例,而不是“最佳实践”的声明):
# Make all numpy available via shorter 'np' prefix
import numpy as np
#
# Make the SciPy linear algebra functions available as linalg.func()
# e.g. linalg.lu, linalg.eig (for general l*B@u==A@u solution)
from scipy import linalg
#
# Define a Hermitian function
def hermitian(A, **kwargs):
return np.conj(A,**kwargs).T
# Make a shortcut for hermitian:
# hermitian(A) --> H(A)
H = hermitian
要使用已弃用的 matrix 和其他 matlib 函数:
# 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 matrix,rand,zeros,ones,empty,eye
链接#
另一个有些过时的 MATLAB/NumPy 交叉引用可以在 https://mathesaurus.sf.net/ 找到.
可以在 topical software page 中找到用于 Python 进行科学工作的大量工具列表.
请参阅 List of Python software: scripting ,以获取使用 Python 作为脚本语言的软件列表
MATLAB® 和 SimuLink® 是 The MathWorks, Inc. 的注册商标.