如何在向量化NumPy数组上进行移动窗口
作者:deephub 发布时间:2023-04-23 08:26:55
今天很有可能你已经做了一些使用滑动窗口(也称为移动窗口)的事情,而你甚至不知道它。例如:许多编辑算法都是基于移动窗口的。
在GIS中做地形分析的大多数地形栅格度量(坡度、坡向、山坡阴影等)都基于滑动窗口。很多情况下,对格式化为二维数组的数据进行分析时,都很有可能涉及到滑动窗口。
滑动窗口操作非常普遍,非常有用。它们也很容易在Python中实现。学习如何实现移动窗口将把你的数据分析和争论技能提升到一个新的水平。
什么是滑动窗?
下面的例子显示了一个3×3(3×3)滑动窗口。用红色标注的数组元素是目标元素。这是滑动窗口将计算的新度量的数组位置。例如,在下面的图像中,我们可以计算灰色窗口中9个元素的平均值(平均值也是8),并将其分配给目标元素,用红色标出。你可以计算最小值(0)、最大值(16)或其他一些指标,而不是平均值。对数组中的每个元素都这样做。
就是这样。这就是滑动窗口的基本原理。当然,事情可能变得更加复杂。有限差分方法可以用于时间和空间数据。逻辑可以实现。可以使用更大的窗口大小或非正方形窗口。你懂的。但在其核心,移动窗口分析可以简单地总结为邻居元素的平均值。
需要注意的是,必须为边缘元素设置特殊的调整,因为它们没有9个相邻元素。因此,许多分析都排除了边缘元素。为简单起见,我们将在本文中排除边缘元素。
样例数组
3x3的滑动窗口
创建一个NumPy数组
为了实现一些简单的示例,让我们创建上面所示的数组。首先,导入numpy。
import numpy as np
然后使用arange创建一个7×7的数组,值范围从1到48。另外,创建另一个包含无数据值的数组,该数组的形状和数据类型与初始数组相同。在本例中,我使用-1作为无数据值。
a = np.arange(49).reshape((7, 7))
b = np.full(a.shape, -1.0)
我们将使用这些数组来开发下面的滑动窗口示例。
通过循环实现滑动窗口
毫无疑问,你已经听说过Python中的循环很慢,应该尽可能避免。特别是在使用大型NumPy数组时。这是完全正确。尽管如此,我们将首先看一个使用循环的示例,因为这是一种简单的方法来概念化在移动窗口操作中发生的事情。在你通过循环示例掌握了概念之后,我们将继续使用更有效的向量化方法。
要实现移动窗口,只需循环遍历所有内部数组元素,识别所有相邻元素的值,并在特定的计算中使用这些值。
通过行和列偏移量可以很容易地识别相邻值。3×3窗口的偏移量如下所示。
行偏移
列偏移
循环中NumPy移动窗口的Python代码
我们可以用三行代码实现一个移动窗口。这个例子在滑动窗口内计算平均值。首先,循环遍历数组的内部行。其次,循环遍历数组的内部列。第三,在滑动窗口内计算平均值,并将值赋给输出数组中相应的数组元素。
for i in range(1, a.shape[0]-1):
for j in range(1, a.shape[1]-1):
b[i, j] = (a[i-1, j-1] + a[i-1, j] + a[i-1, j+1] + a[i, j-1] + a[i, j] + a[i, j+1] + a[i+1, j-1] + a[i+1, j] + a[i+1, j+1]) / 9.0
循环后结果
你将注意到结果与输入数组具有相同的值,但是外部元素没有被分配数据值,因为它们不包含9个相邻元素。
[[-1. -1. -1. -1. -1. -1. -1.]
[-1. 8. 9. 10. 11. 12. -1.]
[-1. 15. 16. 17. 18. 19. -1.]
[-1. 22. 23. 24. 25. 26. -1.]
[-1. 29. 30. 31. 32. 33. -1.]
[-1. 36. 37. 38. 39. 40. -1.]
[-1. -1. -1. -1. -1. -1. -1.]]
向量化滑动窗口
Python中的数组循环通常计算效率低下。通过对通常在循环中执行的操作进行向量化,可以提高效率。移动窗口矢量化可以通过同时抵消数组内部的所有元素来实现。
如下图所示。每个图像都有相应的索引。你将注意到最后一张图像索引了所有内部元素,并且对应的图像索引了每个相邻元素的偏移量。
从左到右的偏移索引:[1:-1,:-2],[1:-1,2:],[2 :, 2:]
从左到右的偏移索引:[2 :,:-2],[2 :, 1:-1],[:-2,1:-1]
从左到右的偏移索引:[:-2,2:],[:-2,:-2],[1:-1、1:-1]
Numpy数组上的向量化移动窗口的Python代码
有了上述偏移量,我们现在可以轻松地在一行代码中实现滑动窗口。 只需将输出数组的所有内部元素设置为根据相邻元素计算所需输出的函数。
b[1:-1, 1:-1] = (a[1:-1, 1:-1] + a[:-2, 1:-1] + a[2:, 1:-1] + a[1:-1, :-2] + a[1:-1, 2:] + a[2:, 2:] + a[:-2, :-2] + a[2:, :-2] + a[:-2, 2:]) / 9.0
矢量化滑动窗口结果
如你所见,这将得到与循环相同的结果。
[[-1. -1. -1. -1. -1. -1. -1.]
[-1. 8. 9. 10. 11. 12. -1.]
[-1. 15. 16. 17. 18. 19. -1.]
[-1. 22. 23. 24. 25. 26. -1.]
[-1. 29. 30. 31. 32. 33. -1.]
[-1. 36. 37. 38. 39. 40. -1.]
[-1. -1. -1. -1. -1. -1. -1.]]
速度比较
上述两种方法产生相同的结果,但哪一种更有效?我计算了从5行到100列的数组的每种方法的速度。每种方法对每个测试100次。下面是每种方法的平均时间。
很明显,向量化的方法更加有效。随着数组大小的增加,循环的效率呈指数级下降。另外,需要注意的是,一个包含10,000个元素(100行和100列)的数组非常小。
来源:https://deephub.blog.csdn.net/article/details/112799022


