Numpy中1D数组的滚动窗口?
有没有办法在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)