Numpy中1D数组的滚动窗口?

68 投票
7 回答
75814 浏览
提问于 2025-04-16 22:11

有没有办法在Numpy中高效地实现一维数组的滑动窗口?

比如,我有一段纯Python代码,用来计算一维列表的滑动标准差,其中observations是这个一维值列表,n是计算标准差时的窗口长度:

stdev = []
for i, data in enumerate(observations[n-1:]):
    strip = observations[i:i+n]
    mean = sum(strip) / n
    stdev.append(sqrt(250*sum([(s-mean)**2 for s in strip])/(n-1)))

有没有办法完全在Numpy中做到这一点,也就是说,不使用任何Python的循环?计算标准差用numpy.std很简单,但滑动窗口的部分让我完全搞不懂。

我找到了一篇关于Numpy中滑动窗口的博客文章,这篇,但似乎不适用于一维数组。

7 个回答

14

我试着用so12311在上面提到的答案来处理一个形状为 [样本数, 特征数] 的二维数组,想得到一个形状为 [样本数, 时间步, 特征数] 的输出数组,以便用于卷积神经网络或LSTM神经网络,但效果不太对。经过研究步幅的工作原理,我发现它是在最后一个轴上移动窗口,所以我做了一些调整,让窗口沿着第一个轴移动:

def rolling_window(a, window_size):
    shape = (a.shape[0] - window_size + 1, window_size) + a.shape[1:]
    strides = (a.strides[0],) + a.strides
    return np.lib.stride_tricks.as_strided(a, shape=shape, strides=strides)

注意:如果你只使用一维输入数组,输出是没有区别的。在我的搜索中,这是第一个接近我想要的结果的答案,所以我把这个分享出来,希望能帮助到其他寻找类似答案的人。

49

Numpy 1.20 开始,你可以直接使用 sliding_window_view 来获取一个滚动窗口:

from numpy.lib.stride_tricks import sliding_window_view

sliding_window_view(np.array([1, 2, 3, 4, 5, 6]), window_shape = 3)
# array([[1, 2, 3],
#        [2, 3, 4],
#        [3, 4, 5],
#        [4, 5, 6]])
84

只需要使用博客里的代码,然后把你的函数应用到结果上就可以了。

也就是说:

numpy.std(rolling_window(observations, n), 1)

在这里,你可以看到(来自博客的内容):

def rolling_window(a, window):
    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)

撰写回答