matlab代码转python_matlab程序转为Python代码遇到的坑

随着Pytorch、TensorFlow等机器学习框架的兴起,很多实例都是基于Python实现的。而我自己专业内的程序都是基于MATLAB实现的,所以要结合网上的机器学习代码就有些不方便了,因此就萌生了将MATLAB代码转为Python代码的想法。

最近将MATLAB程序转为Python程序时,遇到了一些坑,在这里列举说明一下,以免再次入坑。这里主要涉及的是对矩阵的操作。Python中用到的主要是numpy库,这里只考虑使用np.array生成数组,不考虑matrix。使用linsapce生成矩阵

MATLAB:

linspace(1,12,12)

结果:

1 2 3 4 5 6 7 8 9 10 11 12

numpy:

import numpy as np

print(np.linspace(1, 12, 12))

结果:

[ 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12.]

2. 生成等间距递增矩阵(生成1,2,3,4,5,6,7,8)

matlab:

1:1:8

结果

1 2 3 4 5 6 7 8

numpy:

print(np.arange(1, 9, 1)) #注意这里是9,而不是8

结果

[1 2 3 4 5 6 7 8]

3. 生成一个3×3的全零矩阵或全1矩阵

matlab

ones(3,3) %全1矩阵

结果

1 1 1

1 1 1

1 1 1

numpy

print(np.ones((3,3)))

结果

[[1. 1. 1.]

[1. 1. 1.]

[1. 1. 1.]]

坑:

print(np.ones(3,3))

报错

TypeError: data type not understood

注意一定要加括号

4. 拼接矩阵

在MATLAB中拼接矩阵是很容易的。

[A B] %矩阵A和矩阵B左右拼接

[A;B] %矩阵A和矩阵B上下拼接

在numpy中可以使用np.concatenate((A,B),axis=1) 水平拼接两个矩阵,axis=0时垂直拼接矩阵。 也可以使用np.vstack((A,B)) 垂直拼接两个矩阵。

import numpy as np

A = np.ones((2,2))

B = np.zeros((2,2))

C = np.concatenate((A, B), axis=1)

D = np.concatenate((A, B), axis=0)

E = np.vstack((A,B))

print(C)

print(D)

print(E)

结果

[[1. 1. 0. 0.]

[1. 1. 0. 0.]]

[[1. 1.]

[1. 1.]

[0. 0.]

[0. 0.]]

[[1. 1.]

[1. 1.]

[0. 0.]

[0. 0.]]

5. 矩阵的乘法

在MATLAB中:A*B 表示两矩阵相乘,两个矩阵的维度必须满足相乘的条件

A.*B 表示矩阵对应元素相乘

a=[1 2;3 4]

b=[4 5;6 7]

a*b

a.*b

结果

a =

1 2

3 4

b =

4 5

6 7

a*b

16 19

36 43

a.*b

4 10

18 28

在numpy中: A * B 表示矩阵对应元素相乘

np.dot(A, B) 表示矩阵相乘

import numpy as np

A = np.array(([1,2],[3,4]))

B = np.array(([4,5],[6,7]))

C = A * B

D = np.dot(A, B)

print(A)

print(B)

print(C)

print(D)

结果

[[1 2]

[3 4]]

[[4 5]

[6 7]]

[[ 4 10]

[18 28]]

[[16 19]

[36 43]]

6. 矩阵的转置

在MATLAB中 A.’ 表示A的转置,A’表示共轭转置,如果元素中有复数,虚部会变号。

>> A=[1+1j 2+2j;3+3j 4+4j]

A =

1.0000 + 1.0000i 2.0000 + 2.0000i

3.0000 + 3.0000i 4.0000 + 4.0000i

>> A.'

ans =

1.0000 + 1.0000i 3.0000 + 3.0000i

2.0000 + 2.0000i 4.0000 + 4.0000i

>> A'

ans =

1.0000 - 1.0000i 3.0000 - 3.0000i

2.0000 - 2.0000i 4.0000 - 4.0000i

在numpy中,np.transpose(A) 相当于MATLAB中的A.’

import numpy as np

A = np.array(([1+1j,2+2j],[3+3j,4+4j]))

print(A)

print(np.transpose(A))

结果

