如果你觉得内容对你有帮助,请在 GitHub 上点个 star 吧!

1.5. 数学运算#

本节将对创建的高维数组进行一些数学运算,包括一元函数、二元函数、统计函数以及线性代数。这些运算操作大部分都比较直观,通过函数名或数学运算符的名字,我们就可以知道其要进行的数学计算。

Hide code cell content
import numpy as np

在正式开始前,我们先生成数组 xyz 用作演示练习使用。

x = np.array([1,2,3,4])
y = np.array([-1.2,1.4,1.5,1.7])
z = np.array([-1.2,1.4,1.5,1.7])

一元函数#

一元函数对一个数组执行元素级运算。下面以对数 \(\log\) 和取整两个计算来演示 NumPy 的一元运算,其他运算可参考其官方文档。

对数#

对数函数是数学中的一种常见函数,如果 \(a^x=N\),那么 \(x = \log_{a} N\),其中 \(a\)叫做底数,\(N\) 叫真数。通常以 10 为底的对数叫做常用对数,以 \(e\) 为底的对数称为自然对数。

np.log() 是以 \(e\) 为底的自然对数。

np.log(x)
array([0.        , 0.69314718, 1.09861229, 1.38629436])

np.log10() 对数组中元素求常用对数。

np.log10(x)
array([0.        , 0.30103   , 0.47712125, 0.60205999])

取整运算#

np.ceil() 对数组各元素向上取整;np.floor() 对数组中各个元素向下取整;np.rint() 对数组各元素四舍五入取整。

np.floor(z)
array([-2.,  1.,  1.,  1.])
np.rint(z)
array([-1.,  1.,  2.,  2.])

除去以上一元函数,还有以下函数较为常用:

类型

函数

用途

普通型三角函数

[np.sin() ]

计算正弦函数

普通型三角函数

[np.cos() ]

计算余弦函数

普通型三角函数

[np.tan() ]

计算正切函数

双曲型三角函数

[np.sinh() ]

计算双曲正弦函数

双曲型三角函数

[np.cosh() ]

计算双曲余弦函数

双曲型三角函数

[np.tanh() ]

计算双曲正切函数

指数函数

[np.exp() ]

计算数组各元素的指数值

符号函数

[np.sign() ]

计算数组各元素的符号值

二元函数#

二元运算是指对两个对象(操作数)进行的运算:给定集合 \(A\),二元函数 \(F\) : \(A\times A\)\(A\) 称为集合 \(A\) 上的二元运算。需要注意的是,二元运算的运算结果跟两个输入值必须是同种类型的数据。例如,加法的两个操作数都是整数,得到的运算结果也是整数。

简单数学操作#

两个数组的元素加减乘比较直观,使用常用的数学符号即可。

函数

含义

示例

[+]

对两个数组进行加法运算

x+y

[-]

对两个数组进行减法运算

x-y

[*]

对两个数组进行乘法运算

x*y

[/]

对两个数组进行乘法运算

x/y

下面我们以两个数组元素的加法运算为例:

x / y
array([-0.83333333,  1.42857143,  2.        ,  2.35294118])

np.fmaxnp.maximumnp.fminnp.minimum函数对两个数组进行元素级最大/小值计算。

np.maximum(x,y)
array([1., 2., 3., 4.])

比较操作#

我们可以对两个数组逐元素进行算数比较,产生布尔型数组:

符号

含义

[ ]

小于

[]

大于

[>=]

大于等于

[ <=]

小于等于

[== ]

等于

[!= ]

不等于

Note

需要注意的是,我们常用 = 表示赋值功能,不能用来进行数组的比较。判定数组是否相等时,使用 == 符号。

下面用一个例子作为示范,使用 == 对数组 xy 元素级进行比较是否相等,相等输出结果 True ,若元素对应不相等,则输出结果 False

x==y
array([False, False, False, False])

统计函数#

一元函数和二元函数对数组进行元素级运算,统计函数对高维数组的某个维度(行或列)及整体进行统计运算。

Note

axis 参数用来指定对高维数组的哪个维度(或者说是轴)进行操作,不指定时默认求整体;axis=0 对高维数组的第一个维度进行计算,二维数组的 axis=0 指的是列; axis=1 对高维数组的第二个维度进行计算,二维数组的 axis=1 指的是行。

np_array_2d = np.arange(0, 6).reshape([2,3])
np_array_2d
array([[0, 1, 2],
       [3, 4, 5]])
np.sum(np_array_2d, axis = 0)
array([3, 5, 7])
np.sum(np_array_2d)
15

其他统计函数还有:

函数

用途

[np.mean()]

