本文始发于个人公众号:TechFlow,原创不易,求个关注

今天是Numpy专题的第二篇,我们来进入正题,来看看Numpy的运算。

上一篇文章当中曾经提到过,同样大小的数据,使用Numpy的运算速度会是我们自己写循环来计算的上百倍甚至更多。并且Numpy的API非常简单,通常只要简单几行代码就可以完成非常复杂的操作。

计算与广播

在Python中的数组无论是什么类型,我们是无法直接对其中所有的元素进行计算的。想要做到这一点,必须要通过map这样的方式操作。而Numpy当中,我们可以很方便地对一整个数组或者是矩阵进行各式的计算

首先,我们先定义一个Numpy的数组:

arr = np.array([[1,2,3],[2,2,3]])

image-20200516161939969

首先而我们来看一下基本的四则运算:


image-20200516162021455

这张图中我们可以看出两点,首先是Numpy当中的数组重载了四则运算符,我们可以直接通过加减乘除进行计算。第二点是Numpy自动替我们做了映射,虽然我们运算操作的对象是数组本身,但是Numpy自动替我们映射到了其中的每一个元素。

如果你不喜欢直接运算,想要使用Numpy的api进行调用,也是一样可以的。Numpy当中也为加减乘除提供了api。


image-20200516162427254

我们甚至还可以比较两个数组的大小,得到的结果是一个bool型的数组,代表其中每一个元素的大小关系。


image-20200516162534018

除了列举的这些之外,Numpy当中还提供了许多其他的api来进行各种计算,几乎囊括了所有常见的数学计算公式。比如log、exp、pow、开方、三角函数等等计算,基本上api的名称和math当中的一样,大家也没有必要都记住,基本上可以根据英文猜出来,一般来说记住常用的,其他的可以等到使用的时候再查阅。

广播

理解了Numpy中的基本操作之后,接下来要介绍一个非常重要的概念,叫做广播。如果这个概念理解不到位,那么后来在使用的过程当中,会遇到很多头疼的问题,或者是总是看不懂别人的代码。

广播的英文叫做broadcasting,这个思想应用的范围很广,比如分布式消息中间件等很多领域都有化用。在Numpy计算当中,广播指的是将一个小的数据应用在大数据的计算上。这个概念其实很形象,我们来看个例子。

比如我们想要对Numpy中的数组每一位的元素都加上3,我们当然可以创造出一个同样大小的数组来,然后再把它们相加。但是大可不必这么麻烦,我们直接用原数组加上3即可,Numpy内部会发现3和我们的数据大小不一致,然后自动帮我们把3拓充到和我们的数据一样大小的数组再进行计算:


image-20200516162846508

它其实等价于:

np.full_like(arr, 3) + arr

如果你能理解了上面这个操作,那么同样的,我们要对所有的元素平方或者是开方也都不在话下了:


image-20200516163141477

广播并不是只可以用在数组和一个整数之间,还可以用在数组和另外一个规模更小的数组当中,但是会对两者的shape有所要求。Numpy规定,两个数组的shape必须相等或者其中一个为1才可以执行广播操作。

比如说刚才我们创建的arry数组的shape是(3, 2),我们可以让它和一个大小是(1, 2)或者是(3, 1)的“小数组”进行运算,这同样是支持的。

如果你看不明白上面的计算过程, 我下面用一张图做一下演示。

从图中可以看到左边的数组shape是(2, 3),右边的数组shape是(2, 1),满足Numpy对于广播机制的要求。Numpy会自动对右边数组shape为1的维度进行广播,也就是将它复制若干份使得它们的shape相等。如果你把左边的数组看成是若干个听广播的人,右侧的数组看成是消息的话,那么广播机制就是把消息复制若干份,让每一个听广播的人听到同样的内容。所以这个名字还是很形象的。

切片

Python中数组为人称道的很重要的一点就是它的切片操作非常方便,Numpy作为依托于Python的计算包,自然也继承了这一点,所以在Numpy当中,我们也可以很方便地使用切片功能。切片的使用方法和Python基本是一样的。

