当前位置:好爆料新闻网 >> 企业爆料 >> 从图片中学习NumPy:掌握N维数组的基本知识点 看这一本就够了
从图片中学习NumPy:掌握N维数组的基本知识点 看这一本就够了
小茶整理整理
量子报告| QbitAI,微信官方账号
NumPy是Python最重要的扩展库之一,也是机器学习编程入门的必备工具。但是对于初学者来说,NumPy的无数算术方法是非常难记的。
最近有个外国程序员说NumPy的基本操作是图形化写下来的,学习过程轻松有趣。在Reddit机器学习社区发布后,不到半天就获得了500个赞。
让我们一起学习他的教程。
教程的内容分为三个部分:向量(一维数组)、矩阵(二维数组)和三维与更高维数组.
Numpy数组和Python列表
在介绍正式内容之前,我们先来了解一下Numpy数组和Python列表的区别。
乍一看,NumPy数组类似于Python列表。它们都可以作为容器使用,具有获取和设置元素以及插入和移除元素的功能。
它们之间有许多相似之处,下面是它们操作的一个例子:
与Python列表相比,Numpy数组具有以下特点:
更紧凑的,尤指在不止一个维度上;矢量化比Python列表快,但是在末尾添加元素比Python列表慢。
当在末尾添加元素时,Python列表复杂度为O(1),NumPy复杂度为O(N)向量运算向量初始化
创建NumPy数组的一种方法是直接从Python列表中转换它们,数组元素的类型与列表元素的类型相同。
NumPy数组不能像Python列表那样加长,因为数组末尾没有保留空间。
因此,通常的做法是定义一个Python列表,对其进行操作,然后将其转换为NumPy数组,或者用np.zeros和np.empty,初始化该数组,并预先分配必要的空间:
有时我们需要创建一个与现有数组大小和元素类型相同的空数组:
事实上,用常量填充创建的数组的所有函数都有一个_like对应项来创建相同类型的常量数组:
在NumPy中,可以用arange或linspace:初始化单调序列数组
如果需要像[0]这样的浮点数组。 1. 2.],可以更改阿兰格的输出类型:阿兰格(3)。astype(float)。
但是有更好的办法:arange函数对数据类型敏感,如果取整数作为参数,则生成整数数组;如果一个浮点数(比如arange(3。))时,生成一个浮点数组。
但是阿兰格并不特别擅长处理浮点数:
这是因为0.1对我们来说是有限的十进制数,而对计算机来说不是。在二进制中,0.1是无限小数,必须在某处截断。
这就是为什么在步长中添加小数部分通常是一种糟糕的方式:我们可能会遇到一个错误,这导致数组中的元素数量不是我们想要的,这将降低代码的可读性和可维护性。
到时候,linspace就派上用场了。它不受舍入误差的影响,并且总是生成所需数量的元素。
出于测试目的,通常需要生成随机数组。NumPy提供了随机整数、均匀分布、正态分布等几种随机数:
向量索引
一旦数据存储在数组中,NumPy提供了一种简单的方法来获取它:
上面显示了各种索引,比如取出特定的区间,从右向左索引,只取出奇数位等等。
但都是所谓的视图,就是不存储原始数据。而如果原数组在被索引后发生了变化,则原数组的变化不会得到反映。
这些索引方法允许您分配和修改原始数组的内容,因此应该注意,只有下面的最后一种方法是复制数组,其他方法可能会破坏原始数据:
从NumPy数组中获取数据的另一种非常有用的方法是布尔索引,它允许各种逻辑运算符检索合格的元素:
注意:Python中的三进制比较3=a=5在NumPy数组中不起作用。
如上所述,布尔索引也会覆盖数组。它有两个共同的功能,即np.where和np.clip:
向量运算
算术运算是NumPy速度最引人注目的地方之一。NumPy的向量运算符已经到了C级,避免了Python的慢循环。
NumPy允许像普通数字一样操作整个数组(加法、减法、乘法、除法、整数除法、幂):
在,和Python一样,a//b代表div b,x**n代表x
向量也可以用与标量类似的方式操作:
大多数数学函数都有用于处理向量的NumPy对应物:
向量的点积和叉积也有运算符:
我们还可以执行三角函数、反三角函数和斜边计算:
数组可以四舍五入为整数:
楼层下限;Ceil取上界;四个房子,六进五,也要一轮
NumPy还可以执行以下基本统计操作(最大/最小、平均值、方差、标准差):
但是,排序功能比Python列表功能少:
搜索向量中的元素
与Python列表不同,NumPy数组没有索引方法。
查找元素的一种方法是np.where(a==x)[0][0],这既不优雅也不快速,因为要查找的项需要从头遍历数组的所有元素。
更快的方法是加速到下一个((I [0]对于NP中的I,v。nd enumerate (a) if v==x),-1) in Numba。
数组一旦排序,情况会变好:v=np.searchsorted(a,x);返回v的复杂度如果a[v]==x else -1是O(log N),真的很快,但是首先需要O(N log N)的排序时间。
比较浮点数
np.allclose(a, b)函数用于比较给定容差下的浮点数:
Np.allclose假设所有比较数的秩为1个单位。比如上图,它认为1e-9和2e-9是一样的。如果要做更详细的比较,需要通过环礁:NP指定比较级别1。Allclose (1e-9,2e-9,环礁==false。
Math.isclose没有任何假设,而是基于用户给出的一个合理的abs_tol值:Math。is close(0 . 10 . 20.3,ABS _ tol=1e-8)=true。
另外,np.allclose在绝对和相对容差公式上有一些小问题,比如有些数字有allclose(a,b)!=allclose(b,a).这些问题已经在数学中解决了。
矩阵运算
NumPy中曾经有一个特殊的类矩阵,现在已经废弃了,所以下面会交替使用矩阵和2D阵这两个词。
矩阵初始化语法类似于向量:
这里需要双括号,因为第二个位置参数是为dtype保留的。
随机矩阵的生成类似于向量的生成:
二维索引语法比嵌套列表更方便:
与一维数组一样,上面的视图显示切片数组实际上没有被复制。修改阵列后,更改也将反映在切片中。
轴参数
在很多运算中(比如求和),我们需要告诉NumPy是跨行还是跨列运算。为了使用任何维度的一般表示,NumPy引入了axis:的概念,轴参数实际上是所讨论的索引的数量:第一个索引是轴=0,第二个索引是轴=1,以此类推。
因此,在二维数组中,如果axis=0是按列,那么axis=1是按行。
矩阵运算
除了普通运算符(如-、*、/、//和* *)之外,还有一个计算矩阵乘积的@运算符:
第一部分,我们已经看到了矢量积的运算。NumPy允许向量和矩阵之间甚至两个向量之间的元素混合操作:
行向量和列向量
从上面的例子可以看出,在二维数组中,行向量和列向量被不同地处理。
默认情况下,一维数组在二维操作中被视为行向量。所以矩阵乘以行向量时,可以用(n,),或者(1,n),结果也是一样的。
如果需要列向量,可以使用转置方法对其进行操作:
可以从一维数组生成二进制数组列向量的两个操作是使用reshape重排和newaxis:命令创建新索引
此处的-1参数表示整形会自动计算第二维的数组长度,而无作为方括号中np.newaxis的快捷方式,在指定位置添加一个空轴。
因此,NumPy中有三种类型的向量:一维数组、二维行向量和二维列向量。这是两者之间显式转换的示意图:
根据规则,一维数组隐式解释为二维行向量,所以通常不需要在两个数组之间进行转换,对应的区域用灰色标注。
矩阵运算
连接矩阵有两个主要功能:
这两个函数在只叠加矩阵或向量时可以正常工作。但是,当涉及一维数组和矩阵的混合叠加时,vstack可以正常工作:hstack会有尺寸失配误差。
因为,如上所述,一维数组被解释为行向量而不是列向量。解决方法是将其转换为列向量,或者使用column_stack将其自动化:
堆叠的反向操作是拆分:
矩阵有两种复制方式:tile类似于复制粘贴,repeat类似于页面打印。
可以用delete:删除特定的列和行
反向操作是插入:
Append就像hstack一样,这个函数不能自动转置一维数组,所以需要再次转置或者给向量加上长度,或者用column_stack来代替:
事实上,如果我们需要做的只是在数组的边界上添加常量,那么pad函数就足够了:
网格
如果我们想要创建以下矩阵:
这两种方法都很慢,因为它们使用Python循环。在MATLAB中处理这类问题的方法是创建一个meshgrid:
meshgrid函数接受任何一组索引,mgrid只是一个切片,索引只能生成一个完整的索引范围。如上所述,提供的函数只使用I和J参数调用一次。
但其实NumPy还有更好的办法。不需要消耗整个矩阵上的存储空间。只存储正确大小的向量就够了,操作规则会处理剩下的:
没有索引='ij '参数,meshgrid会改变参数的顺序:j J,I=np.meshgrid(j,i)— j,I)-这是一个“xy”模式,用来可视化三维图像。
除了在2d或3d阵列上初始化之外,meshgrid还可用于索引阵列:
矩阵统计
就像前面提到的统计函数,接收到轴参数后,2D阵列会进行相应的统计运算:
在二维和更高维中,argmin和argmax函数返回最大值和最小值的索引:
轴参数也可由所有和任何功能使用:
矩阵排序
虽然轴参数对上面列出的函数很有用,但对二维排序没有帮助:
Axis绝不是Python列表关键参数的替代品。但是,NumPy有几个允许按列排序的功能:
1.根据第一列对数组进行排序:a[a[:0]。argsort]
argsort排序后,在此返回原始数组的索引数组。
这种方法可以重复,但必须注意避免下一个排序混淆前一个排序的结果:
a=a[a[:2]。argsort]
a=a[a[:1]。argsort(kind='stable')]
a=a[a[:0]。argsort(kind='stable')]
2.有一个辅助函数lexsort,它以上述方式对所有可用的列进行排序,但总是根据行执行它们,例如:
a【NP。lexsort (NP。flipud (a [2,5]。t)]:先按第二列排序,再按第五列排序;
A[np.lexsort(np.flipud(a.T))]:按从左到右的所有列排序。
3.还有一个参数顺序,但是如果从一个普通的(非结构化的)数组开始,既不快速也不容易使用。
4.因为这种特殊的操作模式可读性更强,可能是更好的选择,熊猫不容易出错:
警局。数据帧(a)。sort _ values (by=[2,5])。to _ numpy:按第2列排序,然后按第5列排序。
Pd.dataframe (a)。sort _ values.to _ numpy:按从左到右的所有列排序
高维数组运算
当通过重新排列一维向量或转换嵌套的Python列表来创建3D数组时,索引意味着(z,y,x)。
第一个指标是飞机的编号,然后是飞机上的运动:
这个索引顺序很方便,例如,保存一堆灰色图像:这个a[i]是引用ith图像的快捷方式。
然而,这种索引顺序并不具有普遍性。在处理RGB图像时,通常使用(y,x,z)的顺序:前两个是像素坐标,最后一个是颜色坐标(Matplotlib中的RGB和OpenCV中的BGR):
这样就可以方便地引用一个特定的像素:a[i,j]给出像素的RGB元组(I,j)。
因此,创建特定几何图形的实际命令取决于正在处理的域的约定:
显然,像hstack、vstack或dstack这样的NumPy函数并不知道这些约定。其中硬编码索引顺序为(y,x,z),RGB图像顺序为:
的RGB图像阵列(为简单起见,上图只有2种颜色)
如果数据布局不同,使用concatenate命令堆叠图像并在轴参数中提供显式索引号会更方便:
如果使用axis不方便,可以将数组转换成hstack的形式:
这种转换不会随着实际的复制而发生。它只是混合了索引的顺序。
混合索引顺序的另一种操作是数组转置。检查它可能会让我们更熟悉3D阵列。
根据我们决定的轴顺序,实际用于置换阵列所有平面的命令将会不同:对于一般阵列,它交换索引1和2,对于RGB图像,它交换索引0和1:
有趣的是,(也是唯一的操作模式)默认轴参数颠倒了索引顺序,这与上述两种索引顺序约定不一致。
最后还有一个功能,可以节省大量Python循环,在处理多维数组时,可以让代码更加简洁。这是爱因斯坦的求和函数einsum:
它沿着重复的索引对数组求和。
最后,如果你想掌握NumPy,可以去GitHub上的项目——100道NumPy练习题验证你的学习成绩。
原始链接:
https://medium.com/better-programming/numpy-pictured-the-visual-guide-to-numpy-3b1 d 4976 de 1d
100个NumPy练习:
https://github.com/rougier/numpy-100
——完——
本文是网易新闻网易特别内容奖励计划签约账号【qubit】的原创内容,未经账号授权,禁止随意转载。
AI落地最佳参考!
2020中国人工智能年度评选结果揭晓
12月16日,在qubit MEET 2021 Smart Future Conference上,50家领先企业、10家明星创业公司、30位商业领袖、10款最佳产品、10款最佳解决方案、5款社会责任模式、5款最佳技术社区等年度奖项全部揭晓。
点击图片查看完整列表:
量子位 QBITAI标题签名作者
跟踪人工智能技术和产品的新发展
一键三环“分享”“喜欢”“观看”
科技前沿的进步天天见面~