本文始发于个人公众号: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. Java中常量的概念

    常量:在程序执行过程中,其值不发生改变的量.分类:A:字面值常量B:自定义常量字面值常量A:字符串常量(用“”括起来的内容).举例:"hello"B:整数常量 (所有的整数)举例: ...

  2. Oracle Database 12C 安装教程

    一.下载地址 Oracle Database 官方下载地址:https://www.oracle.com/database/technologies/oracle-database-software- ...

  3. sudo: 在加载插件“sudoers_policy”时在 /etc/sudo.conf 第 0 行出错 sudo: /usr/lib/sudo/sudoers.so 必须只对其所有者可写 sudo: 致命错误,无法加载插件

    解决办法:  su root chmod 644 /usr/lib/sudo/sudoers.so chown -R root /usr/lib/sudo 千万不要给 /usr 赋全部权限!!!   ...

  4. Certified Scrum Master CSM 中文资料大全

    课程概览 本课程由中国唯一一位获CST认证培训师及LeSS-Friendly Scrum Trainer双重认证讲师,丰富一线实战经验的Scrum教练讲授:姜信宝 BoB Jiang. 敏捷变革中心是 ...

  5. HDU 5725 Game

    1. 笔记 题意是求距离的期望(距离仍指连接两点且有效的路径长度的最小值).直观想象可以发现,该距离与曼哈顿距离相比最多多2(可以构造这样的路径). 答案=(任意两点曼哈顿距离的总和 - 至少有一点是 ...

  6. HTML JavaScript 基础(上)

    一.初识JavaScript JavaScript 和 Java什么关系? 半毛线关系都没有,只是名字有点重合而已. JavaScript 和python.C#.Java.Ruby一样,都是一门独立的 ...

  7. 截取nginx日志

    截取nginx日志 sed -n '/24\/Feb\/2017:11:00:00/,/24\/Feb\/2017:12:00:00/p' yunying_api.wanglibao.com.acce ...

  8. XmlSerializer .NET 序列化、反序列化

    序列化对象   要序列化对象,首先创建要序列化的对象并设置其公共属性和字段.为此,您必须确定要将XML流存储的传输格式,作为流或文件. 例如,如果XML流必须以永久形式保存,则创建一个FileStre ...

  9. ICML2016 TUTORIAL参会分享

    本次ICML会议的tutorial安排在主会前一天.这次tutorial内容非常丰富,有微软亚研的hekaiming(已经跳去facebook)介绍深度残差网络,也有deepmind的david si ...

  10. 20171016 Python的安装

    Linux: wget https://www.python.org/ftp/python/2.7.13/Python-2.7.13.tgz.asc tar zxvf Python-2.7.13.tg ...