线性代数

线性代数(如矩阵乘法、矩阵分解、行列式以及其他方阵数学等)是任何数组库的重要组成部分。不像某些语言(如MATLAB),通过*对两个二维数组相乘得到的是一个元素级的积,而不是一个矩阵点积。因此,NumPy提供了一个用于矩阵乘法的dot函数(既是一个数组方法也是numpy命名空间中的一个函数):

  1. In [194]: x = np.array([[1., 2., 3.], [4., 5., 6.]])
  2.  
  3. In [195]: y = np.array([[6., 23.], [-1, 7], [8, 9]])
  4.  
  5. In [196]: x In [197]: y
  6. Out[196]: Out[197]:
  7. array([[ 1., 2., 3.], array([[ 6., 23.],
  8. [ 4., 5., 6.]]) [ -1., 7.],
  9. [ 8., 9.]])
  10.  
  11. In [198]: x.dot(y) # 相当于np.dot(x, y)
  12. Out[198]:
  13. array([[ 28., 64.],
  14. [ 67., 181.]])

一个二维数组跟一个大小合适的一维数组的矩阵点积运算之后将会得到一个一维数组:

  1. In [199]: np.dot(x, np.ones(3))
  2. Out[199]: array([ 6., 15.])

numpy.linalg中有一组标准的矩阵分解运算以及诸如求逆和行列式之类的东西。它们跟MATLAB和R等语言所使用的是相同的行业标准级Fortran库,如BLAS、LAPACK、Intel MKL(可能有,取决于你的NumPy版本)等:

  1. In [201]: from numpy.linalg import inv, qr
  2.  
  3. In [202]: X = randn(5, 5)
  4.  
  5. In [203]: mat = X.T.dot(X)
  6.  
  7. In [204]: inv(mat)
  8. Out[204]:
  9. array([[ 3.0361, -0.1808, -0.6878, -2.8285, -1.1911],
  10. [-0.1808, 0.5035, 0.1215, 0.6702, 0.0956],
  11. [-0.6878, 0.1215, 0.2904, 0.8081, 0.3049],
  12. [-2.8285, 0.6702, 0.8081, 3.4152, 1.1557],
  13. [-1.1911, 0.0956, 0.3049, 1.1557, 0.6051]])
  14.  
  15. In [205]: mat.dot(inv(mat))
  16. Out[205]:
  17. array([[ 1., 0., 0., 0., -0.],
  18. [ 0., 1., -0., 0., 0.],
  19. [ 0., -0., 1., 0., 0.],
  20. [ 0., -0., -0., 1., -0.],
  21. [ 0., 0., 0., 0., 1.]])
  22.  
  23. In [206]: q, r = qr(mat)
  24.  
  25. In [207]: r
  26. Out[207]:
  27. array([[ -6.9271, 7.389 , 6.1227, -7.1163, -4.9215],
  28. [ 0. , -3.9735, -0.8671, 2.9747, -5.7402],
  29. [ 0. , 0. , -10.2681, 1.8909, 1.6079],
  30. [ 0. , 0. , 0. , -1.2996, 3.3577],
  31. [ 0. , 0. , 0. , 0. , 0.5571]])

表4-7中列出了一些最常用的线性代数函数。

注意: Python科学计算社区盼望着有朝一日能实现矩阵乘法的中缀运算符,以便能用一种更漂亮的语法代替np.dot。不过目前就只能先这样了。

线性代数 - 图1