NumPy的matrix类
跟其他面向矩阵运算和线性代数的语言相比(如MATLAB、GAUSS等),NumPy的线性代数语法往往比较繁琐。其中一个原因是,矩阵操作需要用到numpy.dot。再加上NumPy的索引语义也不同,所以有时不那么容易将代码移植到Python译注6。从二维数组中选取一行(比如X[1,:])或一列(如X[:,1])将会产生一个一维数组,而在MATLAB中则是二维数组。
- In [204]: X = np.array([[ 8.82768214, 3.82222409, -1.14276475, 2.04411587],
- ...: [ 3.82222409, 6.75272284, 0.83909108, 2.08293758],
- ...: [-1.14276475, 0.83909108, 5.01690521, 0.79573241],
- ...: [ 2.04411587, 2.08293758, 0.79573241, 6.24095859]])
- In [205]: X[:, 0] # 一维的
- Out[205]: array([ 8.8277, 3.8222, -1.1428, 2.0441])
- In [206]: y = X[:, :1] # 切片操作可产生二维结果
- In [207]: X
- Out[207]:
- array([[ 8.8277, 3.8222, -1.1428, 2.0441],
- [ 3.8222, 6.7527, 0.8391, 2.0829],
- [-1.1428, 0.8391, 5.0169, 0.7957],
- [ 2.0441, 2.0829, 0.7957, 6.241 ]])
- In [208]: y
- Out[208]:
- array([[ 8.8277],
- [ 3.8222],
- [-1.1428],
- [ 2.0441]])
在这个问题中,积yT×y会被表达成下面这个样子:
- In [209]: np.dot(y.T, np.dot(X, y))
- Out[209]: array([[ 1195.468]])
为了不用编写大量的矩阵运算代码,NumPy提供了一个matrix类,其索引行为更像MATLAB:单行或列会以二维形式返回,且使用星号(*)的乘法直接就是矩阵乘法。上面那些运算用numpy.matrix来编写的话,应该是下面这个样子:
- In [210]: Xm = np.matrix(X)
- In [211]: ym = Xm[:, 0]
- In [212]: Xm
- Out[212]:
- matrix([[ 8.8277, 3.8222, -1.1428, 2.0441],
- [ 3.8222, 6.7527, 0.8391, 2.0829],
- [-1.1428, 0.8391, 5.0169, 0.7957],
- [ 2.0441, 2.0829, 0.7957, 6.241 ]])
- In [213]: ym
- Out[213]:
- matrix([[ 8.8277],
- [ 3.8222],
- [-1.1428],
- [ 2.0441]])
- In [214]: ym.T * Xm * ym
- Out[214]: matrix([[ 1195.468]])
matrix还有一个特殊的属性I,其功能是返回矩阵的逆:
- In [215]: Xm.I * X
- Out[215]:
- matrix([[ 1., -0., -0., -0.],
- [ 0., 1., 0., 0.],
- [ 0., 0., 1., 0.],
- [ 0., 0., 0., 1.]])
我不建议用numpy.matrix替代正规的ndarray,因为它们的应用面较窄。对于个别带有大量线性代数运算的函数,可以将函数参数转换为matrix类型,然后在返回之前用np.asarray(不会复制任何数据)将其转换回正规的ndarray。
译注6:原文有歧义,根据上下文的意思,应该是说不容易把其他语言的代码移植过来。