猜你喜欢
- 主要作用与拷贝文件用的。1.shutil.copyfileobj(文件1,文件2):将文件1的数据覆盖copy给文件2。import shu
- created页面加载未渲染html之前执行。mounted渲染html后再执行。由于created在html模板生产之前所以无法对Dom进
- 在Python中一切都是对象。Python中对象包含的三个基本要素,分别是:id(身份标识)、type(数据类型)和value(值)。对象之
- 使用数据库的过程中,由于断电或其他原因,有可能导致数据库出现一些小错误,比如检索某些表特别慢,查询不到符合条件的数据等。出现这些情况的原因,
- 首先,创建一个DataFrame格式数据作为举例数据。# 创建一个DataFrame格式数据data = {'a': [
- 前言最近突然对爬虫有了一点兴趣,所以打算学一下爬虫,但是在安装使用一些库时,遇到了一些不小的麻烦,对于我来说,最麻烦的就是配置环境了,老是有
- 本文实例为大家分享了JavaScript实现QQ聊天室的具体代码,供大家参考,具体内容如下1. 任务要求1)掌握基本过滤选择器;2)掌握jQ
- 本文实例讲述了Go语言使用sort包对任意类型元素的集合进行排序的方法。分享给大家供大家参考。具体如下:使用sort包的函数进行排序时,集合
- 具体解决方案如下: 一、IE和FF下document.body对象的clientHeight,offsetHeight,scrollHeig
- PHP mysqli_stat() 函数创建 SSL 连接:<?php// 假定数据库用户名:root,密码:123456,数据库:c
- 一. 概念理解你可能有留意到当你浏览网页时,会有一些推送消息,大多数是你最近留意过的同类东西,比如你想买桌子,上淘宝搜了一下,结果连着几天会
- 前言对MySQL有研究的读者,可能会发现MySQL更新很快,在安装方式上,MySQL提供了两种经典安装方式:解压式和一键式,虽然是两种安装方
- 用习惯列表解析之后会觉得超级酷,所以在尝试使用列表解析,把循环什么的写在一行里面。使用if的时候什么时候必须要有else,什么时候可以没有e
- 很有创意的鼠标指针风筝,看起来非常有意思。在网络上看到的,一下也想不起来是那里的了,所以特别说一下图片是来自网络的,版权归作者所有。
- 最近老师留了几个作业,虽然用opencv很简单一句话就出来了,但是还没用python写过。在官方文档中的tutorial中的threshol
- 【先锋缓存类】Ver2004作者:孙立宇、apollosun、ezhonghua官方网站:http://www.lkstar.com 技术支
- encode() 方法返回字符串的编码版本。默认编码是当前的默认字符串编码。可给予设置不同的错误处理机制。语法以下是encode
- 本文实例讲述了JS自定义混合Mixin函数。分享给大家供大家参考,具体如下:<script type="text/javas
- 由于ajax在跨域的访问上有问题,目前最好的方法是做代理.写了个代理程序和心得为了做ajax的代理,研究了下服务器端的xmlhttp并和客户
- 我们之前一直都在使用的urlopen,这是一个特殊的opener(也就是模块帮我们构建好的)。但是基本的urlopen()方法不支持代理、c