百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分类 > 正文

NumPy视觉指南

ztj100 2025-01-05 01:00 13 浏览 0 评论

从头开始学习NumPy


NumPy是一个基本库,受(PyTorch)的启发,大多数广泛使用的Python数据处理库都是基于(pandas)构建的,或者可以与(TensorFlow,Keras等)有效地共享数据。了解NumPy的工作方式也可以提高您在这些库中的技能。也可以在GPU1上不做任何改动或进行最少改动即可运行NumPy代码。

NumPy的中心概念是n维数组。这样做的好处是,不管数组有多少维,大多数操作看起来都是一样的。但是一维和二维情况有些特殊。本文包括三个部分:

· 向量,一维数组

· 矩阵,二维数组

· 3D以上

我从JayAlammar2撰写了一篇很棒的文章" NumPy的视觉介绍"作为起点,大大扩展了其覆盖范围,并修改了一些细微差别。

Numpy数组与Python列表

乍一看,NumPy数组类似于Python列表。它们都可以用作容器,具有快速获取和设置项目以及较慢地插入和移除元素的功能。

NumPy数组拍子列表的简化示例是算术运算:

除此之外,NumPy数组是:

· 更紧凑,尤其是在一个以上的维度上

· 可以向量化操作时比列表快

· 将元素追加到末尾比列表慢

· 通常是同质的:只能快速处理一种类型的元素

这里的O(N)表示完成操作所需的时间与数组的大小成正比(请参见Big-O备忘单3网站),以及O *(1)(即所谓的"摊销"的O(1)))表示时间通常不取决于数组的大小(请参见Python时间复杂度wiki页面)

1.向量,一维数组

向量初始化

创建NumPy数组的一种方法是转换Python列表。该类型将从列表元素类型中自动推导:

确保输入同质的列表,否则您将得到dtype ='object',它会消除速度,只保留NumPy中包含的语法糖。

NumPy数组无法像Python列表那样增长:在数组末尾没有保留空间以方便快速追加。因此,通常的做法是增长一个Python列表,并在准备就绪时将其转换为NumPy数组,或者使用np.zeros或np.empty预先分配必要的空间:

通常需要创建一个空数组,以形状和元素类型匹配现有数组:

实际上,所有创建用常量值填充的数组的函数都具有_like对应项:

NumPy中有多达两个函数用于具有单调序列的数组初始化:

如果您需要类似[0.,1.,2.]的浮点数组,则可以更改arange输出的类型:arange(3).astype(float),但是有更好的方法。arange函数对类型敏感:如果将int作为参数输入,它将生成int,并且如果输入浮点数(例如arange(3。)),则将生成浮点数。

但是arange在处理浮点数方面并不是特别擅长:

这个0.1对我们来说似乎是一个有限的十进制数,但对计算机而言却不是:二进制,它是一个无穷小数,必须四舍五入到一个错误的地方。这就是为什么将小数部分加到范围的步通常不是一个好主意:您可能会遇到一个错误的错误。您可以使间隔的末尾落入非整数步数(解决方案1),但这会降低可读性和可维护性。这是linspace派上用场的地方。它不受舍入错误的影响,并始终生成您要求的元素数量。但是,linspace有一个常见的陷阱。它计算点,而不是间隔,因此最后一个参数始终是您通常会想到的加一个。因此它是11,而不是上面示例中的10。

为了进行测试,通常需要生成随机数组:

向量索引

一旦将数据存储在数组中,NumPy便会出色地提供简单的方法来将其取回:

除花式索引外,以上介绍的所有索引方法实际上都是所谓的"视图":它们不存储数据,并且如果原始数组在被索引后发生更改,则不会反映原始数组中的更改。

所有这些方法,包括花式索引,都是可变的:如上所述,它们允许通过分配来修改原始数组的内容。此功能通过切片来打破复制数组的习惯:

从NumPy数组中获取数据的另一种超级有用的方法是布尔索引,它允许使用各种逻辑运算符:


小心点;3 <= a <= 5之类的Python"三元"比较在这里不起作用。

如上所述,布尔索引也是可写的。它有两个常见的用例,它们是专用功能:过度重载的np.where函数(请参阅下面的两种含义)和np.clip。

向量运算

算术是NumPy速度最耀眼的地方之一。向量运算符已转移到c ++级别,使我们避免了慢Python循环的代价。NumPy允许像普通数字一样操作整个数组:

将加法或减法将int提升为浮点数的方式相同,将标量提升(也称为广播)至数组:

大多数数学函数都有NumPy对应项,可以处理矢量:

标量产品具有自己的运算符:

您也不需要三角函数的循环:

数组可以四舍五入为一个整体:


