数据向量列表的快速滚动求和(二维矩阵)
Posted
技术标签:
【中文标题】数据向量列表的快速滚动求和(二维矩阵)【英文标题】:Fast rolling-sum for list of data vectors (2d matrix) 【发布时间】:2015-04-02 00:28:13 【问题描述】:我正在寻找一种快速计算滚动和的方法,可能使用 Numpy。这是我的第一种方法:
def func1(M, w):
Rtn = np.zeros((M.shape[0], M.shape[1]-w+1))
for i in range(M.shape[1]-w+1):
Rtn[:,i] = np.sum(M[:, i:w+i], axis=1)
return Rtn
M = np.array([[0., 0., 0., 0., 0., 1., 1., 0., 1., 1., 1., 0., 0.],
[0., 0., 1., 0., 1., 0., 0., 0., 0., 0., 0., 1., 1.],
[1., 1., 0., 1., 0., 0., 0., 1., 0., 0., 0., 0., 0.]])
window_size = 4
print func1(M, window_size)
[[ 0. 0. 1. 2. 2. 3. 3. 3. 3. 2.]
[ 1. 2. 2. 1. 1. 0. 0. 0. 1. 2.]
[ 3. 2. 1. 1. 1. 1. 1. 1. 0. 0.]]
我想防止窗口(/sum)在循环中被重做,并希望让它更快,所以我想出了以下函数,它将总和限制为滚动窗口的第一个和最后一个元素:
def func2(M, w):
output = np.zeros((M.shape[0], M.shape[1]-w+1))
sum = np.sum(M[:, 0:w], axis=1)
output[:,0] = sum
for i in range(w, M.shape[1]):
sum = sum + M[:,i]- M[:,i-w]
output[:,i-w+1] = sum
return output
但令我惊讶的是,func2 几乎不比 func1 快:
In [251]:
M = np.random.randint(2, size=3000).reshape(3, 1000)
window_size = 100
%timeit func1(M, window_size)
10 loops, best of 3: 20.9 ms per loop
In [252]:
%timeit func2(M, w)
10 loops, best of 3: 15.5 ms per loop
我在这里遗漏了什么吗?你们知道更好的,我的意思是更快的方法来实现这一目标吗?
【问题讨论】:
由于运行总和 == 移动平均,可能重复:***.com/questions/14313510/… 除了除法部分,其他都可以 你没有得到实际的总和。您正在寻找滑动窗口,而不是运行总和。 我也不认为滑动窗口本身是正确的。我认为您可以对滑动窗口(或滚动窗口)进行求和,也可以对滑动窗口求平均值。我建议将其编辑为滚动总和,这似乎更接近正确的东西。 我同意 E 先生的观点。快速滚动求和是我的想法。很抱歉造成混乱。 【参考方案1】:改编自@Jaime 的回答:https://***.com/a/14314054/553404
import numpy as np
def rolling_sum(a, n=4) :
ret = np.cumsum(a, axis=1, dtype=float)
ret[:, n:] = ret[:, n:] - ret[:, :-n]
return ret[:, n - 1:]
M = np.array([[0., 0., 0., 0., 0., 1., 1., 0., 1., 1., 1., 0., 0.],
[0., 0., 1., 0., 1., 0., 0., 0., 0., 0., 0., 1., 1.],
[1., 1., 0., 1., 0., 0., 0., 1., 0., 0., 0., 0., 0.]])
print(rolling_sum(M))
输出
[[ 0. 0. 1. 2. 2. 3. 3. 3. 3. 2.]
[ 1. 2. 2. 1. 1. 0. 0. 0. 1. 2.]
[ 3. 2. 1. 1. 1. 1. 1. 1. 0. 0.]]
时间
In [7]: %timeit rolling_sum(M, 4)
100000 loops, best of 3: 7.89 µs per loop
In [8]: %timeit func1(M, 4)
10000 loops, best of 3: 70.4 µs per loop
In [9]: %timeit func2(M, 4)
10000 loops, best of 3: 54.1 µs per loop
【讨论】:
太棒了。只是一个挑剔,你必须采取实际的sum(running_sum(M))
你确定吗?我没有从问题中得到答案。
?在这种情况下,OP 正在寻找 滑动窗口,而不是运行总和
是的,我认为您是对的,因为措辞不正确。但很清楚问题的输出应该是什么。
修复了标题和标签以上是关于数据向量列表的快速滚动求和(二维矩阵)的主要内容,如果未能解决你的问题,请参考以下文章