19、NumPy——线性代数

NumPy 线性代数

NumPy 提供了线性代数函数库 linalg,该库包含了线性代数所需的所有功能,可以看看下面的说明:

函数 描述
dot 两个数组的点积,即元素对应相乘。
vdot 两个向量的点积
inner 两个数组的内积
matmul 两个数组的矩阵积
determinant 数组的行列式
solve 求解线性矩阵方程
inv 计算矩阵的乘法逆矩阵

 

 

 

 

 

1、numpy.dot()

numpy.dot() 对于两个一维的数组,计算的是这两个数组对应下标元素的乘积和(数学上称之为内积);对于二维数组,计算的是两个数组的矩阵乘积;对于多维数组,它的通用计算公式如下,即结果数组中的每个元素都是:数组a的最后一维上的所有元素与数组b的倒数第二位上的所有元素的乘积和: dot(a, b)[i,j,k,m] = sum(a[i,j,:] * b[k,:,m])。

1 numpy.dot(a, b, out=None)

参数说明:

  • a : ndarray 数组
  • b : ndarray 数组
  • out : ndarray, 可选,用来保存dot()的计算结果

实例:

 1 import numpy as np
 2 # 对于两个一维的数组,计算的是这两个数组对应下标元素的乘积和(数学上称之为内积)
 3 x = np.arange(1, 5)
 4 y = np.arange(2, 6)
 5 print('x:\n', x)
 6 print('y:\n', y)
 7 print('a·b=', np.dot(x, y))
 8 #对于二维数组,计算的是两个数组的矩阵乘积
 9 a = np.matrix([[1, 2]])
10 b = np.matrix('2, 3;4, 5')
11 print('a:\n', a)
12 print('b:\n', b)
13 print(np.dot(a, b))

 执行结果:

x:
 [1 2 3 4]
y:
 [2 3 4 5]
a·b= 40
a:
 [[1 2]]
b:
 [[2 3]
 [4 5]]
[[10 13]]

2、numpy.vdot()

numpy.vdot() 函数是两个向量的点积。 如果第一个参数是复数,那么它的共轭复数会用于计算。 如果参数是多维数组,它会被展开

1 import numpy as np
2 a = np.array([[1, 2], [3, 4]])
3 b = np.array([[11, 12], [13, 14]])
4 print('a:{}\nb:{}'.format(a, b))
5 # vdot 将数组展开计算内积
6 print(np.vdot(a, b))

执行结果:130

计算式:

1*11 + 2*12 + 3*13 + 4*14 = 130

 3、numpy.inner()

numpy.inner() 函数返回一维数组的向量内积。对于更高的维度,它返回最后一个轴上的和的乘积

1 import numpy as np
2 a = np.array([[1, 2], [3, 4]])
3 print('数组 a:')
4 print(a)
5 b = np.array([[11, 12], [13, 14]])
6 print('数组 b:')
7 print(b)
8 print('内积:')
9 print(np.inner(a, b))

 执行结果:

数组 a:
[[1 2]
 [3 4]]
数组 b:
[[11 12]
 [13 14]]
内积:
[[35 41]
 [81 95]]

内积计算式为:

1*11+2*12, 1*13+2*14

3*11+4*12, 3*13+4*14

4、numpy.matmul

numpy.matmul 函数返回两个数组的矩阵乘积。 虽然它返回二维数组的正常乘积,但如果任一参数的维数大于2,则将其视为存在于最后两个索引的矩阵的栈,并进行相应广播。

另一方面,如果任一参数是一维数组,则通过在其维度上附加 1 来将其提升为矩阵,并在乘法之后被去除。

对于二维数组,它就是矩阵乘法:

1 import numpy as np
2 # 对于二维数组,它就是矩阵乘法
3 a = np.matrix([[1, 0], [0, 1]])
4 b = np.matrix([[4, 1], [2, 2]])
5 print('a:\n{}\nb:\n{}'.format(a, b))
6 print('a·b=', np.matmul(a, b))

