python - numpy 或 pytorch 中的滚动统计

标签 python pandas numpy pytorch

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

#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 中的函数可以以更干净或更有效的方式进行滚动统计?

最佳答案

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


使用Tensor.reshape

假设您的 data 张量的形状可被 10 整除,那么您只需将张量 reshape 为形状 (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 个最新样本(包括样本 0)示例 10 等...(请注意,pandas 解决方案中的第一个条目是 nan,因为前面的示例少于 10)。

如果这种差异 Not Acceptable ,您可以通过首先填充 9 个 nan 值并剪掉最后 9 个样本来重新创建 pandas 结果。

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

解决有关重叠时该怎么做的评论。如果您只对平均统计量感兴趣,那么有多种方法可以计算它(例如卷积、平均池化、张量展开)。也就是说,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)

在上述情况下,展开与 reshape 产生相同的结果,因为大小和步长相等。然而,与 reshape 不同的是,展开还支持大小!=步长。

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 值填充功能的前面,以达到与 pandas 相同的结果。

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]

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

关于python - numpy 或 pytorch 中的滚动统计,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63361688/

相关文章:

python - 使用 NumPy 计算平均分数时出错 : 'ufunc add' did not contain a loop

python - 无法弄清楚使用什么输入来使 cv2.calcOpticalFlowPyrLK 方法起作用

python - 将不同日期格式的txt导入MySQL

python,代码的不同结果

python - 如何计算 Pandas 数据框中的结果行?

pandas - 用数据框中列的平均值替换字符串值

python - Django:如何正确使用UserProfile? (Django 授权额外信息)

python - 如何从 pandas 数据帧的两个不同列添加值

python - 将一列替换为属于两个不同数据框的另一列的值

python - win32com 内存错误 : CreatingSafeArray attempting to insert data into excel