numpy或pytroch中的滚动统计

2024-10-19 21:47:37 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个传感器的张量数据,每个张量都是形状(41500) 这是1500个时间点,每个时间点我有4个功能。 我想用滚动平均值或其他滚动统计数据“平滑”序列。最终目标是尝试使用滚动统计信息来改进lstm自动编码器,而不是使用长原始序列。 我熟悉熊猫的滚动窗口,目前我正在这样做:

#tensor shape:
 data.shape
 (4,1500)

 #convert data to numpy array and then to dataframe and perform rolling mean
 rolled_data=pd.DataFrame(data.numpy().swapaxes(1,0)).rolling(10).mean()[::10]
 rolled_data.shape
 (150, 4)

 # convert back the dataframe to tensor
 tensor_rolled_data=torch.Tensor(rolled_data.to_numpy().swapaxes(1,0))
 tensor_rolled_data.shape
 torch.Size([4, 150])

我的问题是——有没有更好的方法?numpy/torch中的一个函数,可以以更干净或更高效的方式进行滚动统计


Tags: andtonumpyconvertdataframedata时间序列
1条回答
网友
1楼 · 发布于 2024-10-19 21:47:37

由于您是按窗口大小对输出进行跨步,因此这实际上更类似于通过平均值进行下采样,而不是计算滚动统计数据。我们可以通过简单地重塑初始张量来利用没有重叠的事实


使用Tensor.reshape

假设你的data张量有一个可被10整除的形状,那么你只需将张量重塑为(4, 150, 10)的形状,并计算沿最后一个维度的统计量。比如说

win_size = 10
tensor_rolled_data = data.reshape(data.shape[0], -1, win_size).mean(dim=2)

此解决方案不会给出与tensor_rolled_data完全相同的结果,因为在此解决方案中,第一个条目将包含前10个样本的平均值,第二个条目将包含后10个样本的平均值,等等。。。熊猫解决方案是一个“因果过滤器”,因此第一个条目将包含10个最新样本(包括样本0)的平均值,第二个条目将包含10个最新样本(包括样本10),以此类推。。。(请注意,第一个条目是pandas解决方案中的nan,因为前面的样本少于10

如果此差异不可接受,您可以通过首先使用9nan值填充并剪裁最后9个样本来重新创建结果

import torch.nn.functional as F
win_size = 10
# pad with `nan` to match behavior of pandas
data_padded = F.pad(data[None, :, :-(win_size - 1)], (win_size - 1, 0), 'constant', float('nan')).squeeze(0)
# find mean of groups of N samples
tensor_rolled_data = data_padded.reshape(data.shape[0], -1, win_size).mean(dim=2)

使用Tensor.unfold

处理有关重叠时应采取的措施的评论。如果你只对均值统计感兴趣,那么有很多方法可以计算(例如卷积、平均池、张量展开)。也就是说,^{}给出了最一般的解决方案,因为它可以用于计算窗口上的任何统计数据。比如说

# same as first example above
win_size = 10
tensor_rolled_data = data.unfold(dimension=1, size=win_size, step=win_size).mean(dim=2)

# same as second example above
import torch.nn.functional as F
win_size = 10
data_padded = F.pad(data.unsqueeze(0), (win_size - 1, 0), 'constant', float('nan')).squeeze(0)
tensor_rolled_data = data_padded.unfold(dimension=1, size=win_size, step=win_size).mean(dim=2)

在上述情况下,展开产生的结果与重塑相同,因为大小和步长相等。但是,与重塑不同,展开也支持大小!=步骤

win_size = 10
stride = 2
tensor_rolled_data = data.unfold(1, win_size, stride).mean(dim=2).mean(dim=2)
# produces shape [4, 746]

或者,您可以使用win_size - 1值填充特征的前面,以获得与熊猫相同的结果

import torch.nn.functional as F
win_size = 10
stride = 2
data_padded = F.pad(data.unsqueeze(0), (win_size - 1, 0), 'constant', float('nan')).squeeze(0)
tensor_rolled_data = data_padded.unfold(1, win_size, stride).mean(dim=2)
# produces shape [4, 750]

注意在实践中,你可能不想与NaN pad在一起,因为这很可能会让人头疼。相反,您可以使用零填充、'replicate'填充或'mirror'填充

相关问题 更多 >