NumPy的matrix类

跟其他面向矩阵运算和线性代数的语言相比(如MATLAB、GAUSS等),NumPy的线性代数语法往往比较繁琐。其中一个原因是,矩阵操作需要用到numpy.dot。再加上NumPy的索引语义也不同,所以有时不那么容易将代码移植到Python译注6。从二维数组中选取一行(比如X[1,:])或一列(如X[:,1])将会产生一个一维数组,而在MATLAB中则是二维数组。

  1. In [204]: X = np.array([[ 8.82768214, 3.82222409, -1.14276475, 2.04411587],
  2. ...: [ 3.82222409, 6.75272284, 0.83909108, 2.08293758],
  3. ...: [-1.14276475, 0.83909108, 5.01690521, 0.79573241],
  4. ...: [ 2.04411587, 2.08293758, 0.79573241, 6.24095859]])
  5.  
  6. In [205]: X[:, 0] # 一维的
  7. Out[205]: array([ 8.8277, 3.8222, -1.1428, 2.0441])
  8.  
  9. In [206]: y = X[:, :1] # 切片操作可产生二维结果
  10.  
  11. In [207]: X
  12. Out[207]:
  13. array([[ 8.8277, 3.8222, -1.1428, 2.0441],
  14. [ 3.8222, 6.7527, 0.8391, 2.0829],
  15. [-1.1428, 0.8391, 5.0169, 0.7957],
  16. [ 2.0441, 2.0829, 0.7957, 6.241 ]])
  17.  
  18. In [208]: y
  19. Out[208]:
  20. array([[ 8.8277],
  21. [ 3.8222],
  22. [-1.1428],
  23. [ 2.0441]])

在这个问题中,积yT×y会被表达成下面这个样子:

  1. In [209]: np.dot(y.T, np.dot(X, y))
  2. Out[209]: array([[ 1195.468]])

为了不用编写大量的矩阵运算代码,NumPy提供了一个matrix类,其索引行为更像MATLAB:单行或列会以二维形式返回,且使用星号(*)的乘法直接就是矩阵乘法。上面那些运算用numpy.matrix来编写的话,应该是下面这个样子:

  1. In [210]: Xm = np.matrix(X)
  2.  
  3. In [211]: ym = Xm[:, 0]
  4.  
  5. In [212]: Xm
  6. Out[212]:
  7. matrix([[ 8.8277, 3.8222, -1.1428, 2.0441],
  8. [ 3.8222, 6.7527, 0.8391, 2.0829],
  9. [-1.1428, 0.8391, 5.0169, 0.7957],
  10. [ 2.0441, 2.0829, 0.7957, 6.241 ]])
  11.  
  12. In [213]: ym
  13. Out[213]:
  14. matrix([[ 8.8277],
  15. [ 3.8222],
  16. [-1.1428],
  17. [ 2.0441]])
  18.  
  19. In [214]: ym.T * Xm * ym
  20. Out[214]: matrix([[ 1195.468]])

matrix还有一个特殊的属性I,其功能是返回矩阵的逆:

  1. In [215]: Xm.I * X
  2. Out[215]:
  3. matrix([[ 1., -0., -0., -0.],
  4. [ 0., 1., 0., 0.],
  5. [ 0., 0., 1., 0.],
  6. [ 0., 0., 0., 1.]])

我不建议用numpy.matrix替代正规的ndarray,因为它们的应用面较窄。对于个别带有大量线性代数运算的函数,可以将函数参数转换为matrix类型,然后在返回之前用np.asarray(不会复制任何数据)将其转换回正规的ndarray。

译注6:原文有歧义,根据上下文的意思,应该是说不容易把其他语言的代码移植过来。