从 Matlab 到 Numpy
Numpy 和 Matlab 比较
Numpy
和 Matlab
有很多相似的地方,但 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, Nx1
,A[:,1]
返回的是二维Nx1
矩阵
- 高维数组
array
:支持大于2的维度matrix
:维度只能为2
- 属性
array
:.T
表示转置matrix
:.H
表示复共轭转置,.I
表示逆,.A
表示转化为array
类型
构造函数
array
:array
函数接受一个(嵌套)序列作为参数——array([[1,2,3],[4,5,6]])
matrix
:matrix
函数额外支持字符串参数——matrix("[1 2 3; 4 5 6]")
其优缺点各自如下:
array
[GOOD]
一维数组既可以看成列向量,也可以看成行向量。v
在dot(A,v)
被看成列向量,在dot(v,A)
中被看成行向量,这样省去了转置的麻烦[BAD!]
矩阵乘法需要使用dot()
函数,如:dot(dot(A,B),C)
vsABC
[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]:
- import numpy
- import numpy.matlib
In [2]:
- a = numpy.ones(7)
- print a.shape
- print type(a)
- (7L,)
- <type 'numpy.ndarray'>
In [3]:
- a = numpy.matlib.ones(7)
- print a.shape
- print type(a)
- (1L, 7L)
- <class 'numpy.matrixlib.defmatrix.matrix'>
mat
函数将一个数组转化为矩阵:
In [4]:
- a = numpy.array([1,2,3])
- b = numpy.mat(a)
- print type(b)
- <class 'numpy.matrixlib.defmatrix.matrix'>
有些函数被放到子模块中了,例如调用 rand()
函数需要使用 numpy.random.rand()
(或者从 matlib
模块中生成矩阵):
In [5]:
- a = numpy.random.rand(10)
- print a
- [ 0.66007267 0.34794294 0.5040946 0.65044648 0.74763248 0.42486999
- 0.90922612 0.69071747 0.33541076 0.08570178]
等效操作
假定我们已经这样导入了 Numpy
:
In [6]:
- from numpy import *
- import scipy.linalg
以下 linalg
表示的是 numpy.linalg
,与 scipy.linalg
不同。
注意:MATLAB
与 Numpy
下标之间有这样几处不同:
1-base
vs0-base
()
vs[]
MATLAB
:beg(:step):end
,包含结束值end
Numpy
:beg: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 n 个 a |
[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