飞桨AI课程中附录《Numpy简介》的笔记,非常简明地给本小白上了一课所以做了笔记,方便自己查看。不过用惯了语雀的折叠块后看优快云的md文档总觉得缺点啥。。所以也贴一个语雀的传送门好了 Numpy简介
Numpy基础功能:
- ndarray数组:具有矢量算术运算和复杂广播能力的多维数组,特点是快速且节省空间;
- 拥有对整组数据进行快速运算的标准数学函数(无需循环);
- 具有线性代数、随机数生成、傅里叶变换功能;
- 可读写磁盘数据、操作内存映射文件。
感觉正确理解使用这个包的前提是知道向量加减乘除应是什么结果。
举个栗子:从成都飞东京=从成都飞北京+从成都飞南京
什么两面包夹芝士!
简单粗暴的,这里放一个相对可信的学习链接:向量的加减
1. ndarray数组
1.1 为什么引入ndarray数组
- 其数组中所有元素的数据类型相同、数据地址连续、批量操作数组元素时速度更快
- 支持广播机制,矩阵运算无需for循环
- 底层使用C语言编写,内置并行计算功能,运行速度快于python
向量的加减示例
# 实现a+1的计算(数组内全部+1)
import numpy as np
a = np.array([1,2,3,4,5])
a = a + 1
print(a)
# a = array([2,3,4,5,6])
# 实现c=a+b的计算(两数组的对应位置相加)
a = [1,2,3,4,5]
b = [2,3,4,5,6]
import numpy as np
a = np.array([1,2,3,4,5])
b = np.array([2,3,4,5,6])
c = a + b
print(c)
# c = array([3,5,7,9,11])
关于广播机制:其会按一定规则自动对数组的维度进行扩展以完成计算。
1.2 创建ndarray数组
可用四个函数进行创建:array
、arange
、zeros
、ones
array:创建嵌套序列并转换为一个多维数组
# array
import numpy as np
a = [1,2,3,4,5]
b = np.array(a)
# b = array([1,2,3,4,5])
arange:创建元素从0到10依次递增2的数组
# arange
a = np.arange(0,10,2)
# a = array([0,2,4,6,8])
# zeros:创建指定长度或形状的全0数组。
a = np.zeros([3,3])
# a = array([0.,0.,0.],
# [0.,0.,0.],
# [0.,0.,0.])
# ones:创建指定长度或形状的全1数组。
a = np.ones([3,3])
# a = array([1.,1.,1.],
# [1.,1.,1.],
# [1.,1.,1.])
1.3 查看ndarray数组的属性
属性包括shapedtypesizendim等。
- shape:数组形状,
- dtype:数组中的数据类型
- size:数组中包含的元素个数 ndarray.size,其大小等于各个维度的长度的乘积
- ndim:数组的维度大小,ndarray.ndim,其大小等于ndarray.shape所含元素的个数
a = np.ones([3, 3])
print('a, dtype: {}, shape: {}, size: {}, ndim: {}'.format(a.dtype, a.shape, a.size, a.ndim))
# float64, (3,3), 9, 2
1.4 改变ndarray数组的数据类型和形状
# 改变数据类型
d = a.astype(np.int64)
# 改变形状
c = a.reshape([1,9])
1.5 ndarray数组的基本运算
1. 标量与 ndarray 数组之间的运算(加减乘除)
# 与标量的除等于用标量除以数组的每一个元素
arr = np.array([[1.,2.,3.],[4.,5.,6.]])
1.0 * arr
# array([1., 0.5, 0.333333,],
# [0.25, 0.2, 0.1666667])
# 与标量的乘等于标量乘以数组的每一个元素
arr = np.array([1.,2.,3.],[4.,5.,6.])
2.0 * arr
# array([[2.,4.,6.,],
# [8.,10.,12.]])
# 与标量的加等于标量加上数组的每一个元素
arr = np.array([1.,2.,3.],[4.,5.,6.])
2.0 + arr
# array([[3.,4.,5.],
# [6.,7.,8.]])
# 与标量的减等于标量减去数组的每一个元素
arr = np.array([1.,2.,3.],[4.,5.,6.])
2.0 - arr
array([[1.,0.,-1.],
[-2.,-3.,-4.]])
2. 两个ndarray数组之间的运算(加减乘除+开根号)
# 数组相减等于对应位置的元素相减
arr1 = np.array([[1.,2.,3.],[4.,5.,6.]])
arr2 = np.array([[11.,12.,13.],[21.,22.,23.]])
arr1 - arr2
# array([[-10.,-10.,10.],
# [-17.,-17.,-17.]])
# 数组相加等于对应位置的元素相加
arr1 = np.array([[1.,2.,3.],[4.,5.,6.]])
arr2 = np.array([[11.,12.,13.],[21.,22.,23.]])
arr1 + arr2
# array([[11.,24.,39.],
# [84.,110.,138.]])
# 数组相乘等于对应位置的元素相乘
arr1 * arr2
# array([[11.,24.,39.],
# [84.,110.,138.]])
# 数组相除等于对应位置的元素相除
arr1 / arr2
# array([[0.09090909, 0.16666667, 0.23076923],
# [0.19047619, 0.22727273, 0.26086957]])
# 数组开根号等于每个位置的元素都开根号
arr ** 0.5
# array([[1. , 1.41421356, 1.73205081],
# [2. , 2.23606798, 2.44948974]])
1.6 ndarray数组的索引和切片
访问或修改某个位置:索引
访问或修改某个区域:切片
关键词:[-n,n-1]、slice函数、start,stop,step
1. 一维ndarray数组的索引和切片
- 数组切片产生的新数组仍然指向原来的内存区域
- 数据不会被复制
- 视图上的任何修改都会直接反映到源数组上
- 将一个标量赋值给切片时,会自动传播到整个选区
a = np.arrange(30)
a[10]
# 10
b = a[4:7]
# b = array([4,5,6])
a[4:7] = 10
# a = array([0,1,2,3,10,10,10,7,8,...29])
arr_slice = a[4:7]
arr_slice[0] = 100
# a = array([0,1,2,3,100,5,6,...29])
# arr_slice = array([100,5,6])
如果要使新数组拥有独立的内存空间,要使用copy
a = np.arange(30)
arr_slice = a[4:7]
arr_slice = np.copy(arr_slice)
arr_slice[0] = 100
# a = array([0,1,2,...,29])
# arr_slice = array([100,5,6])
2. 多维ndarray数组的索引和切片
特点
- 各索引位置上的元素不再是标量而是多维数组
- 以逗号隔开的索引列表来选取单个元素
- 若省略后面的索引,则返回对象会是一个维度低一点的ndarray
a = np.arange(30)
arr3d = a.reshape(5, 3, 2)
# 可简单理解为将一维数组里的30个数字分为5排含3组每组含2数的排布。
arr3d = array([[[ 0, 1],[ 2, 3],[ 4, 5]],
[[ 6, 7],[ 8, 9],[10, 11]],
[[12, 13],[14, 15],[16, 17]],
[[18, 19],[20, 21],[22, 23]],
[[24, 25],[26, 27],[28, 29]]])
# 仅一个索引指标时,会在第0维索引,后面的维度保持不变
arr3d[0] = array([[0,1],[2,3],[4,5]])
# 两个索引时(单独式)
arr3d[0][1] = array([2,3])
# 两个索引时(区间式)
arr3d[0, 1] = array([2,3])
# ---------------------
# 切片
a = np.arange(24)
a = a.reshape([6,4])
# a 变形为 6 行 4 列的数组
[k for k in range(0,6,2)]
# [0,2,4]
slices = [a[k:k+2] for k in range(0,6,2)]
1.7 ndarray数组的统计方法
- mean:平均数
- std和var:标准差与方差
- sum:求和
- max和min:极大值,极小值
- argmax和argmin:极大值的索引,极小值的索引
- cumsum:所有元素的累加和
- cumprod:所有元素的累乘积
以上方法中可使用参数如axis指定行,可以具体到使用时查看对应api
2. 随机数np.random
2.1 创建随机 ndarry 数组
含三部分内容
- 随机数种子(一个种子跟一个随机数,一次一用,下次无效)
np.random.seed(10)
a = np.random.rand(3,3)
以上两行代码若同时选中再执行,就会出现与上一次执行相同的结果,如果去掉seed,则每次执行结果都会不一致。
在以上两行之后,若未再设置seed就执行rand,则该次rand生成的随机数也会每次都不一致。
- 均匀分布(指定取值范围与数组形状)
np.random.uniform(low = -1.0, high = 1.0, size=(2, 2)
- 正态分布(指定均值 loc 和方差 scale)
np.random.normal(loc = 1.0, scale = 1.0, size = (3, 3))
2.2 随机打乱ndarray数组顺序
随机打乱一维ndarray数组顺序
np.random.shuffle(a)
随机打乱二维ndarray数组顺序,则仅打乱行顺序,可理解为多维数组内最外层的数组才会打乱排序
2.3 随机选取元素
np.random.choice(a, size=5)
3. 线性代数
线性代数的矩阵乘法、矩阵分解、行列式以及其他方阵数学等是任何数组库的重要组成部分。在 numpy 中集成于 numpy.linalg 模块。常见使用有以下函数:
- diag:以一维数组的形式返回方阵的对角线或非对角线元素,或将一维数组转换为方阵(非对角线元素为0)
- dot:矩阵乘法
- trace:计算对角线元素的和
- det:计算矩阵行列式
- eig:计算方阵的特征值和特征向量
- inv:计算方阵的逆
dot 矩阵乘法
设矩阵 a 和 b ,b的第二维大小必须等于a的第一维大小
a = np.arange(12)
b = a.reshape([3,4])
c = a.reshape([4,3])
d = b.dot(c)
diag 转对角线元素
e = np.diag(d)
f = np.diag(e)
trace 计算对角线元素的和
g = np.trace(d)
g=440
det 计算行列式
h = np.linalg.det(d)
eig 计算特征值和特征向量
i = np.linalg.eig(d)
inv 计算方阵的逆
tmp = np.random.rand(3,3)
j = np.linalg.inv(tmp)
4. Numpy保存和导入文件
4.1 文件读写
d = np.fromfile(filepath,sep='分隔符')
d 是np数组
4.2 文件保存
np.save('文件名', 数据对象)#数组将直接保存为npy后缀的文件
b = np.load('文件名')#从磁盘文件读入数据
check = (a == b).all()#检查读取的文件与原始数据对象 a 是否一致