[[1.+1.j 2.+2.j]

[3.+3.j 4.+4.j]]

[[1.+1.j 3.+3.j]

[2.+2.j 4.+4.j]]

在numpy中,共轭矩阵可以使用A.conjugate() 计算

import numpy as np

A = np.array(([1+1j,2+2j],[3+3j,4+4j]))

print(A)

print(A.conjugate())

结果

[[1.+1.j 2.+2.j]

[3.+3.j 4.+4.j]]

[[1.-1.j 2.-2.j]

[3.-3.j 4.-4.j]]

7. 复数类型的声明

在numpy中,如果不声明变量是复数类型的,很可能会导致计算结果出现nan。

import numpy as np

a = -1

print(np.sqrt(a))

结果

RuntimeWarning: invalid value encountered in sqrt

print(np.sqrt(a))

nan

解决办法:定义变量时声明为复数类型

import numpy as np

a = np.array(-1, dtype = complex)

print(np.sqrt(a))

结果

1j

坑:如果一次计算中涉及多个复数变量,最好将这些变量都设置为复数类型,以免出错。

生成全1或全0矩阵也要声明为复数类型。

np.zeros((1, N),dtype = complex)

否则可能会出现以下警告:

RuntimeWarning: invalid value encountered in...

ComplexWarning: Casting complex values to real discards the imaginary part

8. 求矩阵的特征值

MATLAB:[V, D] = eig(A) 其中矩阵A的全部特征值构成对角矩阵D,而A的特征向量构成列向量V。

>> a=[1 2;3 4]

a =

1 2

3 4

>> [V, D]=eig(a)

V =

-0.8246 -0.4160

0.5658 -0.9094

D =

-0.3723 0

0 5.3723

Numpy:VV, DD = np.linalg.eig(A) 其中VV是特征值,DD是特征向量。

import numpy as np

a = np.array(([1,2],[3,4]))

VV, DD = np.linalg.eig(a)

print(VV)

print(DD)

结果

[-0.37228132 5.37228132]

[[-0.82456484 -0.41597356]

[ 0.56576746 -0.90937671]]

坑:有两点不同:1.MATLAB和numpy返回特征值和特征向量的顺序是反的;2.MATLAB返回的特征值是对角矩阵形式,而numpy返回的特征值是一个数组。

9. 求逆矩阵

MATLAB: inv(A)

A=[1 2;3 4]

A =

1 2

3 4

>> inv(A)

ans =

-2.0000 1.0000

1.5000 -0.5000

numpy : np.linalg.inv(A)

import numpy as np

a = np.array(([1,2],[3,4]))

print(np.linalg.inv(a))

结果

[[-2. 1. ]

[ 1.5 -0.5]]

10. 矩阵的除法

计算矩阵的除法MATLAB有两种方式。

MATLAB 1: A\B 表示矩阵B除矩阵A

MATLAB 2:inv(A) * B 矩阵B除矩阵A,可以表示为A的逆矩阵乘矩阵B

A =

1 2

3 4

>> B=[2 3;4 5]

B =

2 3

4 5

>> A\B

ans =

0 -1

1 2

>> inv(A)*B

ans =

0 -1.0000

1.0000 2.0000

Numpy:np.dot(np.linalg.inv(A), B)

import numpy as np

A = np.array(([1,2],[3,4]))

B = np.array(([2,3],[4,5]))

print(np.dot(np.linalg.inv(A), B))

结果

[[ 4.4408921e-16 -1.0000000e+00]

[ 1.0000000e+00 2.0000000e+00]]

11. 矩阵连乘

MATLAB: A*B*C 表示三个矩阵A、B、C连乘

A =

1 2

3 4

>> B

B =

2 3

4 5

>> C=[3 4;5 6]

C =

3 4

5 6

>> A*B*C

ans =

95 118

211 262

numpy:np.dot(A,B,C)是错误的,实际上只计算了矩阵A乘矩阵B

import numpy as np

A = np.array(([1,2],[3,4]))

B = np.array(([2,3],[4,5]))

C = np.array(([3,4],[5,6]))

print(np.dot(A,B))

print(np.dot(A,B,C))

结果

[[10 13]

[22 29]]

[[10 13]

[22 29]]

