{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# 从 Matlab 到 Numpy" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##Numpy 和 Matlab 比较" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**`Numpy`** 和 **`Matlab`** 有很多相似的地方,但 **`Numpy`** 并非 **`Matlab`** 的克隆,它们之间存在很多差异,例如:\n", "\n", "`MATLAB®`|`Numpy`\n", "---|---\n", "基本类型为双精度浮点数组,以二维矩阵为主 | 基本类型为 `ndarray`,有特殊的 `matrix` 类\n", "1-based 索引 | 0-based 索引\n", "脚本主要用于线性代数计算 | 可以使用其他的 **Python** 特性 \n", "采用值传递的方式进行计算
切片返回复制 | 采用引用传递的方式进行计算
切片返回引用\n", "文件名必须和函数名相同 | 函数可以在任何地方任何文件中定义\n", "收费 | 免费\n", "2D,3D图像支持 | 依赖第三方库如 `matplotlib` 等\n", "完全的编译环境 | 依赖于 **Python** 提供的编译环境" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## array 还是 matrix?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`Numpy` 中不仅提供了 `array` 这个基本类型,还提供了支持矩阵操作的类 `matrix`,但是一般推荐使用 `array`:\n", "\n", "- 很多 `numpy` 函数返回的是 `array`,不是 `matrix`\n", "- 在 `array` 中,逐元素操作和矩阵操作有着明显的不同\n", "- 向量可以不被视为矩阵\n", "\n", "具体说来:\n", "\n", "- `*, dot(), multiply()`\n", " - `array`:`*` -逐元素乘法,`dot()` -矩阵乘法\n", " - `matrix`:`*` -矩阵乘法,`multiply()` -逐元素乘法\n", "- 处理向量 \n", " - `array`:形状为 `1xN, Nx1, N` 的向量的意义是不同的,类似于 `A[:,1]` 的操作返回的是一维数组,形状为 `N`,一维数组的转置仍是自己本身\n", " - `matrix`:形状为 `1xN, Nx1`,`A[:,1]` 返回的是二维 `Nx1` 矩阵\n", "- 高维数组\n", " - `array`:支持大于2的维度\n", " - `matrix`:维度只能为2\n", "- 属性\n", " - `array`:`.T` 表示转置\n", " - `matrix`:`.H` 表示复共轭转置,`.I` 表示逆,`.A` 表示转化为 `array` 类型\n", "- 构造函数\n", " - `array`:`array` 函数接受一个(嵌套)序列作为参数——`array([[1,2,3],[4,5,6]])`\n", " - `matrix`:`matrix` 函数额外支持字符串参数——`matrix(\"[1 2 3; 4 5 6]\")`\n", "\n", "其优缺点各自如下:\n", "\n", "- **`array`**\n", " - `[GOOD]` 一维数组既可以看成列向量,也可以看成行向量。`v` 在 `dot(A,v)` 被看成列向量,在 `dot(v,A)` 中被看成行向量,这样省去了转置的麻烦\n", " - `[BAD!]` 矩阵乘法需要使用 `dot()` 函数,如: `dot(dot(A,B),C)` vs `A*B*C`\n", " - `[GOOD]` 逐元素乘法很简单: `A*B`\n", " - `[GOOD]` 作为基本类型,是很多基于 `numpy` 的第三方库函数的返回类型\n", " - `[GOOD]` 所有的操作 `*,/,+,**,...` 都是逐元素的\n", " - `[GOOD]` 可以处理任意维度的数据\n", " - `[GOOD]` 张量运算\n", "\n", "- **`matrix`**\n", " - `[GOOD]` 类似与 **`MATLAB`** 的操作\n", " - `[BAD!]` 最高维度为2\n", " - `[BAD!]` 最低维度也为2\n", " - `[BAD!]` 很多函数返回的是 `array`,即使传入的参数是 `matrix`\n", " - `[GOOD]` `A*B` 是矩阵乘法\n", " - `[BAD!]` 逐元素乘法需要调用 `multiply` 函数\n", " - `[BAD!]` `/` 是逐元素操作\n", "\n", "当然在实际使用中,二者的使用取决于具体情况。\n", "\n", "二者可以互相转化:\n", "\n", "- `asarray` :返回数组\n", "- `asmatrix`(或者`mat`) :返回矩阵\n", "- `asanyarray` :返回数组或者数组的子类,注意到矩阵是数组的一个子类,所以输入是矩阵的时候返回的也是矩阵" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 类 Matlab 函数" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "有很多类似的函数:\n", "\n", "- `ones, zeros, empty, eye, rand, repmat`\n", "\n", "通常这些函数的返回值是 `array`,不过 `numpy` 提供了一个 `matlib` 的子模块,子模块中的这些函数返回值为 `matrix`:" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": true }, "outputs": [], "source": [ "import numpy\n", "import numpy.matlib" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(7L,)\n", "\n" ] } ], "source": [ "a = numpy.ones(7)\n", "\n", "print a.shape\n", "print type(a)" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(1L, 7L)\n", "\n" ] } ], "source": [ "a = numpy.matlib.ones(7)\n", "\n", "print a.shape\n", "print type(a)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`mat` 函数将一个数组转化为矩阵:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n" ] } ], "source": [ "a = numpy.array([1,2,3])\n", "\n", "b = numpy.mat(a)\n", "\n", "print type(b)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "有些函数被放到子模块中了,例如调用 `rand()` 函数需要使用 `numpy.random.rand()` (或者从 `matlib` 模块中生成矩阵):" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[ 0.66007267 0.34794294 0.5040946 0.65044648 0.74763248 0.42486999\n", " 0.90922612 0.69071747 0.33541076 0.08570178]\n" ] } ], "source": [ "a = numpy.random.rand(10)\n", "print a" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 等效操作" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "假定我们已经这样导入了 `Numpy`:" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": true }, "outputs": [], "source": [ "from numpy import *\n", "import scipy.linalg" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "以下 `linalg` 表示的是 `numpy.linalg`,与 `scipy.linalg` 不同。\n", "\n", "注意:**`MATLAB`** 与 **`Numpy`** 下标之间有这样几处不同:\n", "- `1-base` vs `0-base`\n", "- `()` vs `[]`\n", "- `MATLAB`:`beg(:step):end`,包含结束值 `end`\n", "- `Numpy`:`beg:end(:step)`,不包含结束值 `end`\n", "\n", "MATLAB|Numpy|注释\n", "---|---|---\n", "`help func` | `info(func)`, `help(func)`, `func?`(IPython)| 查看函数帮助\n", "`which func` | | 查看函数在什么地方定义\n", "`type func` | `source(func)`, `func??`(IPython)| 查看函数源代码\n", "`a && b` | `a and b` | 逻辑 `AND`\n", "`1*i, 1*j, 1i, 1j` | `1j` | 复数\n", "`eps` | `spacing(1)` | `1` 与最近浮点数的距离\n", "`ndims(a)` | `ndim(a), a.ndim` | `a` 的维数\n", "`numel(a)` | `size(a), a.size` | `a` 的元素个数\n", "`size(a)` | `shape(a), a.shape` | `a` 的形状\n", "`size(a,n)` | `a.shape[n-1]` | 第 n 维的大小\n", "`a(2,5)` | `a[1,4]` | 第 2 行第 5 列元素\n", "`a(2,:)` | `a[1], a[1,:]` | 第 2 行 \n", "`a(1:5,:)` | `a[0:5]` | 第 1 至 5 行\n", "`a(end-4:end,:)` | `a[-5:]` | 后 5 行\n", "`a(1:3,5:9)` | `a[0:3][:,4:9]` | 特定行列(1~3 行,5~9 列)\n", "`a([2,4,5],[1,3])` | `a[ix_([1,3,4],[0,2])]` | 特定行列(2,4,5 行的 1,3 列)\n", "`a(3:2:21,:)` | `a[2:21:2,:]` | 特定行列(3,5,...,21 行)\n", "`a(1:2:end,:)` | `a[ ::2,:]` | 奇数行\n", "`a([1:end 1],:)` | `a[r_[:len(a),0]]` | 将第一行添加到末尾\n", "`a.'` | `a.T` | 转置\n", "`a ./ b` | `a/b` | 逐元素除法\n", "`(a>0.5)` | `(a>0.5)` | 各个元素是否大于 0.5\n", "`find(a>0.5)` | `nonzero(a>0.5)` | 大于 0.5 的位置\n", "`a(a<0.5)=0` | `a[a<0.5]=0` | 小于 0.5 的设为 0\n", "`a(:) = 3` | `a[:] = 3` | 所有元素设为 3\n", "`y=x` | `y=x.copy()` | 将 y 设为 x\n", "`y=x(2,:)` | `y=x[1,:].copy()` | 注意值传递和引用传递的区别\n", "`y=x(:)` | `y=x.flatten(1)` | 将矩阵变为一个向量,这里 `1` 表示沿着列进行转化\n", "`max(max(a))` | `a.max()` | 最大值\n", "`max(a)` | `a.max(0)` | 每一列的最大值\n", "`max(a,[],2)` | `a.max(1)` | 每一行的最大值\n", "`max(a,b)` | `maximum(a,b)` | 逐元素比较,取较大的值\n", "`a & b` | `logical_and(a, b)` | 逻辑 AND\n", "`bitand(a, b)` | `a & b` | 逐比特 AND\n", "`inv(a)` | `linalg.inv(a)` | a 的逆\n", "`pinv(a)` | `linalg.inv(a)` | 伪逆\n", "`rank(a)` | `linalg.matrix_rank(a)` | 秩\n", "`a\\b` | `linalg.solve(a,b)(如果a是方阵),linalg.lstsq(a,b)` | 解 `a x = b`\n", "`b/a` | 求解 `a.T x.T = b.T` | 解 `x a = b`\n", "`[U,S,V]=svd(a)` | `U, S, Vh = linalg.svd(a), V = Vh.T` | 奇异值分解\n", "`chol(a)` | `linalg.cholesky(a).T` | Cholesky 分解\n", "`[V,D]=eig(a)` | `D,V = linalg.eig(a)` | 特征值分解\n", "`[V,D]=eig(a,b)` | `V,D = scipy.linalg.eig(a,b)` | \n", "`[V,D]=eigs(a,k)` | | 前 k 大特征值对应的特征向量\n", "`` | `` |\n", "`` | `` |\n", "`` | `` |\n", "`` | `` |\n", "\n", "MATLAB|numpy.array|numpy.matrix|注释\n", "---|---|---|---\n", "`[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` 矩阵\n", "`[a b;c d]` | `vstack([hstack([a,b]), hsatck([c,d])]])` | `bmat('a b;c d')` | 分块矩阵构造\n", "`a(end)` | `a[-1]` | `a[:,-1][0,0]` | 最后一个元素\n", "`a'` | `a.conj().T` | `a.H` | 复共轭转置\n", "`a * b` | `dot(a,b)` | `a * b` | 矩阵乘法\n", "`a .* b` | `a * b` | `multiply(a,b)` | 逐元素乘法\n", "`a.^3` | `a**3` | `power(a,3)` | 逐元素立方\n", "`a(:,find(v>0.5))` | `a[:,nonzero(v>0.5)[0]]` | `a[:,nonzero(v.A>0.5)[0]]` | 找出行向量 `v>0.5` 对应的 `a` 中的列\n", "`a(:,find(v>0.5))` | `a[:,v.T>0.5]` | `a[:,v.T>0.5)]` | 找出列向量 `v>0.5` 对应的 `a` 中的列\n", "`a .* (a>0.5)` | `a * (a>0.5)` | `mat(a.A * (a>0.5).A)` | 将所有小于 0.5 的元素设为 0\n", "`1:10` | `arange(1.,11.), r_[1.:11.], r_[1:10:10j]` | `mat(arange(1.,11.)), r_[1.:11., 'r']` | 这里 `1.` 是为了将其转化为浮点数组\n", "`0:9` | `arange(10.), r_[:10.], r_[:9:10j]` | `mat(arange(10.)), r_[:10., 'r']` | \n", "`[1:10]'` | `arange(1.,11.)[:,newaxis]` | `r_[1.:11.,'c']` | 列向量\n", "`zeros, ones, eye, diag, linspace` | `zeros, ones, eye, diag, linspace` | `mat(...)` |\n", "`rand(3,4)` | `random.rand(3,4)` | `mat(...)` | 0~1 随机数\n", "`[x,y]=meshgrid(0:8,0:5)` | `mgrid[0:9., 0:6.], meshgrid(r_[0:9.],r_[0:6.])` | `mat(...)` | 网格\n", "| `ogrid[0:9.,0:6.], ix_(r_[0:9.],r_[0:6.])` | `mat()` | 建议在 `Numpy` 中使用\n", "`[x,y]=meshgrid([1,2,4],[2,4,5])`|`meshgrid([1,2,4],[2,4,5])`|`mat(...)`|\n", "|`ix_([1,2,4],[2,4,5])`|`mat(...)`|\n", "`repmat(a, m, n)`|`tile(a, (m,n))`|`mat(...)`| 产生 `m x n` 个 `a`\n", "`[a b]` | `c_[a,b]`|`concatenate((a,b),1)`| 列对齐连接\n", "`[a; b]` | `r_[a,b]`|`concatenate((a,b))`| 行对齐连接\n", "`norm(v)` | `sqrt(dot(v,v)), linalg.norm(v)` | `sqrt(dot(v.A,v.A)), linalg.norm(v)` | 模\n", "`[Q,R,P]=qr(a,0)` | `Q,R = scipy.linalg.qr(a)` | `mat(...)` | QR 分解\n", "`[L,U,P]=lu(a)` | `L,U = Sci.linalg.lu(a)` | `mat(...)` | LU 分解\n", "`fft(a)` | `fft(a)` | `mat(...)` | FFT\n", "`ifft(a)` | `ifft(a)` | `mat(...)` | IFFT\n", "`sort(a)` | `sort(a),a.sort` | `mat(...)` | 排序\n", "\n", "参考:http://wiki.scipy.org/NumPy_for_Matlab_Users#whichNotes" ] } ], "metadata": { "kernelspec": { "display_name": "Python 2", "language": "python", "name": "python2" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 2 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython2", "version": "2.7.10" } }, "nbformat": 4, "nbformat_minor": 0 }