NumPy
认识NumPy
NumPy是Python的一个科学计算库,用于快速处理大型矩阵,可以看做是打开人工智能的一把钥匙。
在Python中本身提供的有list结构,但是list中的元素可以是任何对象,就会导致list中保存的是对象的指针,进行运算的时候就得去做内存寻址,类型检测等事情,显然会浪费比较多的内存和CPU资源。在大数据的环境下,list结构难以胜任。
NumPy的很多底层函数都是用C语言编写,所以运行速度是普通Python代码无法相比的。
注:NumPy中的数组类型名叫anarray,在本文中一般直接称作矩阵或数组。
安装
pip3 install numpy
import numpy as np print(np.__version__)
打印结果:
1.19.2
注:导入的numpy模块一般都会命名为np,因此在本文中只要出现np.xxx 指的都是numpy模块中的xxx函数或属性。
创建矩阵
基本创建
转化生成
创建矩阵使用np.array方法进行创建,可传入列表、元组、字典,将传入的对象转化为矩阵。
也可以指定存储的数据类型dtype,不指定dtype的话默认会自动判断类型。dtype一般有有符号整数int8、int16、int32,无符号整数unit8、unit16、unit32、浮点数float16、float32、float64,布尔值bool,复数complex、complex64、complex128。
list1 = [0,1,2,3,4] arr1 = np.array(list1) print(arr1) print(f'矩阵的对象类型:{type(arr1)}') print(f'矩阵的数据类型:{arr1.dtype}') print(f'矩阵的元素总数:{arr1.size}') print(f'矩阵的维数:{arr1.ndim}') print(f'矩阵的形状:{arr1.shape}')
打印结果:
[0 1 2 3 4]
矩阵的对象类型:<class 'numpy.ndarray'>
矩阵的数据类型:int32
矩阵的元素总数:5
矩阵的维数:1
矩阵的形状:(5,)
打印的形状代表这是有5个元素的一维矩阵。
list2 = [[0,1,2,3,4],[5,6,7,8,9]] arr2 = np.array(list2) print(arr2) print(f'矩阵的对象类型:{type(arr2)}') print(f'矩阵的数据类型:{arr2.dtype}') print(f'矩阵的元素总数:{arr2.size}') print(f'矩阵的维数:{arr2.ndim}') print(f'矩阵的形状:{arr2.shape}')
打印结果:
[[0 1 2 3 4]
[5 6 7 8 9]]
矩阵的对象类型:<class 'numpy.ndarray'>
矩阵的数据类型:int32
矩阵的元素总数:10
矩阵的维数:2
矩阵的形状:(2, 5)
打印的形状代表这是一个2行5列的矩阵。
指定存储的数据类型可以传入dtype参数:np.array([2,3,4],dtype=np.int64)
创建连续值的矩阵
与Python的range函数相同,NumPy也提供了arange函数,用来创建连续值的矩阵,但是是一维矩阵。
np.arange([start,] stop[, step,], dtype=None)
如果start和stop都指定,那么生成的值为左闭右开区间
arr = np.arange(0,10) print(arr)
打印结果:
[0 1 2 3 4 5 6 7 8 9]
如果只指定一个参数,那么即为stop,默认start为0
arr = np.arange(10) print(arr)
打印结果:
[0 1 2 3 4 5 6 7 8 9]
如果传入三个参数,那么第三个为步长
arr = np.arange(0,10,2) print(arr)
打印结果:
[0 2 4 6 8]
如果不想传入start也要指定步长
arr = np.arange(10,step=2) print(arr)
打印结果:
[0 2 4 6 8]
等差数列与等比数列
等差数列:np.linspace(start,stop,num=50,endpoint=True,retstep=False,dtype=None)
start:起始值
stop:结束值
num:生成数列个数,默认是50个
endpoint:如果为True,则最后一个元素包含在序列中,默认为True
retstep:如果为True,则返回等差间距,默认False
dtype:数据类型,自动推断,一般都会是浮点数
创建1-10之间12个等差数列
arr = np.linspace(1,10,12) print(arr)
打印结果:
[ 1. 1.81818182 2.63636364 3.45454545 4.27272727 5.09090909
5.90909091 6.72727273 7.54545455 8.36363636 9.18181818 10. ]
等比数列:np.logspace(start,stop,num=50,endpoint=True,base=10.0,dtype=None)
start:基底的start次幂
stop:基底的stop次幂
num:生成数列个数,默认是50个
endpoint:如果为True,则最后一个元素包含在序列中,默认为True
base:基底,默认以10为底
dtype:数据类型,自动推断,一般都会是浮点数
创建基底的1次方到基底的3次方的3个等比数列
arr = np.logspace(1,3,3) print(arr)
打印结果:
[ 10. 100. 1000.]
创建基底的1次方到基底的10次方的10个等比数列,设基底为2
arr = np.logspace(1,10,10,base=2) print(arr)
打印结果:
[ 2. 4. 8. 16. 32. 64. 128. 256. 512. 1024.]
创建特定形状的矩阵
全0矩阵
创建3行4列的全0矩阵
arr = np.zeros((3,4)) print(arr)
打印结果:
[[0. 0. 0. 0.]
[0. 0. 0. 0.]
[0. 0. 0. 0.]]
全1矩阵
创建3行4列的全1矩阵
arr = np.ones((3,4)) print(arr)
打印结果:
[[1. 1. 1. 1.]
[1. 1. 1. 1.]
[1. 1. 1. 1.]]
空矩阵
创建3行4列的空矩阵
arr = np.empty((3,4)) print(arr)
打印结果:
[[1.91409885e-233 1.78018403e-306 6.23057349e-307 1.06811422e-306]
[1.24610383e-306 1.69118108e-306 8.06632139e-308 1.20160711e-306]
[1.69119330e-306 1.29062229e-306 1.29060531e-306 2.16443571e-312]]
空矩阵中的元素内容并不为空,而是未经初始化的垃圾值,也就是随机产生的数据。
元素值相同的矩阵
创建3行4列元素值为9的矩阵
arr = np.full((3,4),9) print(arr)
打印结果:
[[9 9 9 9]
[9 9 9 9]
[9 9 9 9]]
仿维度创建矩阵
不管是zeros(),ones(),empty(),full(),都提供得有仿维度创建矩阵的函数,分别为zeros_like(),ones_like(),empty_like(),full_like(),用于创建出与其他矩阵相同维度的矩阵。
list2 = [[0,1,2,3,4],[5,6,7,8,9]] arr = np.zeros_like(list2) print(arr)
打印结果:
[[0 0 0 0 0]
[0 0 0 0 0]]
单位矩阵
生成4行4列的单位矩阵
arr = np.eye(4) print(arr)
打印结果:
[[1. 0. 0. 0.]
[0. 1. 0. 0.]
[0. 0. 1. 0.]
[0. 0. 0. 1.]]
对角矩阵
生成对角元素为1、2、3、4的对角矩阵
arr = np.diag([1,2,3,4]) print(arr)
打印结果:
[[1 0 0 0] [0 2 0 0] [0 0 3 0] [0 0 0 4]]
创建随机矩阵
生成0-1的随机数矩阵
生成0到1之间的3行3列随机矩阵
arr = np.random.random((3,3)) print(arr)
打印结果:
[[0.17461969 0.95103848 0.90655296]
[0.43783401 0.86078027 0.21500809]
[0.41657465 0.74977705 0.94805408]]
生成均匀分布的随机数
生成一个1-3之间的随机数
arr = np.random.uniform(1,3) print(arr)
打印结果:
1.719737091794529
生成12个1-3之间均匀分布的随机数
arr = np.random.uniform(1,3,12) print(arr)
打印结果:
[1.61483448 1.9048385 1.13600459 1.45937536 2.94301615 2.57079044
1.51789902 2.36870025 1.53805667 1.77119578 1.14710285 1.28136849]
生成一个3行3列的1-3之间均匀分布的随机数二维矩阵
arr = np.random.uniform(1,3,(3,3)) print(arr)
打印结果:
[[1.12853188 1.62992154 1.08904213]
[2.3179576 2.80127557 2.59765234]
[2.58337986 2.46281735 1.69915473]]
生成标准正态的随机数
生成一个3行3列的标准正态的随机数二维矩阵
arr = np.random.randn(3,3) print(arr)
打印结果:
[[-0.6659642 -0.14469211 -1.11157242] [-1.02770088 0.35732496 -0.74733868] [-2.30185962 0.05385927 -1.27661142]]
生成正态分布的随机数
本函数有3个参数:
第一个为正态分布的均值,也就是正态分布的中心对称点。
第二个为正态分布的标准差,标准差越大,图像越矮胖,标准差越小,图像越高瘦。
第三个为生成的矩阵形状。
生成以1为均值2为标准差的3个随机数
arr = np.random.normal(1,2,3) print(arr)
打印结果:
[0.13655215 4.1985189 2.63631302]
生成以1为均值3为标准差的3行3列的随机数矩阵
arr = np.random.normal(1,2,(3,3)) print(arr)
打印结果:
[[-0.94984175 0.9797389 -1.9574591 ]
[ 1.68702742 -0.1447021 0.80012014]
[-0.40085419 -1.56918216 -0.45392184]]
生成随机整数
生成3行3列0-10之间的随机整数矩阵
arr = np.random.randint(0,10,(3,3)) print(arr)
打印结果:
[[7 3 1]
[0 3 0]
[3 6 1]]
矩阵一般操作
矩阵截取
矩阵截取实际上就是融合了索引机制与切片机制,与list结构的截取用法一样。
生成一个5行5列的矩阵,作为本小节操作源。
np.random.seed(0) #设置随机数种子 让每次生成的随机数都相同 方便测试 arr = np.random.randint(0,10,(5,5)) print(arr)
打印结果:
[[5 0 3 3 7]
[9 3 5 2 4]
[7 6 8 8 1]
[6 7 7 8 1]
[5 9 8 9 4]]
截取矩阵第1行
a = arr[0] print(a)
打印结果:
[5 0 3 3 7]
截取矩阵最后一行
a = arr[-1] print(a)
打印结果:
[5 9 8 9 4]
截取矩阵最后两行
a = arr[-2:] print(a)
打印结果:
[[6 7 7 8 1]
[5 9 8 9 4]]
整个矩阵隔行截取
a = arr[0::2] print(a)
打印结果:
[[5 0 3 3 7]
[7 6 8 8 1]
[5 9 8 9 4]]
截取矩阵第2行的第3列
a = arr[1,2] print(a)
打印结果:
5
截取矩阵前两列
a = arr[:,0:2] print(a)
打印结果:
[[5 0]
[9 3]
[7 6]
[6 7]
[5 9]]
按条件截取
依然生成一个5行5列的矩阵,作为本小节操作源。
np.random.seed(0) #设置随机数种子 让每次生成的随机数都相同 方便测试 arr = np.random.randint(0,10,(5,5)) print(arr)
打印结果:
[[5 0 3 3 7]
[9 3 5 2 4]
[7 6 8 8 1]
[6 7 7 8 1]
[5 9 8 9 4]]
以大于5为条件转布尔值矩阵
a = arr > 5
print(a)
打印结果:
[[False False False False True]
[ True False False False False]
[ True True True True False]
[ True True True True False]
[False True True True False]]
找出所有大于5的数
a = arr[arr > 5] print(a)
打印结果:
[7 9 7 6 8 8 6 7 7 8 9 8 9]
矩阵中小于等于5的值置为0,其他不变
arr[arr <= 5] = 0 print(arr)
打印结果:
[[0 0 0 0 7]
[9 0 0 0 0]
[7 6 8 8 0]
[6 7 7 8 0]
[0 9 8 9 0]]
矩阵合并
生成两个一样的矩阵,作为本小节的示例源。
np.random.seed(0) arr1 = arr2 = np.random.randint(0,10,(2,2)) print(arr1)
打印结果:
[[5 0]
[3 3]]
矩阵拉直合并
arr3 = np.append(arr1,arr2) print(arr3)
打印结果:
[5 0 3 3 5 0 3 3]
矩阵横向合并
arr3 = np.hstack([arr1,arr2]) print(arr3)
打印结果:
[[5 0 5 0]
[3 3 3 3]]
矩阵纵向合并
arr3 = np.vstack([arr1,arr2]) print(arr3)
打印结果:
[[5 0]
[3 3]
[5 0]
[3 3]]
矩阵运算
普通运算
普通运算有如下几种:
加法 + 矩阵各元素对应相加
减法 - 矩阵各元素对应相减
乘法 * 矩阵各元素对应相乘
除法 / 矩阵各元素对应相除
取余 % 矩阵各元素对应相除后取余
幂运算 ** 矩阵各元素对应幂运算
创建一个3行3列的矩阵,用来作为本小节的操作源。
np.random.seed(0) arr1 = np.random.randint(0,10,(3,3)) print(arr1)
打印结果:
[[5 0 3]
[3 7 9]
[3 5 2]]
加法
arr2 = arr1 + 10
print(arr2)
打印结果:
[[15 10 13]
[13 17 19]
[13 15 12]]
平方
arr2 = arr1 ** 2
print(arr2)
打印结果:
[[25 0 9]
[ 9 49 81]
[ 9 25 4]]
矩阵乘法
矩阵乘法要满足矩阵乘法的条件:第一个矩阵的列数要等于第二个矩阵的行数才可以进行乘法计算
计算规则是,第一个矩阵的每行的每个数字与第二个矩阵的每列的每个数字对应相乘再相加,计算结果是第一个矩阵的行数第二个矩阵的列数所对应的值。
比如矩阵A:
2 3
4 5
矩阵B:
1 2
3 4
AB两矩阵相乘,得到新矩阵C
C11:2*1 + 3*3 = 11
C12:2*2 + 3*4 = 16
C21:4*1 + 5*3 = 19
C22:4*2 + 5*4 = 28
也就是:
11 16
19 28
arr1 = np.array([[2,3],[4,5]]) print(arr1) arr2 = np.array([[1,2],[3,4]]) print(arr2) arr3 = np.dot(arr1,arr2) print(arr3)
打印结果:
[[2 3] [4 5]] [[1 2] [3 4]] [[11 16] [19 28]]
矩阵转置
np.transpose和arr.T效果相同,只适用于一维矩阵和二维矩阵。
arr = np.random.randint(1,10,(3,3)) print(arr) print(np.transpose(arr)) print(arr.T)
打印结果:
[[9 7 5]
[1 9 6]
[3 3 4]]
[[9 1 3]
[7 9 3]
[5 6 4]]
[[9 1 3]
[7 9 3]
[5 6 4]]
最大最小值
最大值函数为np.amax(),最小值函数为np.amin(),使用方法一模一样,再次只演示最大值。
求矩阵最大值
arr = np.array([[0,1,2,3,4],[5,6,7,8,9]]) print(arr) print(np.amax(arr))
打印结果:
[[0 1 2 3 4]
[5 6 7 8 9]]
9
求每行的最大值
arr = np.array([[0,1,2,3,4],[5,6,7,8,9]]) print(arr) print(np.amax(arr,axis=1))
打印结果:
[[0 1 2 3 4]
[5 6 7 8 9]]
[4 9]
求每列的最大值
arr = np.array([[0,1,2,3,4],[5,6,7,8,9]]) print(arr) print(np.amax(arr,axis=0))
打印结果:
[[0 1 2 3 4]
[5 6 7 8 9]]
[5 6 7 8 9]
计算均值
arr = np.array([[0,1,2,3,4],[5,6,7,8,9]]) print(arr) print(np.mean(arr))
打印结果:
[[0 1 2 3 4]
[5 6 7 8 9]]
4.5
计算中位数
arr = np.array([[0,1,2,3,4],[5,6,7,8,9]]) print(arr) print(np.median(arr))
打印结果:
[[0 1 2 3 4]
[5 6 7 8 9]]
4.5
计算标准差
arr = np.array([[0,1,2,3,4],[5,6,7,8,9]]) print(arr) print(np.std(arr))
打印结果:
[[0 1 2 3 4]
[5 6 7 8 9]]
2.8722813232690143
计算方差
arr = np.array([[0,1,2,3,4],[5,6,7,8,9]]) print(arr) print(np.var(arr))
打印结果:
[[0 1 2 3 4]
[5 6 7 8 9]]
8.25
持久化存储
保存为二进制文件
arr = np.array([[0,1,2,3,4],[5,6,7,8,9]]) np.save('binary',arr) z = np.load('binary.npy') print(z)
打印结果:
[[0 1 2 3 4]
[5 6 7 8 9]]
np.save方法如果指定的文件名不是.npy后缀的话,会自动追加.npy后缀。
np.save方法可以保存任何维度的矩阵。
保存为txt文件
arr = np.array([[0,1,2,3,4],[5,6,7,8,9]]) np.savetxt('a.txt',arr,fmt="%d") z = np.loadtxt('a.txt') print(z)
打印结果:
[[0. 1. 2. 3. 4.]
[5. 6. 7. 8. 9.]]
np.savetxt方法只能保存一维或二维矩阵。
np.savetxt方法的fmt参数需要指定存储数据格式,不指定的话默认是保留18位小数点的浮点数。存储整数用fmt="%d",保留4位小数点用fmt="%0.4f",保存字符串用fmt='%s'。
np.savetxt方法还可以传入header参数和footer参数,用于添加文件头部和尾部的注释信息。
np.loadtxt方法读取文件默认接收为浮点数格式,可以使用dtype参数指定格式。
保存为csv文件
arr = np.array([[0,1,2,3,4],[5,6,7,8,9]]) np.savetxt('a.csv',arr,fmt="%d",delimiter=',') z = np.loadtxt('a.csv',delimiter=',') print(z)
打印结果:
[[0. 1. 2. 3. 4.]
[5. 6. 7. 8. 9.]]
保存为csv文件依然还是使用np.savetxt方法,只不过添加一个delimiter参数,指明每个数据之间以逗号分隔。