numpy或pytroch中的滚动统计 使用Tensor.reshape 使用Tensor.unfold

问题描述

我有一个传感器的张量数据,每个张量的形状为(4,1500) 这是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中的功能可以以更简洁或更有效的方式进行滚动统计吗?

解决方法

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


使用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个样本的平均值,等等... pandas解决方案是一个“因果过滤器”,因此第一个条目将包含10个最新样本(包括样本0)的平均值,第二个条目将包含10个最新样本(包括样本10)的平均值,等等...(请注意,第一个条目在大熊猫解决方案中是nan,因为前面的样本少于10

如果这种差异是不可接受的,则可以通过先填充9个nan值并剪切最后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],win_size).mean(dim=2)

使用Tensor.unfold

解决重叠时该怎么办的评论。如果您只对均值统计感兴趣,则有多种计算方法(例如卷积,平均池,张量展开)。也就是说,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),float('nan')).squeeze(0)
tensor_rolled_data = data_padded.unfold(dimension=1,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),float('nan')).squeeze(0)
tensor_rolled_data = data_padded.unfold(1,stride).mean(dim=2)
# produces shape [4,750]

注意实际上,您可能不想使用NaN pad,因为这可能会让人头疼。相反,您可以使用零填充,'replicate'填充或'mirror'填充。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...