名称np.around只是引入的np.round的别名,以避免从numpy import *写入时遮盖Python的回合(而不是更常见的导入numpy作为np)。您也可以使用a.round()。

NumPy还可以执行以下基本统计信息:


排序功能比Python对应功能具有更少的功能:

在一维情况下,可以通过反转结果来轻松地补偿反向关键字的缺失。在2D中,它有些棘手(功能要求?)。

搜索向量中的元素

与Python列表相反,NumPy数组没有索引方法。相应的功能请求?已经悬挂了一段时间。


· 查找元素的一种方法是np.where(a == x)[0] [0],它既不优雅也不快速,因为它需要遍历数组的所有元素,即使要查找的项位于开始。

· 一种更快的方法是使用Numba?加速next((i的i [0],np中的v.ndenumerate(a),如果v == x),-1)(否则,在最坏的情况下,它的速度比)。

· 一旦对数组进行排序,情况就会变得更好:v = np.searchsorted(a,x);如果a [v] == x,则返回v,否则-1的复杂度为O(log N)确实非常快,但首先需要O(N log N)的时间才能排序。

实际上,通过在C中实现搜索来加速搜索不是问题。问题是浮点比较。这是一项对于任意数据开箱即用的工作。

比较浮点数

函数np.allclose(a,b)比较具有给定公差的浮点数组


· np.allclose假定所有比较数字的典型比例为1。例如,如果使用纳秒,则需要将默认atol参数值除以1e9:np.allclose(1e-9,2e-9,atol = 1e-17)== False。

· math.isclose不对要比较的数字做任何假设,而是依靠用户提供一个合理的abs_tol值(采用默认的np.allclose atol值1e-8足以满足典型小数位数为1的数字):math.isclose(0.1 + 0.2–0.3,abs_tol = 1e-8)==真。

除此之外,np.allclose在绝对和相对公差的公式中还有一些小问题,例如,对于某些a,b allclose(a,b)!= allclose(b,a)。这些问题已在(标量)函数math.isclose中解决(稍后介绍)。要了解更多信息,请查看GitHub上出色的浮点指南?和相应的NumPy问题?。

2.矩阵,二维数组

NumPy中曾经有一个专用的矩阵类,但现在已弃用,因此我将交替使用矩阵和2D数组一词。

矩阵初始化语法与向量相似:

这里需要双括号,因为第二个位置参数是为(可选)dtype(它也接受整数)保留的。

随机矩阵的生成也类似于矢量的生成:

二维索引语法比嵌套列表更方便:

"视图"符号表示切片数组时实际上并未进行任何复制。修改数组后,更改也将反映在切片中。

轴参数

在许多操作(例如,求和)中,您需要告诉NumPy是否要跨行或跨列进行操作。为了具有适用于任意数量维的通用表示法,NumPy引入了axis的概念:axis参数的值实际上是所讨论的索引的数量:第一个索引是axis = 0,第二个是axis = 1,依此类推。因此在2D中,轴= 0是列方向,轴= 1是指行方向。

矩阵算术

