拒绝for循环,从take_along_axis开始
技术背景
在前一篇文章中,我们提到了关于Numpy中的各种取index的方法,可以用于取出数组里面的元素,也可以用于做切片,甚至可以用来做排序。但是遇到对于高维矩阵的某一个维度取多个值的时候,单纯的使用下标已经无法完成相关的操作了。如果找不到相应的接口,对于性能要求不高的场景可以使用一个for循环进行替代,但是对于性能要求比较高的场景下,我们还是尽可能的使用Numpy本身自带的接口,比如本文将要提到的take_along_axis操作。
使用案例
我们考虑这样的一个场景,给定一个维度为(4,11,3)的矩阵a作为数据,和一个维度为(4,2)的矩阵b作为下标,意味着从a中第二条轴的11个元素中每次取两个元素,也就是希望得到一个维度为(4,2,3)的结果:
In [11]: a = np.arange(132).reshape((4,11,3))
In [12]: a
Out[12]:
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],
[ 30, 31, 32]],
[[ 33, 34, 35],
[ 36, 37, 38],
[ 39, 40, 41],
[ 42, 43, 44],
[ 45, 46, 47],
[ 48, 49, 50],
[ 51, 52, 53],
[ 54, 55, 56],
[ 57, 58, 59],
[ 60, 61, 62],
[ 63, 64, 65]],
[[ 66, 67, 68],
[ 69, 70, 71],
[ 72, 73, 74],
[ 75, 76, 77],
[ 78, 79, 80],
[ 81, 82, 83],
[ 84, 85, 86],
[ 87, 88, 89],
[ 90, 91, 92],
[ 93, 94, 95],
[ 96, 97, 98]],
[[ 99, 100, 101],
[102, 103, 104],
[105, 106, 107],
[108, 109, 110],
[111, 112, 113],
[114, 115, 116],
[117, 118, 119],
[120, 121, 122],
[123, 124, 125],
[126, 127, 128],
[129, 130, 131]]])
In [13]: b = np.array([[0,1],[1,2],[2,3],[3,4]])
In [14]: b
Out[14]:
array([[0, 1],
[1, 2],
[2, 3],
[3, 4]])
为了方便展示我们就定义了这样两个比较简单的矩阵a和b,那么在这个结果中,我们理想的结果应该是:
[[[ 0, 1, 2],
[ 3, 4, 5]],
[[ 36, 37, 38],
[ 39, 40, 41]],
[[ 72, 73, 74],
[ 75, 76, 77]],
[[108, 109, 110],
[111, 112, 113]]]
这样的一个矩阵。关于这个结果的来源,可以对b这个定义进行展开解释,b的值为:
[[0, 1],
[1, 2],
[2, 3],
[3, 4]]
它所表示的是在a[0]下取第0个元素和第1个元素,在a[1]下取第1个元素和第2个元素,以此类推。然而如果我们直接把定义好的b放到a的索引中或者直接使用numpy.take的方法的话,得到的结果是这样的:
In [16]: a[:,b]
Out[16]:
array([[[[ 0, 1, 2],
[ 3, 4, 5]],
[[ 3, 4, 5],
[ 6, 7, 8]],
[[ 6, 7, 8],
[ 9, 10, 11]],
[[ 9, 10, 11],
[ 12, 13, 14]]],
[[[ 33, 34, 35],
[ 36, 37, 38]],
[[ 36, 37, 38],
[ 39, 40, 41]],
[[ 39, 40, 41],
[ 42, 43, 44]],
[[ 42, 43, 44],
[ 45, 46, 47]]],
[[[ 66, 67, 68],
[ 69, 70, 71]],
[[ 69, 70, 71],
[ 72, 73, 74]],
[[ 72, 73, 74],
[ 75, 76, 77]],
[[ 75, 76, 77],
[ 78, 79, 80]]],
[[[ 99, 100, 101],
[102, 103, 104]],
[[102, 103, 104],
[105, 106, 107]],
[[105, 106, 107],
[108, 109, 110]],
[[108, 109, 110],
[111, 112, 113]]]])
显然这不是我们想要的结果。需要额外申明的是,这个执行操作中,最后一个维度的冒号加与不加是一样的效果,跟numpy.take本质上也是同样的操作,因此就需要使用到numpy中的另外一个接口:take_along_axis
,如下是其官方的API文档:
还有相关的使用案例:
需要注意的是,输入的indices必须要跟原始的数据矩阵保持同样的维度,因此在我们自己的案例中,对b进行了扩维,最终的代码如下所示:
In [23]: np.take_along_axis(a,b[:,:,None],axis=1)
Out[23]:
array([[[ 0, 1, 2],
[ 3, 4, 5]],
[[ 36, 37, 38],
[ 39, 40, 41]],
[[ 72, 73, 74],
[ 75, 76, 77]],
[[108, 109, 110],
[111, 112, 113]]])
最后得到的就是我们想要的结果了,并且是直接使用下标无法实现的操作(当然,也可能是我还没研究出来这样的操作)。这里axis设置为1,就表示a的第0个维度和b的第0个维度是一致的取法,也可以理解成全取的意思。
总结概要
Numpy是在Python中用于各种矩阵运算非常强大的工具之一,而快速的通过下标取出所需位置的元素也是numpy所支持的强大功能之一。常规的元素取法都可以通过numpy的下标或者是numpy.take函数来实现,比如array[0,:]可用于取第一条轴的所有元素,array[:,0]可以用于取第二条轴的所有第二个元素,放在一个2维的矩阵里面就分别是取第一行的所有元素和取第一列的所有元素。但是本文更加关注于更高维的矩阵,当我们想从多个维度中取多个元素时,是不太容易直接用下标去取的,比如同时取a[0][0],a[0][1],a[1,1],a[1][2]的话,那么就只能使用numpy所支持的另外一个函数numpy.take_along_axis来实现。
版权声明
本文首发链接为:https://www.cnblogs.com/dechinphy/p/take_along_axis.html
作者ID:DechinPhy
更多原著文章请参考:https://www.cnblogs.com/dechinphy/
打赏专用链接:https://www.cnblogs.com/dechinphy/gallery/image/379634.html
腾讯云专栏同步:https://cloud.tencent.com/developer/column/91958
参考链接
拒绝for循环,从take_along_axis开始的更多相关文章
- 停止使用循环 教你用underscore优雅的写代码
你一天(一周)内写了多少个循环了? var i; for(i = 0; i < someArray.length; i++) { var someThing = someArray[i]; ...
- 说说Golang的使用心得
13年上半年接触了Golang,对Golang十分喜爱.现在是2015年,离春节还有几天,从开始学习到现在的一年半时间里,前前后后也用Golang写了些代码,其中包括业余时间的,也有产品项目中的.一直 ...
- 剑指Offer - 九度1507 - 不用加减乘除做加法
剑指Offer - 九度1507 - 不用加减乘除做加法2013-11-29 20:00 题目描述: 写一个函数,求两个整数之和,要求在函数体内不得使用+.-.*./四则运算符号. 输入: 输入可能包 ...
- Android应用程序线程消息循环模型分析
文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6905587 我们知道,Android应用程序是 ...
- 深入理解 JavaScript 事件循环(二)— task and microtask
引言 microtask 这一名词是 JS 中比较新的概念,几乎所有人都是在学习 ES6 的 Promise 时才接触这一新概念,我也不例外.当我刚开始学习 Promise 的时候,对其中回调函数的执 ...
- 微信小程序开发问答《五十四》同步请求授权 & 用户拒绝授权,重新调起授权 ... ...
1.同步请求授权 需求分析: 1.在小程序首次打开的时候,我需要同时请求获取多个权限,由用户逐一授权. (['scope.userInfo','scope.userLocation','scope.a ...
- 从JavaScript的事件循环到Promise
JS线程是单线程运行机制,就是自己按顺序做自己的事,浏览器线程用于交互和控制,JS可以操作DOM元素, 说起JS中的异步时,我们需要注意的是,JS中其实有两种异步,一种是基于浏览器的异步IO,比如Aj ...
- JavaScript是如何工作的:事件循环和异步编程的崛起 + 5种使用 async/await 更好地编码方式!
摘要: 深度理解JS事件循环!!! 原文:JavaScript是如何工作的:事件循环和异步编程的崛起+ 5种使用 async/await 更好地编码方式! 作者:前端小智 Fundebug经授权转载, ...
- JDK线程池的拒绝策略
关于新疆服务请求未带入来话原因的问题 经核查,该问题是由于立单接口内部没有成功调用接续的 “更新来电原因接口”导致的,接续测更新来电原因接口编码:NGCCT_UPDATESRFLAG_PUT ,立单接 ...
随机推荐
- Idea操作Maven详细使用:
Idea操作Maven详细使用: Maven简介 什么是 Maven Maven 的正确发音是[ˈmevən] "卖v",而不是"马瘟"以及其他什么瘟. Mav ...
- cesium结合geoserver利用WFS服务实现图层删除(附源码下载)
前言 cesium 官网的api文档介绍地址cesium官网api,里面详细的介绍 cesium 各个类的介绍,还有就是在线例子:cesium 官网在线例子,这个也是学习 cesium 的好素材. 内 ...
- Cesium入门9 - Loading and Styling Entities - 加载和样式化实体
Cesium入门9 - Loading and Styling Entities - 加载和样式化实体 Cesium中文网:http://cesiumcn.org/ | 国内快速访问:http://c ...
- gin源码解读1-net/http的大概流程
gin框架预览 router.Run()的源码: func (engine *Engine) Run(addr ...string) (err error) { defer func() { debu ...
- Selenium&PhantomJS 完成爬取网络代理
Selenium模块是一套完整的Web应用程序测试系统,它包含了测试的录制(SeleniumIDE).编写及运行(Selenium Remote Control)和测试的并行处理(Selenimu G ...
- python列表删除和排序
1.del message[0]---知道位置不知道值 2.message.remove('a')----知道值不知道位置 3.message.sort()--正向永久排序 4.message.sor ...
- 基于 esbuild 的 universal bundler 设计
--字节跳动前端 Byte FE :杨健 背景 由于 Lynx(公司自研跨端框架)编译工具和传统 Web 编译工具链有较大的差别(如不支持动态 style 和动态 script 基本告别了 bundl ...
- Azure AD Domain Service(一)将 Azure VM 实例添加到域服务里
一,引言 有网友提到实际项目中如何将 Azuer VM 实例加入到 Azure AD 域,那我们今天就带着整个问题开始今天的分析!首先我们得了解什么是 Azure AD 域服务,Azure AD 域服 ...
- 关于基于python2.7的unity自动化测试框架GAutomator测试环境的搭建(源码网盘下载地址:https://pan.baidu.com/s/1c2TXwtU)
关于基于python 2.7的unity自动化测试框架GAutomator测试环境的搭建 百度云盘链接(思维图学习资料):https://pan.baidu.com/s/1dFWExMD 准备工作(具 ...
- idea2020.1版本的maven项目报包不存在,找不到包错误
错误描述 idea创建maven项目,导入依赖都是成功,但是运行就会报找不到对应jar包的错误 解决办法: File -> Settings -> 搜索maven -> 展开mave ...