求平均值

[np.sum()]

求和

[np.max()]

求最大值

[np.min()]

求最小值

[np.var()]

求方差

[np.std()]

求标准误

线性代数#

矩阵与向量的乘积#

dot(a,b) 计算两个数组的点积:

1)如果 ab 都是一维数组,那么点积即为内积(没有共轭);

np.dot(3, 4)
12
np.dot(3j, 4j)
(-12+0j)

2)如果 ab 都是二维数组,np.dot() 等价于矩阵乘法,也可以用 a @ b 来表示;

a = [[1, 0], [0, 1]]
b = [[4, 1], [2, 2]]
np.dot(a, b)
array([[4, 1],
       [2, 2]])

3)如果 ab 是标量(维数为 0),那么其点积等价于乘,可以使用 numpy.multiply(a,b)a*b 来表示;

a = 4
b = [[4,1],[2,2]]
np.dot(a,b)
array([[16,  4],
       [ 8,  8]])

4)如果a 是一维数组, bN维数组,那么点积是 ab 的最后一个轴的积的和;

a = [3,4,5]
b = [[1,2,3],[4,5,6],[7,8,9]]
np.dot(a,b)
array([54, 66, 78])

5)如果aN维数组, bM-d维数组(M≥2),那么点积为 a 的最后一个轴与 b 的倒数第二条轴的乘机的和: dot(a,b)[i,j,k,m] = sum(a[i,j,:]*b[k,:,m])

a = [[1,5,7],[2,4,6],[3,6,9],[4,8,10]]
b = [[1,2,3],[4,5,6],[7,8,9]]
np.dot(a,b)
array([[ 70,  83,  96],
       [ 60,  72,  84],
       [ 90, 108, 126],
       [106, 128, 150]])

矩阵特征值#

假设我们有一个 n 阶的矩阵 A 以及一个实数 λ ,使得我们可以找到一个非零向量 x ,满足:\(Ax = \lambda x\),如果能够找到的话,我们就称 λ 是矩阵 A 的特征值,非零向量 x 是矩阵 A 的特征向量。我们可以使用 np.linalg.eig(a) 函数计算方阵的特征值和特征向量。

eigenvalues, eigenvectors = np.linalg.eig(np.diag((1, 2, 3)))

我们还可以使用 np.linalg.eigvals(a) 函数计算一般矩阵的特征值。 与 np.linalg.eig() 函数不同的是, np.linalg.eigvals() 不返回特征向量。

范数(norm)和秩(rank)#

在线性代数中, 范数(norm)是一个表示“长度”概念的函数,为向量空间内的所有向量赋予非零的正长度或大小。

首先,我们生成矩阵 a 用于练习演示:

b = np.arange(9)
a = b.reshape((3,3))
a
array([[0, 1, 2],
       [3, 4, 5],
       [6, 7, 8]])
np.linalg.norm(a)
14.2828568570857

在线性代数中,一个矩阵 A 的列秩是 A 的线性独立的纵列的极大数,通常表示为 r(A)rk(A)rank A 。 行秩是 A 的线性无关的横行的极大数目。即如果把矩阵看成一个个行向量或者列向量,秩就是这些行向量或者列向量的秩,也就是极大无关组中所含向量的个数。我们可以使用 np.linalg.matrix_rank(A) 函数,使用 SVD 方法计算并返回数组的矩阵秩。

np.linalg.matrix_rank(a) 
2

接下来,我们生成一个4维满秩的矩阵 b ,该矩阵的秩与维数相同。

b = np.eye(4)
b
array([[1., 0., 0., 0.],
       [0., 1., 0., 0.],
       [0., 0., 1., 0.],
       [0., 0., 0., 1.]])

解方程与逆#

我们可以使用 np.linalg.solve(a, b) 函数求解线性矩阵方程或线性标量方程组。

a = np.array([[1, 2], [7, 9]])
b = np.array([1, 2])
x = np.linalg.solve(a, b)
x
array([-1.,  1.])

根据生成的矩阵中元素,我们可以列出所求解的方程组为 x0+2*x1=17*x0+9*x1=2

A 是数域上的一个 n 阶方阵,若在相同数域上存在另一个 n 阶矩 B ,使得: AB=BA=E 。则我们称 BA 的逆矩阵, A 则被称为可逆矩阵。 其中,E 为单位矩阵

我们可以使用 np.linalg.inv(a) 函数对矩阵 a 求逆。

b = np.arange(4) +1
a = b.reshape((2,2))
ainv = np.linalg.inv(a)
ainv
array([[-2. ,  1. ],
       [ 1.5, -0.5]])