无法播放?请 点击这里 跳转到Youtube
切换视频源:

通过前两章的学习,我们已经学会了创建NumPy数组常用的函数,以及和索引相关的内容。这一章我们来更深入地学习NumPy中和数学相关的函数,帮助我们更好地掌握如何实现NumPy数组中的数学运算。

Arithmetic operations

首先我们来学习一下 NumPy中基本的算数运算,除了使用计算符号实现这类操作之外,我们还能直接使用NumPy自带的一些函数。

matrix1 = np.array([[1,2],[3,4]], dtype=np.float64)
matrix2 = np.array([[5,6],[7,8]], dtype=np.float64)

matrix1 + matrix2 # 加法
np.add(matrix1, matrix2)
[[ 6.  8.]
 [10. 12.]]

matrix1 - matrix2 # 减法
np.add(matrix1, matrix2)
[[-4. -4.]
 [-4. -4.]]

matrix1 * matrix2 # 相乘
np.multiply(matrix1, matrix2)
[[ 5. 12.]
 [21. 32.]]

matrix1 / matrix2 # 相除
np.divide(matrix1, matrix2)
[[0.2        0.33333333]
 [0.42857143 0.5       ]]

matrix2 // matrix1 # 整除
np.floor_divide(matrix2, matrix1)
[[5. 3.]
 [2. 2.]]

matrix2 % matrix1 # 取余
np.mod(matrix2, matrix1)
[[0. 0.]
 [1. 0.]]

matrix1 ** matrix2 # 幂运算
np.power(matrix1, matrix2)
[[1.0000e+00 6.4000e+01]
 [2.1870e+03 6.5536e+04]]

Mathematical and statistical functions

除了简单的算数计算,NumPy也提供了许多和数学与统计相关的函数,帮助我们方便地获取相关的运算结果。

rand_matrix = (np.random.randint(10, 1000, size=(2,5)) - 500) / 10.0
[[ 20.   15.4 -12.8  -1.1  -8.8]
 [-18.3 -19.6  20.2 -15.5  43.1]]

print(np.isnan(rand_matrix)) # 检测是否为nan
[[False False False False False]
 [False False False False False]]

print(np.sign(rand_matrix)) # 检测每个元素的正负,正是1,负是-1
[[ 1.  1. -1. -1. -1.]
 [-1. -1.  1. -1.  1.]]

print(np.nonzero(rand_matrix)) # 拿到数组中非零元素的位置,会返回非零元素的索引值位置
(array([0, 0, 0, 0, 0, 1, 1, 1, 1, 1]), array([0, 1, 2, 3, 4, 0, 1, 2, 3, 4]))

print(np.ceil(rand_matrix)) # 拿到大于元素的最小整数
[[ 20.  16. -12.  -1.  -8.]
 [-18. -19.  21. -15.  44.]]

print(np.cumsum(rand_matrix)) # 计算数组的累计和
[ 20.   35.4  22.6  21.5  12.7  -5.6 -25.2  -5.  -20.5  22.6]

print(np.diff(rand_matrix)) # 计算数组的离散差值
[[ -4.6 -28.2  11.7  -7.7]
 [ -1.3  39.8 -35.7  58.6]]

print(np.sqrt(matrix1)) # 计算数组的正平方根
[[4.47213595 3.92428337        nan        nan        nan]
 [       nan        nan 4.49444101        nan 6.56505902]]

print(np.square(rand_matrix)) # 计算数组的平方数
[[4.00000e+02 2.37160e+02 1.63840e+02 1.21000e+00 7.74400e+01]
 [3.34890e+02 3.84160e+02 4.08040e+02 2.40250e+02 1.85761e+03]]

m2 = np.arange(10) * 2
np.sin(m2) # 计算数组的三角函数 sin
[ 0.          0.90929743 -0.7568025  -0.2794155   0.98935825 -0.54402111
 -0.53657292  0.99060736 -0.28790332 -0.75098725]

print(np.sort(rand_matrix)) # 将数组进行排序
[[-12.8  -8.8  -1.1  15.4  20. ]
 [-19.6 -18.3 -15.5  20.2  43.1]]

还有以下常用的统计函数:

matrix = np.arange(10).reshape(2, 5)
[[-5 -4 -3 -2 -1]
 [ 0  1  2  3  4]]

