#!/usr/bin/env python
# coding: utf-8
# # 从 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)` vs `A*B*C`
# - `[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)
# In[3]:
a = numpy.matlib.ones(7)
print a.shape
print type(a)
# `mat` 函数将一个数组转化为矩阵:
# In[4]:
a = numpy.array([1,2,3])
b = numpy.mat(a)
print type(b)
# 有些函数被放到子模块中了,例如调用 `rand()` 函数需要使用 `numpy.random.rand()` (或者从 `matlib` 模块中生成矩阵):
# In[5]:
a = numpy.random.rand(10)
print a
# ## 等效操作
# 假定我们已经这样导入了 `Numpy`:
# In[6]:
from numpy import *
import scipy.linalg
# 以下 `linalg` 表示的是 `numpy.linalg`,与 `scipy.linalg` 不同。
#
# 注意:**`MATLAB`** 与 **`Numpy`** 下标之间有这样几处不同:
# - `1-base` vs `0-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`
# `1*i, 1*j, 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