除了普通的运算符(例如+,-,*,/,//和**)可以逐个元素地工作之外,还有一个@运算符可计算矩阵乘积:

作为在第一部分中已经看到的从标量广播的概括,NumPy允许向量和矩阵之间,甚至两个向量之间的混合运算:


行向量和列向量

从上面的示例可以看出,在2D上下文中,行向量和列向量被不同地对待。这与通常的NumPy做法相反,后者通常会尽可能使用一种类型的1D数组(例如a [:,j]-2D数组a的第j列是1D数组)。默认情况下,一维数组在2D操作中被视为行向量,因此,将矩阵乘以行向量时,可以使用形状(n,)或(1,n)-结果将相同。如果您需要列向量,则有几种方法可以从一维数组中进行处理,但是令人惊讶的是,转置不是其中一种:

能够从1D数组中生成2D列向量的两个操作是使用newaxis重新塑形和索引:

这里的-1参数告诉reshape自动计算尺寸尺寸之一,方括号中的None用作np.newaxis的快捷方式,它将在指定位置添加一个空轴。

因此,NumPy中共有三种类型的向量:1D数组,2D行向量和2D列向量。这是两者之间显式转换的示意图:

根据广播规则,一维数组被隐式解释为二维行向量,因此通常不必在这两个数组之间进行转换-因此,相应区域被阴影化。

矩阵操作

连接数组有两个主要功能:

这两个仅适用于堆叠矩阵或仅适用于向量,但在将一维数组和矩阵进行混合堆叠时,只有vstack可以按预期工作:hstack生成维度不匹配错误,因为如上所述,一维数组被解释作为行向量,而不是列向量。解决方法是将其转换为行向量,或使用专门的column_stack函数自动执行此操作:

堆叠的逆向分裂:

可以通过两种方式完成矩阵复制:拼贴的行为类似于复制粘贴,重复的行为类似于分页打印:

特定的列和行可以像这样删除:

相反的操作是insert:

像hstack一样,append函数无法自动转置1D数组,因此,再次需要重新调整向量的形状或添加维,或者需要使用column_stack来代替:

实际上,如果您需要做的就是向数组的边界添加常量值,那么(稍微有点复杂)的pad函数就足够了:

网状网格

广播规则使使用网格网格的工作更加简单。假设您需要以下矩阵(但尺寸很大):

两种明显的方法很慢,因为它们使用Python循环。MATLAB处理此类问题的方法是创建一个网格:

meshgrid函数接受任意一组索引mgrid-仅切片和索引只能生成完整的索引范围。如上所述,fromfunction仅使用I和J参数调用提供的函数一次。

但是实际上,在NumPy中有一种更好的方法。无需在整个I和J矩阵上花费内存(即使meshgrid足够聪明,仅在可能的情况下仅存储对原始向量的引用)。仅存储正确形状的矢量就足够了,广播规则将处理其余的内容:

如果没有indexing ='ij'参数,则meshgrid将更改参数的顺序:J,I = np.meshgrid(j,i)-这是一种" xy"模式,可用于可视化3D绘图(请参见docs)。

除了在二维或三维网格上初始化函数外,网格还可以用于索引数组:


矩阵统计

就像sum一样,所有其他统计函数(min / max,argmin / argmax,mean / median / percentile,std / var)都接受axis参数并相应地起作用:


2D及更高版本中的argmin和argmax函数令人讨厌返回平坦索引(最小和最大值的第一个实例)。要将其转换为两个坐标,需要一个unravel_index函数:

量词all和any也都知道axis参数:

矩阵排序

尽管axis参数对于上面列出的函数很有用,但对2D排序却没有帮助:

排序矩阵或电子表格通常不是您所希望的:轴绝不能替代key参数。但是幸运的是,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))]首先按第2列排序,然后(按第2列的值相等)按第5列排序。np.lexsort(np.flipud(aT))]按从左到右的顺序对所有列进行排序。

在这里,flipud沿上下方向翻转矩阵(准确地说,沿axis = 0方向,与a [::-1,…]相同,其中三个点表示"所有其他维度"),因此突然翻转(而不是fliplr)翻转1D数组)。

3.还有一个order参数可以排序,但是如果从普通(非结构化)数组开始,则既不快速也不容易使用。

4.在熊猫中执行此操作可能是一个更好的选择,因为该特定操作在此处更具可读性且不易出错:– pd.DataFrame(a).sort_values(by = [2,5])。to_numpy()按第2列,然后按第5列排序。– pd.DataFrame(a).sort_values()。to_numpy()按从左到右的顺序按所有列排序。

3. 3D及以上

通过重塑1D向量或转换嵌套的Python列表来创建3D数组时,索引的含义为(z,y,x)。第一个索引是平面的编号,然后坐标在该平面上移动:

此索引顺序很方便,例如用于保留一堆灰度图像:a [i]是引用第i个图像的快捷方式。

但是此索引顺序不是通用的。使用RGB图像时,通常使用(y,x,z)顺序:第一个是两个像素坐标,最后一个是颜色坐标(Matplotlib中的RGB,OpenCV中的BGR):

这样可以方便地引用特定像素:a [i,j]给出(i,j)像素的RGB元组。

因此,创建某种几何形状的实际命令取决于您正在使用的域的约定:

显然,诸如hstack,vstack或dstack之类的NumPy函数并不了解这些约定。其中硬编码的索引顺序是(y,x,z),RGB图像顺序:


如果您的数据布局不同,则使用concatenate命令堆叠图像,并在axis参数中为其提供显式索引号,将更加方便:


如果您不方便考虑轴数,可以将数组转换为硬编码为hstack和co的形式:

这种转换是便宜的:没有实际的复制发生。它只是动态混合索引的顺序。

混合索引顺序的另一个操作是数组转置。检查它可能会让您对3D阵列更加熟悉。根据您决定的轴顺序,转置数组所有平面的实际命令会有所不同:对于通用数组,它交换索引1和2,对于RGB图像,它交换0和1:

有趣的是,用于转置的默认轴参数(以及唯一的a.T操作模式)会颠倒索引顺序,这与上述两个索引顺序约定都不相符。

最后,这是一个函数,可以在处理多维数组时为您节省很多Python循环,并使您的代码更简洁— einsum(爱因斯坦求和):

