从 Matlab 到 Numpy

Numpy 和 Matlab 比较

NumpyMatlab 有很多相似的地方,但 Numpy 并非 Matlab 的克隆,它们之间存在很多差异,例如:

MATLAB® Numpy
基本类型为双精度浮点数组,以二维矩阵为主 基本类型为 ndarray,有特殊的 matrix
1-based 索引 0-based 索引
脚本主要用于线性代数计算 可以使用其他的 Python 特性
采用值传递的方式进行计算切片返回复制 采用引用传递的方式进行计算切片返回引用
文件名必须和函数名相同 函数可以在任何地方任何文件中定义
收费 免费
2D,3D图像支持 依赖第三方库如 matplotlib
完全的编译环境 依赖于 Python 提供的编译环境

array 还是 matrix?

Numpy 中不仅提供了 array 这个基本类型,还提供了支持矩阵操作的类 matrix,但是一般推荐使用 array

  • 很多 numpy 函数返回的是 array,不是 matrix
  • array 中,逐元素操作和矩阵操作有着明显的不同
  • 向量可以不被视为矩阵 具体说来:

  • *, dot(), multiply()

    • array* -逐元素乘法,dot() -矩阵乘法
    • matrix* -矩阵乘法,multiply() -逐元素乘法
  • 处理向量
    • array:形状为 1xN, Nx1, N 的向量的意义是不同的,类似于 A[:,1] 的操作返回的是一维数组,形状为 N,一维数组的转置仍是自己本身
    • matrix:形状为 1xN, Nx1A[:,1] 返回的是二维 Nx1 矩阵
  • 高维数组
    • array:支持大于2的维度
    • matrix:维度只能为2
  • 属性
    • array.T 表示转置
    • matrix.H 表示复共轭转置,.I 表示逆,.A 表示转化为 array 类型
  • 构造函数

    • arrayarray 函数接受一个(嵌套)序列作为参数——array([[1,2,3],[4,5,6]])
    • matrixmatrix 函数额外支持字符串参数——matrix("[1 2 3; 4 5 6]") 其优缺点各自如下:
  • array

    • [GOOD] 一维数组既可以看成列向量,也可以看成行向量。vdot(A,v) 被看成列向量,在 dot(v,A) 中被看成行向量,这样省去了转置的麻烦
    • [BAD!] 矩阵乘法需要使用 dot() 函数,如: dot(dot(A,B),C) vs ABC
    • [GOOD] 逐元素乘法很简单: A*B
    • [GOOD] 作为基本类型,是很多基于 numpy 的第三方库函数的返回类型
    • [GOOD] 所有的操作 ,/,+,*,… 都是逐元素的
    • [GOOD] 可以处理任意维度的数据
    • [GOOD] 张量运算
  • matrix

    • [GOOD] 类似与 MATLAB 的操作
    • [BAD!] 最高维度为2
    • [BAD!] 最低维度也为2
    • [BAD!] 很多函数返回的是 array,即使传入的参数是 matrix
    • [GOOD] A*B 是矩阵乘法
    • [BAD!] 逐元素乘法需要调用 multiply 函数
    • [BAD!] / 是逐元素操作 当然在实际使用中,二者的使用取决于具体情况。

二者可以互相转化:

  • asarray :返回数组
  • asmatrix(或者mat) :返回矩阵
  • asanyarray :返回数组或者数组的子类,注意到矩阵是数组的一个子类,所以输入是矩阵的时候返回的也是矩阵

类 Matlab 函数

有很多类似的函数:

  • ones, zeros, empty, eye, rand, repmat 通常这些函数的返回值是 array,不过 numpy 提供了一个 matlib 的子模块,子模块中的这些函数返回值为 matrix

In [1]:

  1. import numpy
  2. import numpy.matlib

In [2]:

  1. a = numpy.ones(7)
  2.  
  3. print a.shape
  4. print type(a)
  1. (7L,)
  2. <type 'numpy.ndarray'>

In [3]:

  1. a = numpy.matlib.ones(7)
  2.  
  3. print a.shape
  4. print type(a)
  1. (1L, 7L)
  2. <class 'numpy.matrixlib.defmatrix.matrix'>

mat 函数将一个数组转化为矩阵:

In [4]:

  1. a = numpy.array([1,2,3])
  2.  
  3. b = numpy.mat(a)
  4.  
  5. print type(b)
  1. <class 'numpy.matrixlib.defmatrix.matrix'>

有些函数被放到子模块中了,例如调用 rand() 函数需要使用 numpy.random.rand() (或者从 matlib 模块中生成矩阵):

In [5]:

  1. a = numpy.random.rand(10)
  2. print a
  1. [ 0.66007267 0.34794294 0.5040946 0.65044648 0.74763248 0.42486999
  2. 0.90922612 0.69071747 0.33541076 0.08570178]

等效操作

假定我们已经这样导入了 Numpy

In [6]:

  1. from numpy import *
  2. import scipy.linalg

以下 linalg 表示的是 numpy.linalg,与 scipy.linalg 不同。