matrix.mean() # 数组中的平均数: -0.5
np.median(matrix) # 数组中的中位数: -0.5
np.argmin(matrix) # 数组中最大数的索引值: 0
np.argmax(matrix) # 数组中最大数的索引值: 9

np.sum(matrix) # 计算所有元素相加的和: -5
np.abs(matrix) # 计算数组元素的绝对值
[[5 4 3 2 1]
 [0 1 2 3 4]]
np.max(matrix) # 数组中最大的数: 4

np.sum(matrix) # 计算所有元素的和: -5
np.sum(matrix, axis=0) # 按列相加之和的数组
[-5 -3 -1  1  3]
np.sum(matrix, axis=1) # 按行相加之和的数组
[-15  10]

Linear Algebra

除了上面提到的基本数学计算,NumPy还支持和线性代数相关的计算操作,可以帮助我们非常方便地对矩阵进行相关操作。

matrix1 = np.arange(8).reshape(2, 4)
print(matrix)
[[0 1 2 3]
 [4 5 6 7]]
print(matrix.T) # 转置矩阵 Tranpose
[[0 4]
 [1 5]
 [2 6]
 [3 7]]
matrix2 = np.arange(5)
print(matrix2)
print(matrix2.T)
[[0 1 2 3 4]]

matrix3 = matrix2.reshape(1, 5)
print(matrix3)
print(matrix3.T)
[[0]
 [1]
 [2]
 [3]
 [4]]

矩阵乘法

matrix1 = np.arange(8).reshape(2, 4)
print(matrix1)
[[0 1 2 3]
 [4 5 6 7]]

matrix2 = np.arange(8).reshape(4, 2)
print(matrix2)
[[0 1]
 [2 3]
 [4 5]
 [6 7]]

print(matrix1.dot(matrix2)) # 矩阵积
[[28 34]
 [76 98]]

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

matrix = np.arange(9).reshape(3, 3)
inverse_matrix = np.linalg.inv(matrix) # 获得逆矩阵: 此语句会返回错误,因为该矩阵是Singular Matrix,所有没有相对性的逆矩阵

valid_matrix = np.array([[1,2,3],[5,7,11],[21,29,31]])
print(valid_matrix)
inverse_matrix = np.linalg.inv(valid_matrix) # 获得逆矩阵
print(inverse_matrix)
[[-2.31818182  0.56818182  0.02272727]
 [ 1.72727273 -0.72727273  0.09090909]
 [-0.04545455  0.29545455 -0.06818182]]

print(valid_matrix.dot(inverse_matrix)) # The product of a matrix by its inverse returns the identity matrix
[[ 1.00000000e+00 -1.66533454e-16  0.00000000e+00]
 [ 6.31439345e-16  1.00000000e+00 -1.38777878e-16]
 [ 5.21110932e-15 -2.38697950e-15  1.00000000e+00]]

print(np.eye(3)) # eye函数可以输出对角线为1的矩阵,函数内的参数代表1的个数

获得矩阵的行列式:

np.linalg.det(valid_matrix) # 获得矩阵的行列式: 43.9999

计算矩阵的特征值和右特征向量(Eigenvalues and eigenvectors)

eigenvalues, eigenvectors = np.linalg.eig(matrix) # 计算方阵的特征值和右特征向量
print(eigenvalues)
print(eigenvectors)
print(matrix.dot(eigenvectors) - eigenvalues * eigenvectors) # M.E1 - E2.E1 = 0

我们甚至还能直接使用NumPy自带的函数解决线性标量方程,比如我们可以使用下面的代码,给以下两个方程求解:

  • 2x + 6y = 6
  • 5x + 3y = -9
coeffs = np.array([[2,6],[5,3]])
depvars = np.array([6,-9])
solution = np.linalg.solve(coeffs, depvars) # 以矩阵形式解一个线性矩阵方程
print(solution) # array([-3., 2.])

coeffs.dot(solution), depvars # (array([ 6., -9.]), array([ 6, -9]))

Homework

将以下的两个不同形状的矩阵,进行矩阵的相乘,得到最终形状为(3,3)的矩阵。然后计算出数组中各个元素的正平方根,最后再将计算之后所有元素相加,得到一个和。

matrix1 = np.arange(15).reshape(3, 5)
matrix2 = np.arange(15).reshape(5, 3)

答案:

matrix3 = np.dot(matrix1, matrix2)
matrix3 = np.sqrt(matrix3)
total_sum =np.sum(matrix3)
print(total_sum) # 143.2015963354727