它将沿重复索引的数组求和。在此特定示例中,np.tensordot(a,b,axis = 1)在两种情况下都足够,但是在更复杂的情况下,einsum可能工作得更快,并且通常更容易读写,只要您了解其背后的逻辑即可。

如果您想测试自己的NumPy技能,可以在GitHub上进行一组棘手的众筹,其中包括100个NumPy练习。

如果我错过了您最喜欢的NumPy功能,请告诉我,我将尽力配合使用!


(本文由闻数起舞翻译自Lev Maximov的文章《NumPy Illustrated: The Visual Guide to NumPy》,转载请注明出处,原文链接:https://medium.com/better-programming/numpy-illustrated-the-visual-guide-to-numpy-3b1d4976de1d)

相关推荐

Vue 技术栈(全家桶)(vue technology)

Vue技术栈(全家桶)尚硅谷前端研究院第1章:Vue核心Vue简介官网英文官网:https://vuejs.org/中文官网:https://cn.vuejs.org/...

vue 基础- nextTick 的使用场景(vue的nexttick这个方法有什么用)

前言《vue基础》系列是再次回炉vue记的笔记,除了官网那部分知识点外,还会加入自己的一些理解。(里面会有部分和官网相同的文案,有经验的同学择感兴趣的阅读)在开发时,是不是遇到过这样的场景,响应...

vue3 组件初始化流程(vue组件初始化顺序)

学习完成响应式系统后,咋们来看看vue3组件的初始化流程既然是看vue组件的初始化流程,咋们先来创建基本的代码,跑跑流程(在app.vue中写入以下内容,来跑流程)...

vue3优雅的设置element-plus的table自动滚动到底部

场景我是需要在table最后添加一行数据,然后把滚动条滚动到最后。查网上的解决方案都是读取html结构,暴力的去获取,虽能解决问题,但是不喜欢这种打补丁的解决方案,我想着官方应该有相关的定义,于是就去...

Vue3为什么推荐使用ref而不是reactive

为什么推荐使用ref而不是reactivereactive本身具有很大局限性导致使用过程需要额外注意,如果忽视这些问题将对开发造成不小的麻烦;ref更像是vue2时代optionapi的data的替...

9、echarts 在 vue 中怎么引用?(必会)

首先我们初始化一个vue项目,执行vueinitwebpackechart,接着我们进入初始化的项目下。安装echarts,npminstallecharts-S//或...

无所不能,将 Vue 渲染到嵌入式液晶屏

该文章转载自公众号@前端时刻,https://mp.weixin.qq.com/s/WDHW36zhfNFVFVv4jO2vrA前言...

vue-element-admin 增删改查(五)(vue-element-admin怎么用)

此篇幅比较长,涉及到的小知识点也比较多,一定要耐心看完,记住学东西没有耐心可不行!!!一、添加和修改注:添加和编辑用到了同一个组件,也就是此篇文章你能学会如何封装组件及引用组件;第二能学会async和...

最全的 Vue 面试题+详解答案(vue面试题知识点大全)

前言本文整理了...

基于 vue3.0 桌面端朋友圈/登录验证+60s倒计时

今天给大家分享的是Vue3聊天实例中的朋友圈的实现及登录验证和倒计时操作。先上效果图这个是最新开发的vue3.x网页端聊天项目中的朋友圈模块。用到了ElementPlus...

不来看看这些 VUE 的生命周期钩子函数?| 原力计划

作者|huangfuyk责编|王晓曼出品|CSDN博客VUE的生命周期钩子函数:就是指在一个组件从创建到销毁的过程自动执行的函数,包含组件的变化。可以分为:创建、挂载、更新、销毁四个模块...

Vue3.5正式上线,父传子props用法更丝滑简洁

前言Vue3.5在2024-09-03正式上线,目前在Vue官网显最新版本已经是Vue3.5,其中主要包含了几个小改动,我留意到日常最常用的改动就是props了,肯定是用Vue3的人必用的,所以针对性...

Vue 3 生命周期完整指南(vue生命周期及使用)

Vue2和Vue3中的生命周期钩子的工作方式非常相似,我们仍然可以访问相同的钩子,也希望将它们能用于相同的场景。...

救命!这 10 个 Vue3 技巧藏太深了!性能翻倍 + 摸鱼神器全揭秘

前端打工人集合!是不是经常遇到这些崩溃瞬间:Vue3项目越写越卡,组件通信像走迷宫,复杂逻辑写得脑壳疼?别慌!作为在一线摸爬滚打多年的老前端,今天直接甩出10个超实用的Vue3实战技巧,手把...

怎么在 vue 中使用 form 清除校验状态?

在Vue中使用表单验证时,经常需要清除表单的校验状态。下面我将介绍一些方法来清除表单的校验状态。1.使用this.$refs...

取消回复欢迎 发表评论: