栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

从一维数组构建高效的Numpy 2D数组

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

从一维数组构建高效的Numpy 2D数组

实际上,有一种更有效的方法来执行此操作…使用

vstack
etc的缺点是,您正在复制数组。

顺便说一句,这实际上与@Paul的答案相同,但我将其发布只是为了更详细地说明事情…

有一种方法可以只使用视图来执行此操作,这样就 不会 复制 任何 内存。

我直接从Erik Rigtorp的帖子中借给numpy-discussion,后者又从Keith
Goodman的Bottleneck(这很有用!)中借用了它。

基本技巧是直接操纵数组的步幅(对于一维数组):

import numpy as npdef rolling(a, window):    shape = (a.size - window + 1, window)    strides = (a.itemsize, a.itemsize)    return np.lib.stride_tricks.as_strided(a, shape=shape, strides=strides)a = np.arange(10)print rolling(a, 3)

a
输入数组在哪里,是您
window
想要的窗口的长度(在您的情况下为3)。

这样产生:

[[0 1 2] [1 2 3] [2 3 4] [3 4 5] [4 5 6] [5 6 7] [6 7 8] [7 8 9]]

但是,原始

a
数组和返回的数组之间绝对没有重复的内存。这意味着,它的快速和规模 高于其他选项更好。

例如(使用

a = np.arange(100000)
window=3
):

%timeit np.vstack([a[i:i-window] for i in xrange(window)]).T1000 loops, best of 3: 256 us per loop%timeit rolling(a, window)100000 loops, best of 3: 12 us per loop

如果我们将其沿N维数组的最后一个轴归纳为“滚动窗口”,则会得到Erik Rigtorp的“滚动窗口”功能:

import numpy as npdef rolling_window(a, window):   """   Make an ndarray with a rolling window of the last dimension   Parameters   ----------   a : array_like       Array to add rolling window to   window : int       Size of rolling window   Returns   -------   Array that is a view of the original array with a added dimension   of size w.   Examples   --------   >>> x=np.arange(10).reshape((2,5))   >>> rolling_window(x, 3)   array([[[0, 1, 2], [1, 2, 3], [2, 3, 4]],          [[5, 6, 7], [6, 7, 8], [7, 8, 9]]])   Calculate rolling mean of last dimension:   >>> np.mean(rolling_window(x, 3), -1)   array([[ 1.,  2.,  3.],          [ 6.,  7.,  8.]])   """   if window < 1:       raise ValueError, "`window` must be at least 1."   if window > a.shape[-1]:       raise ValueError, "`window` is too long."   shape = a.shape[:-1] + (a.shape[-1] - window + 1, window)   strides = a.strides + (a.strides[-1],)   return np.lib.stride_tricks.as_strided(a, shape=shape, strides=strides)

因此,让我们看一下这里发生的事情…操纵数组

strides
似乎有些神奇,但是一旦您了解了正在发生的事情,那根本就没有。numpy数组的步幅描述了沿给定轴递增一个值所必须执行的步长(以字节为单位)。因此,在64位浮点数的一维数组的情况下,每一项的长度为8个字节,
x.strides
(8,)

x = np.arange(9)print x.strides

现在,如果将其重塑为2D,3x3数组,则步幅将为

(3 * 8,8)
,因为我们必须跳24个字节才能沿第一个轴增加一个步长,而要跳8个字节来沿第二个轴增加一个步长。

y = x.reshape(3,3)print y.strides

类似地,转置与反转数组的步幅相同:

print yy.strides = y.strides[::-1]print y

显然,阵列的步幅和阵列的形状紧密相连。如果更改一个,则必须相应地更改另一个,否则,我们将无法获得对实际上保存数组值的内存缓冲区的有效描述。

因此,如果你想改变 两者 同时数组的形状和大小,你不能仅仅通过设置这样做

x.strides
x.shape
,即使新的进展和形状是兼容的。

那就是问题所在

numpy.lib.as_strided
。它实际上是一个非常简单的函数,它可以同时设置数组的步幅和形状。

它会检查这两者是否兼容,但不会检查旧的步幅和新形状是否兼容,如果您分别设置这两者会发生这种情况。(它实际上是通过numpy

__array_interface__
做到的,它允许任意类将内存缓冲区描述为numpy数组。)

因此,我们所做的全部工作都是使它沿着一个轴向前移动一个项目(在64位数组的情况下为8个字节),而沿着另一个轴 仅向前移动8个字节

换句话说,在“窗口”大小为3的情况下,数组的形状为

(whatever, 3)
,但不是
3 * x.itemsize
将第二维的整数步进,而是
仅向前推动一项 ,有效地使新数组的行成为“移动”窗口”视图进入原始数组。

(这也意味着

x.shape[0] * x.shape[1]
它将与
x.size
您的新阵列不同。)

无论如何,希望这会使事情变得更加清晰。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/611970.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号