注意:MATLABNumpy 下标之间有这样几处不同:

  • 1-base vs 0-base
  • () vs []
  • MATLABbeg(:step):end,包含结束值 end
  • Numpybeg:end(:step),不包含结束值 end |MATLAB|Numpy|注释 |——- |help func|info(func)help(func)func?(IPython)|查看函数帮助 |which func||查看函数在什么地方定义 |type func|source(func)func??(IPython)|查看函数源代码 |a && b|a and b|逻辑 AND |1i, 1j, 1i, 1j|1j|复数 |eps|spacing(1)|1 与最近浮点数的距离 |ndims(a)|ndim(a), a.ndim|a 的维数 |numel(a)|size(a), a.size|a 的元素个数 |size(a)|shape(a), a.shape|a 的形状 |size(a,n)|a.shape[n-1]|第 n 维的大小 |a(2,5)|a[1,4]|第 2 行第 5 列元素 |a(2,:)|a[1], a[1,:]|第 2 行 |a(1:5,:)|a[0:5]|第 1 至 5 行 |a(end-4:end,:)|a[-5:]|后 5 行 |a(1:3,5:9)|a[0:3][:,4:9]|特定行列(1~3 行,5~9 列) |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,:]|特定行列(3,5,…,21 行) |a(1:2:end,:)|a[ ::2,:]|奇数行 |a([1:end 1],:)|a[r[:len(a),0]]|将第一行添加到末尾 |a.'|a.T|转置 |a ./ b|a/b|逐元素除法 |(a>0.5)|(a>0.5)|各个元素是否大于 0.5 |find(a>0.5)|nonzero(a>0.5)|大于 0.5 的位置 |a(a<0.5)=0|a[a<0.5]=0|小于 0.5 的设为 0 |a(:) = 3|a[:] = 3|所有元素设为 3 |y=x|y=x.copy()|将 y 设为 x |y=x(2,:)|y=x[1,:].copy()|注意值传递和引用传递的区别 |y=x(:)|y=x.flatten(1)|将矩阵变为一个向量,这里 1 表示沿着列进行转化 |max(max(a))|a.max()|最大值 |max(a)|a.max(0)|每一列的最大值 |max(a,[],2)|a.max(1)|每一行的最大值 |max(a,b)|maximum(a,b)|逐元素比较,取较大的值 |a & b|logical_and(a, b)|逻辑 AND |bitand(a, b)|a & b|逐比特 AND |inv(a)|linalg.inv(a)|a 的逆 |pinv(a)|linalg.inv(a)|伪逆 |rank(a)|linalg.matrix_rank(a)|秩 |a\b|linalg.solve(a,b)(如果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), V = Vh.T|奇异值分解 |chol(a)|linalg.cholesky(a).T|Cholesky 分解 |[V,D]=eig(a)|D,V = linalg.eig(a)|特征值分解 |[V,D]=eig(a,b)|V,D = scipy.linalg.eig(a,b)| |[V,D]=eigs(a,k)||前 k 大特征值对应的特征向量 ||| ||| ||| |||
MATLAB numpy.array numpy.matrix 注释
[1,2,3;4,5,6] array([[1.,2.,3.],[4.,5.,6.]]) mat([[1.,2.,3.],[4.,5.,6.]]), mat('1,2,3;4,5,6') 2x3 矩阵
[a b;c d] vstack([hstack([a,b]), hsatck([c,d])]]) bmat('a b;c d') 分块矩阵构造
a(end) a[-1] a[:,-1][0,0] 最后一个元素
a' a.conj().T a.H 复共轭转置
a * b dot(a,b) a * b 矩阵乘法
a .* b a * b multiply(a,b) 逐元素乘法
a.^3 a**3 power(a,3) 逐元素立方
a(:,find(v>0.5)) a[:,nonzero(v>0.5)[0]] a[:,nonzero(v.A>0.5)[0]] 找出行向量 v>0.5 对应的 a 中的列
a(:,find(v>0.5)) a[:,v.T>0.5] a[:,v.T>0.5)] 找出列向量 v>0.5 对应的 a 中的列
a .* (a>0.5) a * (a>0.5) mat(a.A * (a>0.5).A) 将所有小于 0.5 的元素设为 0
1:10 arange(1.,11.), r[1.:11.], r[1:10:10j] mat(arange(1.,11.)), r_[1.:11., 'r'] 这里 1. 是为了将其转化为浮点数组
0:9 arange(10.), r[:10.], r[:9:10j] mat(arange(10.)), r_[:10., 'r']
[1:10]' arange(1.,11.)[:,newaxis] r_[1.:11.,'c'] 列向量
zeros, ones, eye, diag, linspace zeros, ones, eye, diag, linspace mat(…)
rand(3,4) random.rand(3,4) mat(…) 0~1 随机数
[x,y]=meshgrid(0:8,0:5) mgrid[0:9., 0:6.], meshgrid(r[0:9.],r[0:6.]) mat(…) 网格
ogrid[0:9.,0:6.], ix(r[0:9.],r_[0:6.]) mat() 建议在 Numpy 中使用
[x,y]=meshgrid([1,2,4],[2,4,5]) meshgrid([1,2,4],[2,4,5]) mat(…)
ix_([1,2,4],[2,4,5]) mat(…)
repmat(a, m, n) tile(a, (m,n)) mat(…) 产生 m x na
[a b] c_[a,b] concatenate((a,b),1) 列对齐连接
[a; b] r_[a,b] concatenate((a,b)) 行对齐连接
norm(v) sqrt(dot(v,v)), linalg.norm(v) sqrt(dot(v.A,v.A)), linalg.norm(v)
[Q,R,P]=qr(a,0) Q,R = scipy.linalg.qr(a) mat(…) QR 分解
[L,U,P]=lu(a) L,U = Sci.linalg.lu(a) mat(…) LU 分解
fft(a) fft(a) mat(…) FFT
ifft(a) ifft(a) mat(…) IFFT
sort(a) sort(a),a.sort mat(…) 排序

参考:http://wiki.scipy.org/NumPy_for_Matlab_Users#whichNotes

原文: https://nbviewer.jupyter.org/github/lijin-THU/notes-python/blob/master/03-numpy/03.23-from-matlab-to-numpy.ipynb