Dustone
2021/5/12
本文为深度概率模型采样库pydpm中Topic model的matlab代码转Python代码时总结的细节及注意事项
宣传一下实验室的pydpm库:https://github.com/BoChenGroup/pydpm
函数替换m -> py
浮点数精度 eps -> np.spacing(1)
矩阵A*B -> np.dot(A,B)
A.*B -> A*B
randi(max,m,n) -> np.random.randint(max,size=(m,n))
A./sum(A,2) -> A/A.sum(axis=1,keepdims=1) # A为矩阵/ndarray
randg -> np.random.gamma
betarnd -> np.random.beta
x(find(x>0))=0 -> np.argwhere(x>t) 返回每个元素的索引
x[x>0]=0 x>0返回布尔值
np.where(a==1) 返回维数个array构成的tuple,array为元素的在某维下索引
max(array, realmin) -> np.maximum(array, realmin)
[row,col] = find(X, ...) -> col, row = np.where(X.T) matlab中一列一列地查找,Python中一行一行查找
reshape(X,m,n) -> X.reshape(m,n) 同find用法,matlab按列操作
repmat(x,m,n) -> np.tile(x,(m,n)) 复制数组m倍y轴,n倍x轴
np.repeat() 以element为最小单位进行复制
ones(size(a)) -> np.ones_like(a)
> np.ones(a.shape)
max(realmin, A) -> A[A
bsxfun(@rdivide,A,a) -> A/a A(n,m)ndarray a(n,1)
MEX Theta[k + Ksize*j] -> Theta[k, j] Theta(Ksize,N),MEX中按列索引
sparse(zs, ds, 1, k, N) -> sparse.csc_matrix((1*, zs, ds), shape=(P, N))
sparse(X) -> sparse.csc_matrix(X)
full(x) -> x.toarray() x: csc matrix
MEX,csc_matrix: mxGetPr mxGetIr mxGetJc -> .data(取值pr) .indices(行号lr) .indptr(列号jc)
csc_matrix((data, (row, col)), shape=(3, 3)) # row 行,col列, 按列存储 a[row_ind[k], col_ind[k]] = data[k]
不同
Matlab中函数的参数传递需要显式定义,而Python中面向对象编程,参数的传递可以通过属性
int/float/doubel的问题,matlab中double属性的整数可以作为索引,而Python中不可
numpy中(n,)和(n,1),(1,n)shape的array存在区别,a=np.ones(n),b=np.ones((n,1)),c=np.ones((1,n))。在matlab中就是(n,1)的形式,此类型变量一般可直接在Python中定义为(n,)的形式,因为很多函数输入(n,1)输出(n,)。在某些特殊运算中,如np.dot中可reshape一下。
matlab中(1,n)数组可索引到元素,py中需a[0][index]。所以变量一般可直接在Python中定义为(n,)的形式
matlab中sum(A,2)得到(m,1)结果,Python中np.sum(A,1)得到(m,) array
matlab中sparse可以直接索引,Python中需要toarray再索引
array的操作方法,如find,reshape
'~1' stand for logical 0(False) in matlab, but -2(按位取反运算符1) in python,逻辑判断一般采用if not flag
Python参数传递时是传递对象引用(传值和传址的混合方式),如果是数字,字符串,元组则传值;如果是列表,字典则传址。可通过copy.deepcopy()来传值;而matlab中是传值
in python, 'a is b' and 'a==b' is not equal. use 'a is b' to test if a&b share the same data in memery使用is查看两个变量名是否指向同一个地址
Debug-固定随机数调试
产生相同随机数方法:
rand('twister', 0)
rand(3,1) % matlab
np.random.seed(0)
np.random.rand(3,1) # python
通过
save data1 %in m
import scipy.io as sio
d = sio.loadmat('data1.mat') #in py. 反向使用savemat
将matlab工作区变量保存引入Python可对比变量是否相等(非int型可能会存在非常小的误差),d的嵌套比较多且形式会改变,可以通过reshape后进行对比
Debug-matlab和Python变量互传
%matlab 2 Python
save data1 %m
import scipy.io as sio # py
d = sio.loadmat('data1.mat') #py
#python 2 matlab
sio.savemat('python_phi.mat',{'phi':phi}) # py
phi=load('python_phi.mat').phi
matlab-混合编程mex
Matlab运算能力强大,但是太慢,而C语言速度极快。实际操作过程中可以通过mex混合编程把计算速度慢、涉及到大量循环的matlab代码转而用C来实现。
工作流程为:
编写执行核心计算任务的C语言函数代码
编写接口函数mexFunction
编译,matlab命令行 mex test.c
在matlab中调用
mexFunction可以看成是matlab与C的接口函数,matlab调用mexFunction来实现C语言的功能。mexFunction的定义如下:
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
其中nlhs为输出的个数(n of left-hand-side),plhs为输出的指针数组。nrhs为输入参数的个数,prhs为输入参数的指针数组。
需要注意的是,c中通过指针索引数组值时是按列索引的,即Theta[k + Ksize*j]在Python转化为Theta[k, j],其中Theta.shape=(Ksize,N)
并且,由于for循环计算速度较慢,而且有些无法改造为对ndarray的操作,导致运行速度较慢
Python-CUDA并行加速
由于matlab通过mex使用c语言进行大量循环计算,速度较快,而Python中有很多操作需要for循环,导致运行速度远慢于matlab,可通过CUDA编程来实现并行加速
2do
Else-tips
matlab稀疏矩阵