我们用上下标加上冒号来表示我们想要切片的范围, 和Python一样,这是一个左闭右开的区间。

我们也可以省略其中的一个范围,只提供上界或者是下界:


image-20200516165031942

我们还可以上下界都省略,表示全部都要,以及倒序切片的方法也和Python是一样的。


image-20200516165127699

但是有一点不太一样,Numpy中的切片和golang中的切片比较像,它代表原数组一段区间的引用,而不是拷贝。也就是说我们修改切片中的内容是会影响原数组的,我们对一个切片赋值,明显可以发现原数组的对应位置发生了改变。


image-20200516165245162

这么设计的原因和golang是一样的,因为Numpy是为了大数据计算而诞生的,大数据计算显然性能是一个非常重要的考量指标。如果这里不是设计成引用,而是拷贝的话,那么当一个大的切片产生的时候,必然会涉及到大量拷贝的操作。不仅非常消耗内存,并且也会占用大量计算资源。如果使用引用可以非常快速地返回结果。

golang当中如此设计,也是一样的道理。

那问题来了,如果我们想要拷贝出一份切片出来,而不是获得一个切片应该怎么办?答案也很简单,我们可以调用copy方法,获取一份拷贝。

arr[3:10].copy()

索引

理解了切片的用法之后,我们接下来看看索引。索引也是Numpy当中非常重要的概念,应用也非常普遍。

Numpy当中的索引对应数组中的维度,比如一个二维的数组,当我们用下标访问的时候,获得的其实是一个一维的数组。所以如果我们想要访问一个具体的元素的时候,能做的就是继续往下指定下标:


image-20200516171154055

这个很好理解,和Python当中的多维数组的用法是一样的。上面我们用了两个方括号去锁定一个元素的位置,为了写起来方便,我们还可以用逗号分隔查询。友情提醒,Python原生的数组并不支持这样的操作,不要搞混哦。

同样的道理,如果是多维的数组也是一样的,我们依次写出从0到k维的坐标来获取一个固定的元素。如果我们给出的坐标信息较少,那么则会获得一个数组。

拿3维数组举例,如果我们访问的时候只用一个下标,那么我们获得的是一个二维数组。如果使用两个下标,则获得的是一个一维数组。对于更高的维度也是同样。

结尾

今天的文章我们一起了解了Numpy当中常见的计算api以及广播和索引机制,关于索引的使用今天只是开了个头,还有很多非常灵活的用法,由于篇幅的限制,我们分成了多篇文章,会在之后的文章当中一一介绍。

今天介绍的也是Numpy的基础内容,除了广播机制稍稍需要思考一下之外,其余的应该都非常简单,我相信大家都能看明白。Numpy之所以普及,除了速度快之外,api简单易用,学习成本低也是很大的特点。

关注我,获取更多精彩文章。