执行结果:

a:
[[1 0]
 [0 1]]
b:
[[4 1]
 [2 2]]
a·b= [[4 1]
 [2 2]]

 二维和一维运算:

1 import numpy.matlib 
2 import numpy as np 
3  
4 a = [[1,0],[0,1]] 
5 b = [1,2] 
6 print (np.matmul(a,b))
7 print (np.matmul(b,a))

执行结果:

[1  2] 
[1  2]

 维度大于二的数组 :

1 import numpy as np 
2  
3 a = np.arange(8).reshape(2,2,2) 
4 b = np.arange(4).reshape(2,2) 
5 print (np.matmul(a,b))

 执行结果:

[[[ 2  3]
  [ 6 11]]

 [[10 19]
  [14 27]]]、

6、numpy linalg模块

 numpy.linalg模块包含线性代数的函数。使用这个模块,可以计算逆矩阵、求特征值、解线性方程组以及求解行列式等

 6.1 numpy.linalg.inv()

numpy.linalg.inv() 函数计算矩阵的乘法逆矩阵。

逆矩阵(inverse matrix):设A是数域上的一个n阶矩阵,若在相同数域上存在另一个n阶矩阵B,使得: AB=BA=E ,则我们称B是A的逆矩阵,而A则被称为可逆矩阵。注:E为单位矩阵。

1 import numpy as np
2 A = np.matrix('0, 1, 2;1, 0, 3;4, -3, 8')
3 print('A=', A)
4 # 使用inv函数计算逆矩阵
5 A_inv = np.linalg.inv(A)
6 print('矩阵A的逆矩阵:\n', A_inv)
7 # 检查原矩阵和求得的逆矩阵相乘的结果为单位矩阵
8 print('A·A_inv=\n', A*A_inv)

 执行结果:

A= [[ 0  1  2]
 [ 1  0  3]
 [ 4 -3  8]]
矩阵A的逆矩阵:
 [[-4.5  7.  -1.5]
 [-2.   4.  -1. ]
 [ 1.5 -2.   0.5]]
A·A_inv=
 [[1. 0. 0.]
 [0. 1. 0.]
 [0. 0. 1.]]

 # 注:矩阵必须是方阵且可逆,否则会抛出LinAlgError异常

 6.2 numpy.linalg.solve()

numpy.linalg中的函数solve可以求解形如 Ax = b 的线性方程组,其中 A 为矩阵,b 为一维或二维的数组,x 是未知变量

 1 import numpy as np
 2 #创建矩阵和数组
 3 A = np.matrix([[1, 1, 1],
 4                 [4, 2, -5],
 5                 [2, 8, 7]])
 6 b = np.array([6, -4, 27])
 7 # 求解Ax=b的解
 8 x = np.linalg.solve(A, b)
 9 print('方程组解为:\n', x)
10 # 验证
11 print(np.dot(A, x))

 执行结果:

方程组解为:
 [ 2.97727273 -0.11363636  3.13636364]
[[ 6. -4. 27.]]

 6.3   特征值和特征向量

# 特征值(eigenvalue)即方程 Ax = ax 的根,是一个标量。其中,A 是一个二维矩阵,x 是一个一维向量。特征向量(eigenvector)是关于特征值的向量

numpy.linalg模块中,eigvals函数可以计算矩阵的特征值,而eig函数可以返回一个包含特征值和对应的特征向量的元组

 1 import numpy as np
 2 # 创建一个矩阵
 3 A = np.mat("3 -2;1 0")
 4 
 5 print('调用eigvals函数求解特征值:')
 6 a = np.linalg.eigvals(A)
 7 print(a)
 8 print('使用eig函数求解特征值和特征向量 (该函数将返回一个元组,按列排放着特征值和对应的特征向量,\
 9 其中第一列为特征值,第二列为特征向量)')
10 a1, a2 = np.linalg.eig(A)
11 print(a1)
12 print(a2)
13 print('使用dot函数验证求得的解是否正确:')
14 
15 for i in range(len(a1)):
16     print("left:", np.dot(A, a2[:, i]))
17     print("right:", a1[i] * a2[:, i])

执行结果:

调用eigvals函数求解特征值:
[2. 1.]
使用eig函数求解特征值和特征向量 (该函数将返回一个元组,按列排放着特征值和对应的特征向量,其中第一列为特征值,第二列为特征向量)
[2. 1.]
[[0.89442719 0.70710678]
 [0.4472136  0.70710678]]
使用dot函数验证求得的解是否正确:
left: [[1.78885438]
 [0.89442719]]
right: [[1.78885438]
 [0.89442719]]
left: [[0.70710678]
 [0.70710678]]
right: [[0.70710678]
 [0.70710678]]

6.4、numpy.linalg.det()

numpy.linalg.det() 函数计算输入矩阵的行列式。

行列式在线性代数中是非常有用的值。 它从方阵的对角元素计算。 对于 2×2 矩阵,它是左上和右下元素的乘积与其他两个的乘积的差。

换句话说,对于矩阵[[a,b],[c,d]],行列式计算为 ad-bc。 较大的方阵被认为是 2×2 矩阵的组合。

1 import numpy as np
2 a = np.array([[1,2], [3,4]]) 
3  
4 print (np.linalg.det(a))

 输出结果为:-2.0000000000000004

6.5.奇异值分解

# SVD(Singular Value Decomposition,奇异值分解)是一种因子分解运算,将一个矩阵分解为3个矩阵的乘积
# numpy.linalg模块中的svd函数可以对矩阵进行奇异值分解。该函数返回3个矩阵——U、Sigma和V,其中U和V是正交矩阵,Sigma包含输入矩阵的奇异值。

 1 import numpy as np
 2 # 创建矩阵
 3 D = np.mat("4 11 14;8 7 -2")
 4 # 使用svd函数分解矩阵
 5 U, Sigma, V = np.linalg.svd(D, full_matrices=False)
 6 print('U:\n', U)
 7 print('Sigma\n', Sigma)
 8 print('V:\n', V)
 9 # 使用diag函数生成完整的奇异值矩阵。将分解出的3个矩阵相乘
10 print('diag(Sigma):\n', np.diag(Sigma))
11 print(U * np.diag(Sigma) * V)

执行结果:

U:
 [[-0.9486833  -0.31622777]
 [-0.31622777  0.9486833 ]]
Sigma
 [18.97366596  9.48683298]
V:
 [[-0.33333333 -0.66666667 -0.66666667]
 [ 0.66666667  0.33333333 -0.66666667]]
diag(Sigma):
 [[18.97366596  0.        ]
 [ 0.          9.48683298]]
[[ 4. 11. 14.]
 [ 8.  7. -2.]]

 6.6 广义逆矩阵

1 import numpy as np
2 # 创建一个矩阵
3 E = np.mat("4 11 14;8 7 -2")
4 print('使用pinv函数计算广义逆矩阵:')
5 pseudoinv = np.linalg.pinv(E)
6 print(pseudoinv)
7 print('将原矩阵和得到的广义逆矩阵相乘:')
8 print(E * pseudoinv)

 执行结果:

使用pinv函数计算广义逆矩阵:
[[-0.00555556  0.07222222]
 [ 0.02222222  0.04444444]
 [ 0.05555556 -0.05555556]]
将原矩阵和得到的广义逆矩阵相乘:
[[ 1.00000000e+00 -9.29811783e-16]
 [-1.66533454e-16  1.00000000e+00]]

 numpy.linalg模块包含线性代数的函数。使用这个模块,可以计算逆矩阵、求特征值、解线性方程组以及求解行列式等

猜你喜欢

转载自www.cnblogs.com/weststar/p/11596414.html