对于numpy中三个矩阵的连乘,可以先计算前两个矩阵的乘积,再与第三个矩阵相乘。

import numpy as np

A = np.array(([1,2],[3,4]))

B = np.array(([2,3],[4,5]))

C = np.array(([3,4],[5,6]))

print(np.dot(np.dot(A,B), C))

结果

[[ 95 118]

[211 262]]

很显然,这种方法有缺陷,对于更多数量的矩阵连乘时比较麻烦。

12. 对角矩阵

MATLAB: diag(A) 将一维数组A变成对角矩阵

>> A=1:1:4

A =

1 2 3 4

>> diag(A)

ans =

1 0 0 0

0 2 0 0

0 0 3 0

0 0 0 4

numpy: np.diag() 。 需要注意数组的维度

import numpy as np

a = np.arange(1,5,1)

b = np.ones((1,3))

print(np.diag(a))

print(np.diag(b)) #这时并没有生成对角矩阵

print(np.diag(b[0, :]))

结果

[[1 0 0 0]

[0 2 0 0]

[0 0 3 0]

[0 0 0 4]]

[1.]

[[1. 0. 0.]

[0. 1. 0.]

[0. 0. 1.]]

13. 矩阵赋值

这里用Python很容易出错,一定要特别注意。

在MATLAB中使用‘=’赋值,变量之间并没有联系。

>> a=ones(2,2)

a =

1 1

1 1

>> b=a

b =

1 1

1 1

>> a(1,2)=0;

>> a

a =

1 0

1 1

>> b

b =

1 1

1 1

而在Python中,使用“=”并非仅仅是将变量a的值赋值给变量b。一旦使用“a=b”,就表示今后,a就是b,b就是a。改变a,b也跟着改变;改变b,a也跟着改变。

import numpy as np

a = np.ones((2,2))

b = a

a[0, 1] = 0

print(a)

print(b)

结果:改变变量a, b也跟着改变了。

[[1. 0.]

[1. 1.]]

[[1. 0.]

[1. 1.]]

同样,改变变量b,a也会跟着改变

import numpy as np

a = np.ones((2,2))

b = a

b[0, 1] = 0

print(a)

print(b)

结果

[[1. 0.]

[1. 1.]]

[[1. 0.]

[1. 1.]]

解决:1.使用.copy() 或避免直接赋值

import numpy as np

a = np.ones((2,2))

b = a

c = a.copy()

a[0, 1] = 0

print(a)

print(b)

print(c)

结果

[[1. 0.]

[1. 1.]]

[[1. 0.]

[1. 1.]]

[[1. 1.]

[1. 1.]]

2.通过*1避免直接赋值

未×1

import numpy as np

a = np.arange(0,20,1)

b = a[15:20]

b[ 3:] = 0 #改变b时,a也跟着改变了

c = a[10:]

print(a)

print(b)

print(c)

结果

[ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 0 0]

[15 16 17 0 0]

[10 11 12 13 14 15 16 17 0 0]

通过×1避免

import numpy as np

a = np.arange(0,20,1)

b = a[15:20] * 1

b[ 3:] = 0

c = a[10:]

print(a)

print(b)

print(c)

结果

[ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19]

[15 16 17 0 0]

[10 11 12 13 14 15 16 17 18 19]

附:numpy中需要特别注意的事情

1 数组的维度

MATLAB中没有一维数组,即使是一行数字也会认为行的大小是1,但numpy中却不一样,看下面这个例子

import numpy as np

a = np.array([[1,2,3],[4,5,6]])

b = a[:,0:1] #注意b和c的区别

c = a[:,0]

print(a)

print(a.shape)

print(b)

print(b.shape)

print(c)

print(c.shape)

结果

[[1 2 3]

[4 5 6]]

(2, 3)

[[1]

[4]]

(2, 1)

[1 4]

(2,)

可以看到b和c的维度是不一样的,b是二维的,而c是一维的。因为没有注意到这点,所以我在使用TensorFlow2.1建立网络时遇到了下面的错误。很显然,就是b和c的区别。

ValueError: Input 0 of layer dense is incompatible with the layer: : expected min_ndim=2, found ndim=1. Full shape received: [None]

总结:目前从MATLAB转到numpy遇到的问题就这些,以后还会补充,欢迎评论学习交流!

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值