手把手numpy教程【二】——数组与切片的更多相关文章

  1. Golang教程:数组和切片

    数组 数组是类型相同的元素的集合.例如,整数 5, 8, 9, 79, 76 的集合就构成了一个数组.Go不允许在数组中混合使用不同类型的元素(比如整数和字符串). 声明 var variable_n ...

  2. numpy多维数组

    1 多维数组的切片用法 c = np.array([[[0,1,2],[4,5,6],[8,7,5],[10,11,12]],[[6,2,3],[9,8,34],[100,101,102],[110, ...

  3. 手把手golang教程【二】——数组与切片

    本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是golang专题的第五篇,这一篇我们将会了解golang中的数组和切片的使用. 数组与切片 golang当中数组和C++中的定义类似, ...

  4. Numpy 笔记: 多维数组的切片(slicing)和索引(indexing)【转】

    目录 切片(slicing)操作 索引(indexing) 操作 最简单的情况 获取多个元素 切片和索引的同异 切片(slicing)操作 Numpy 中多维数组的切片操作与 Python 中 lis ...

  5. 手把手教从零开始在GitHub上使用Hexo搭建博客教程(二)-Hexo参数设置

    前言 前文手把手教从零开始在GitHub上使用Hexo搭建博客教程(一)-附GitHub注册及配置介绍了github注册.git相关设置以及hexo基本操作. 本文主要介绍一下hexo的常用参数设置. ...

  6. go语言基础知识笔记(二)之数组和切片

    数组和切片知识用的也是比较多,的给我们工作带来很大的便利 (一) 数组 定义:在golang中数组的长度是不可变,数组存放要求是同一种数据类型 //golang中数组定义的四种方法1.先声明,后赋值 ...

  7. 【NumPy学习指南】day4 多维数组的切片和索引

    ndarray支持在多维数组上的切片操作.为了方便起见,我们可以用一个省略号(...)来 表示遍历剩下的维度. (1) 举例来说,我们先用arange函数创建一个数组并改变其维度,使之变成一个三维数组 ...

  8. go语言教程之浅谈数组和切片的异同

    Hello ,各位小伙伴大家好,我是小栈君,上次分享我们讲到了Go语言关于项目工程结构的管理,本期的分享我们来讲解一下关于go语言的数组和切片的概念.用法和区别. 在go语言的程序开发过程中,我们避免 ...

  9. 【转】numpy教程

    [转载说明] 本来没有必要转载的,只是网上的版本排版不是太好,看的不舒服.所以转过来,重新排版,便于自己查看. 基础篇 NumPy的主要对象是同种元素的多维数组. 这是一个所有的元素都是一种类型.通过 ...

随机推荐

  1. 最通俗易懂的Redis发布订阅及代码实战

    发布订阅简介 除了使用List实现简单的消息队列功能以外,Redis还提供了发布订阅的消息机制.在这种机制下,消息发布者向指定频道(channel)发布消息,消息订阅者可以收到指定频道的消息,同一个频 ...

  2. pytorch 文本情感分类和命名实体识别NER中LSTM输出的区别

    文本情感分类: 文本情感分类采用LSTM的最后一层输出 比如双层的LSTM,使用正向的最后一层和反向的最后一层进行拼接 def forward(self,input): ''' :param inpu ...

  3. CSS躬行记(7)——合成

    在图形编辑软件中,可以按特定地方式处理不同图层的合成,最新的CSS规范也引入了该功能,并提供了mix-blend-mode和background-blend-mode两个属性.混合模式(blendin ...

  4. Xshell下载和连接Linux

    Xshell下载和连接Linux 第一步.Xshell的下载 方法1:从官网下载个人使用时免费的,商业使用是要收费的. http://www.xshellcn.com/ 方法二2:百度云下载Xshel ...

  5. token认证和理解

    认知篇:https://blog.csdn.net/FYGu18/article/details/89345490 token失效篇认知:https://segmentfault.com/q/1010 ...

  6. VideoView--简单的设置全屏幕播放

    我说的最主要的是要在布局哪里设置一下,如: <com.example.mypalyer.fullScreen          android:id="@+id/videoView1& ...

  7. 《名侦探柯南》动画登陆bilibili

    不管你看没看过.喜不喜欢,也一定听说过<名侦探柯南>这部动画,它和<火影>.<海贼王>几部动画陪伴了一代人成长的道路,而且<名侦探柯南>还是这几部动画中 ...

  8. extend()和append()区别

    extend()和append()都可以用来添加. 例: a = [1,2,3,4,5,6] b = [7,8,9,10] c = {'aa':123,'bb':456,'cc':789} 1.    ...

  9. 编写简单的内核模块及内核源码下载,内核模块Makefile编写

    CentOS的内核源码默认是没有下载的,需要自己下载,首先安装linux的时候就应该知道linux的版本,我装的是Centos7的 下面查一下内核的版本,使用下面的命令 [scut_lcw@local ...

  10. Pika源码学习--pika的通信和线程模型

    pika的线程模型有官方的wiki介绍https://github.com/Qihoo360/pika/wiki/pika-%E7%BA%BF%E7%A8%8B%E6%A8%A1%E5%9E%8B,这 ...