这里是一则小广告:
关注作者请点击这里哦:zdr0
我的专栏里面不仅有学习笔记,也有一些科普文章,相信我的专栏不会让您失望哦~大家可以关注一下:数学及自然科学
记得点赞加收藏哦~
创作不易,请赞赏一下支持一下作者吧[期待]~
-尽力写最好的讲义,尽力写最好的科普。
-由于本人是自学Python,所以文中如果有错误或表述不当的地方还望给位大佬不吝指出,感谢!
是
中的用于数值计算的一个包,在这篇文章中我将来介绍一些
包的一些基本操作,首先我们要在
中导入这个包:
import numpy as np总注:若无特殊说明,那么下文中的数组均指的是
数组。
数组
首先我们来学习一下
维的
数组。一个一维
的
数组是一个矢量;
一个二维
的
数组是一个矩阵。
比如:
>>> A = np.array([[1,2,3,4],
[5,6,7,8],
[9,10,11,12],
[13,14,15,16]])
>>>
>>> print(A)
[[ 1 2 3 4]
[ 5 6 7 8]
[ 9 10 11 12]
[13 14 15 16]]
上面的例子创建的矩阵相当于矩阵:
而:
>>> x = np.array([1,2,3,4])
>>> y = np.array([[10],
[20],
[30]])
>>>
>>> print(x)
[1 2 3 4]
>>>
>>> print(y)
[[10]
[20]
[30]]
创建的是两个矢量,它们相当于矢量:
而一维的矢量通常被看是属于
的一个矩阵。如果想要创建一个
下的矩阵,那么我们只要像这里一样,创建一个二维的数组即可。在
中,矢量没有行矢量和列矢量之分。根据需求转化为对应的形式。我们可以对数组中的某个元素进行赋值,只要我们给出这个元素的位置即可,即给出想要进行赋值的元素的行索引和列索引即可。注意:行和列的初始索引均为
。
假如我们要对第一个例子中的矩阵
的索引为
的元素赋值为
的话那我们只需要:
>>> A[3,2] = 0
>>>
>>> print(A)
[[ 1 2 3 4]
[ 5 6 7 8]
[ 9 10 11 12]
[13 14 0 16]]
代表的是数学形式中的矩阵
的第
行第
列的数字。而在
数组中,
代表的是矩阵
中的第
行第
列的数字。这是因为这数学形式中,矩阵的行、列均是从
开始索引的,而在
数组中,矩阵的行、列均是从
开始索引。所以,
数组中的矩阵的第
行相当于数学形式中的
行;第
列相当于数学形式中的第
列。现在对应的
是:
对于元素均为
或元素均为
的矩阵我们有更简便的方式创建:
>>> B = np.zeros((4,3))
>>> C = np.ones((2,5))
>>>
>>> print(B)
[[0. 0. 0.]
[0. 0. 0.]
[0. 0. 0.]
[0. 0. 0.]]
>>>
>>> print(C)
[[1. 1. 1. 1. 1.]
[1. 1. 1. 1. 1.]]
对应了矩阵:
创建一个
行
列的元素全部为
的矩阵;
创建一个
行
列的元素全部为
的矩阵。注意:这里的
不是索引!而是这个矩阵的行数和列数!
对于单位矩阵,我们也有简便的创建方式:
>>> n = 3
>>> I = np.eye(n,n)
>>> I1 = np.eye(3,3)
>>>
>>> print(I)
[[1. 0. 0.]
[0. 1. 0.]
[0. 0. 1.]]
>>>
>>> print(I1)
[[1. 0. 0.]
[0. 1. 0.]
[0. 0. 1.]]
均为三维的单位矩阵,它们相当于:
创建一个
的单位矩阵。注意:
可以被提前赋值,也可以在创建单位矩阵的同时进行赋值(见上例)。而且与
和
相比,
后面只有一个括号!
还有一些命令可以生成一些特殊的数组,比如:
>>> x =np.arange(0,2.2,0.2)
>>>
>>> print(x)
[0. 0.2 0.4 0.6 0.8 1. 1.2 1.4 1.6 1.8 2. ]
是一个一维的数组,它们相当于:
创建一个范围为
,间隔为
的一维数组。
数组的一部分
我们在
节的一开始定义了定义了一个数组
之后,下面我们就思考了,如何取出这个
中的一部分呢?这一部分可以是某一行,某一列,或是一个子数组,我们来看以下代码:
>>> A = np.array([[1,2,3,4],
[5,6,7,8],
[9,10,11,12],
[13,14,15,16]])
>>>
>>> print(A)
[[ 1 2 3 4]
[ 5 6 7 8]
[ 9 10 11 12]
[13 14 15 16]]
>>>
>>> u = A[1,:] #a vector from A
>>> v = A[:,2] #a vector from A
>>> B = A[0:3,0:2] #a matrix from A
>>> C = A[2:4,2:4] #a matrix from A
>>>
>>> print(u)
[5 6 7 8]
>>>
>>> print(v)
[ 3 7 11 15]
>>>
>>> print(B)
[[ 1 2]
[ 5 6]
[ 9 10]]
>>>
>>> print(C)
[[11 12]
[15 16]]
其中,
是二维数组
中索引为
的行(即第二行),它相当于:
是二维数组
中索引为
的列(即第三列),它相当于:
是二维数组
中索引为
到索引为
行、索引为
到索引为
列的子数组,它相当于:
是二维数组
中索引为
到索引为
行、索引为
到索引为
列的子数组,它相当于:
取出数组中行索引为
,列索引为
的元素。且
的值必须小于二维数组
的最大行数,而
的值必须小于二维数组
的最大列数;
取出二维数组
中的索引为
的一整行,且
小于
的最大行数。所取出的一整行为一个矢量,且这个矢量的维度是二维数组
的列数;
取出二维数组
中的索引为
的一整列,且
小于
的最大列数。所取出的一整列为一个矢量,且这个矢量的维度是二维数组
的行数;
取出二维数组
中的索引
到索引
行、索引
到索引
列的一个子数组。其中,
的值可以等于二维数组
的最大行数;
的值可以等于二维数组
的最大列数,但是
的值不能等于二维数组
的最大行数;
的值不能等于二维数组
的最大列数。所取出的子数组是一个矩阵;
取出二维数组
中的索引
到索引
行的一个子数组。其中,
的值可以等于二维数组
的最大行数,但是
的值不能等于二维数组
的最大行数,所取出的子数组是一个行矩阵;
取出二维数组
中的索引
到索引
列的一个子数组。其中,
的值可以等于二维数组
的最大列数,但是
的值不能等于二维数组
的最大列数,所取出的子数组是一个列矩阵。
下面举几个错误例子:
>>> A[4,4]
Traceback (most recent call last):
File "", line 1, in
A[4,4]
IndexError: index 4 is out of bounds for axis 0 with size 4
>>>
>>> F = A[4:4,:]
>>> print(F)
[]
>>> G = A[:,4:4]
>>> print(G)
[]
>>> H = A[4:3,:]
>>> print(H)
[]
>>> I = A[:,4:3]
>>> print(I)
[]
再来体会一下
和
之间的区别:
>>> A[3,3]
16 #scalar
>>>
>>> H = A[3:4,3:4]
>>> print(H)
[[16]] #matrix
一个数组也可以通过它的子数组定义,比如:
>>> I = np.eye(2,2)
>>> Z = np.zeros((2,2))
>>> E = np.array([[2,-1],
[-1,2]])
>>> D = np.hstack((np.vstack((E,Z,I),np.vstack((Z,E,Z)),np.vstack((I,Z,E))))
>>>
>>>print(D)
[[ 2. -1. 0. 0. 1. 0.]
[-1. 2. 0. 0. 0. 1.]
[ 0. 0. 2. -1. 0. 0.]
[ 0. 0. -1. 2. 0. 0.]
[ 1. 0. 0. 0. 2. -1.]
[ 0. 1. 0. 0. -1. 2.]]
最终是由
:
:
:
所组成,最后:
这里将矩阵
组合起来用到了两个函数: 参数
可以是元组,列表,或者
数组,返回结果为
数组。
,动词,具有“堆、叠”之意,
,形容词,“水平的”,所以
的意思就是“水平堆叠”,即就是水平(按列顺序)把数组给堆叠起来;
参数
可以是元组,列表,或者
数组,返回结果为
数组。
,动词,具有“堆、叠”之意,
,形容词,“垂直的”,所以
的意思就是“垂直堆叠”,即就是垂直(按列顺序)把数组给堆叠起来;
所以: 是将矩阵
按照顺序垂直堆叠起来,作为矩阵
的第一、二列:
是将矩阵
按照顺序垂直堆叠起来,作为矩阵
的第三、四列:
是将矩阵
按照顺序垂直堆叠起来,作为矩阵
的第五、六列:
是将矩阵
按照顺序水平堆叠起来
,即得到
。
我们还可以将二维数组
中的某行或某列删除,比如:
>>> B = np.delete(A,(1),axis = 0)
>>> C = np.delete(A,(1),axis = 1)
>>>
>>> print(B)
[[ 1 2 3 4]
[ 9 10 11 12]
[13 14 15 16]]
>>>
>>> print(C)
[[ 1 3 4]
[ 5 7 8]
[ 9 11 12]
[13 15 16]]
其中,矩阵
是删除了矩阵
中的索引为
的行(即第二行
)后的数组,其相当于:
矩阵
是删除了矩阵
中的索引为
的列(即第二列
)后的数组,其相当于:
其中,
为被操作的数组,
指的是要删除的项的索引,
的取值可以是:
:
按行删除;
:
按列删除;
:
会先按行展开,然后按照
,删除第
(从
开始)位置的数,返回一个行矩阵。注意:
的值只能小于矩阵
的最大行数或者最大列数!
我们也可以按照以下方式定义一个矩阵:
>>> D = np.vstack((A[0:2,:],np.array([21,22,23,24]),A[3,:]))
将矩阵
的索引为
的行(即第一行)到索引为
的行(即第二行),矢量
和举证
索引为
的行(即第四行)垂直堆叠起来得到矩阵
,最终矩阵
相当于:
数组的运算
对于两个
维的二维数组(矩阵)
,由于两者维数相同,所以可以直接进行相加减:
>>> A = np.array([[1,2],
[3,4]])
>>> B = np.array([[5,6],
[7,8]])
>>>
>>> C = A+B
>>> print(C)
[[ 6 8]
[10 12]]
>>>
>>> D = A-B
>>>
>>>print(D)
[[-4 -4]
[-4 -4]]
两个相同维数的矩阵相加减就是它们对应位置上的元素相加减,即若:
则:
对于矩阵的乘法,
除了定义了数学中两个矩阵的乘法之外,还定义了一种特殊的矩阵乘法——对应元素相乘。下面我们就通过一个例子来看看两者有何不同:
>>> A = np.array([[1,2],
[3,4]])
>>> B = np.array([[5,6],
[7,8]])
>>>
>>> print(A*B)
[[ 5 12]
[21 32]]
>>>
>>> print(np.dot(A,B))
[[19 22]
[43 50]]
>>>
>>> print(np.dot(B,A))
[[23 34]
[31 46]] 只对维数相同的矩阵
有效!否则会报错。将对应位置上的元素相乘放在对应位置上即可;
数学上的矩阵乘法即
。且一般有
。而且可以调换顺序(这里可以调换顺序是指矩阵
调换之后仍可以计算出结果)的矩阵
为
,则
,
。比如:
>>> C = np.array([[1,2],
[3,4],
[5,6]])
>>> D = np.array([[1,2,3],
[4,5,6]])
>>> print(np.dot(C,D))
[[ 9 12 15]
[19 26 33]
[29 40 51]]
>>> print(np.dot(D,C))
[[22 28]
[49 64]]
>>> print(C*D)
Traceback (most recent call last):
File "", line 1, in
print(C*D)
ValueError: operands could not be broadcast together with shapes (3,2) (2,3)
由于矩阵的
乘只能在同维数的两个矩阵下进行,那么随之而来的一种计算方式就是对矩阵求幂,我们来看一个例子:
>>> A = np.array([[1,2],
[3,4]])
>>>
>>> E = np.linalg.matrix_power(A,3) #C = A∗A∗A
>>> F = A**3
>>>
>>> print(E)
[[ 37 54]
[ 81 118]]
>>>
>>> print(F)
[[ 1 8]
[27 64]] 矩阵
的
次方,即
个 矩阵
相乘,矩阵
必须为方阵;
矩阵
中的各个元素的
次方,在这种情况下,矩阵
不必为方阵。
最后的是矩阵的除法,例如:
>>> A = np.array([[1,2],
[3,4]],)
>>> B = np.array([[5,6],
[7,8]],)
>>>
>>> print(A/B)
[[0.2 0.33333333]
[0.42857143 0.5 ]]
>>>
>>> C = np.array([[1,2],
[3,4],
[5,6]])
>>> E = np.array([[2,1],
[4,3],
[6,5]])
>>> print(C/E)
[[0.5 2. ]
[0.75 1.33333333]
[0.83333333 1.2 ]] 矩阵
和矩阵
的对应位置上的元素相除。这里矩阵
虽不必具有相同的维数,但是矩阵
的行数和列数必须一致,即若
,那么
。
数组函数
我们还是以在
节最开始创建的二维数组
为例进行说明进行说明。
我们想要确定矩阵
的维数,那我们需要使用以下函数:
>>> A = np.array([[1,2,3,4],
[5,6,7,8],
[9,10,11,12],
[13,14,15,16]])
>>>
>>> np.shape(A)
(4,4) 确定矩阵矩阵
的维数,并将结果存在一个元组中。第一个数字是行的维数,第二个数字是列的维数。
确定一个一维数组的长度:
>>> x = ([1,2,3,4,5,6])
>>> len(x)
6 确定一维数组
的长度。
取出矩阵
的主对角线上的元素:
>>> print(np.diag(A))
[ 1 6 11 16]
>>>
>>> C = np.array([[1,2],
[3,4],
[5,6]])
>>>
>>> print(np.diag(C))
[1 4]
>>>
>>> D = np.array([[1,2,3],
[4,5,6]])
>>>
>>> print(np.diag(D))
[1 5] 取出矩阵
的主对角线上的元素,并返回一个一维数组。这里的矩阵
不必为方阵,即便不是方阵也可以(见上例)。
反过来,给定一个长度为的
一维数组
,则下面的命令:
>>> v = np.array([1,2,3,4,5,6]) #n = 6
>>> B = np.diag(v)
>>> print(B)
[[1 0 0 0 0 0]
[0 2 0 0 0 0]
[0 0 3 0 0 0]
[0 0 0 4 0 0]
[0 0 0 0 5 0]
[0 0 0 0 0 6]] 生成一个以一维数组
中的元素为对角线元素的、维度为
的矩阵,而且这个矩阵除了主对角线上的元素以外其余全部元素均为
。
>>> v = np.array([1,2,3,4,5,6])
>>> C = np.diag(v,1)
>>>
>>> print(C)
[[0 1 0 0 0 0 0]
[0 0 2 0 0 0 0]
[0 0 0 3 0 0 0]
[0 0 0 0 4 0 0]
[0 0 0 0 0 5 0]
[0 0 0 0 0 0 6]
[0 0 0 0 0 0 0]] 生成一个以一维数组
中的元素为主对角线上面的第
条副对角线上的元素的、维度为
的矩阵,而且这个矩阵除了主对角线上面的第条
副对角线上的元素以外其余全部元素均为
。
我么也可以通过以下命令来求矩阵
中的所有行和所有列上的元素的和:
>>> print(np.sum(A,axis = 0))
[28 32 36 40]
>>>
>>> print(np.sum(A,axis = 1))
[10 26 42 58] 对矩阵
的每一列上的元素求和,最终得到一个一维的数组;
对矩阵
的每一行上的元素求和,最终得到一个一维的数组。
>>> B = A.T
>>> print(B)
[[ 1 5 9 13]
[ 2 6 10 14]
[ 3 7 11 15]
[ 4 8 12 16]] 计算矩阵
的转置。
还有一些别的例子:
>>> u = np.sum(np.diag(A))
>>> z = np.sum(A[:,3])
>>> v = np.sum(A)
>>>
>>> print(np.sum(np.diag(A)))
34
>>> print(np.sum(A[:,3]))
40
>>> print(np.sum(A))
136 求矩阵
的对角线上的元素的和;
求矩阵
的第四列上的元素的和;
求矩阵
的所有元素的和;
下面的函数是有关一维数组
的函数:
>>> np.max(x)
6
>>> np.min(x)
1
>>> np.linalg.norm(x,ord=1)
21.0
>>> np.linalg.norm(x,ord=2)
9.539392014169456
>>> np.linalg.norm(x,ord=np.inf)
6.0 求一维数组
的最大值;
求一维数组
的最小值;
求一维数组
的
范数;
求一维数组
的
范数;
求一维数组
的
范数。
还有一些常见的常数:
>>> np.pi
3.141592653589793
>>> np.e
2.718281828459045
最后一些是一些我们在数学上学习的过的重要函数:
>>> np.exp(a)
>>> np.log(a) #自然底数的对数函数
>>> np.log10(a)
>>> np.log2(a)
>>> np.sqrt(a)
>>> a∗∗(1/n) #n次根号a
>>> np.sin(a)
>>> np.cos(a)
>>> np.tan(a)
>>> np.ceil(a) #>=a的下一个整数
>>> np.floor(a) #<=a的下一个整数
>>> np.round(a) #对a四舍五入