矩阵滑动窗口元素

4

我有一组时间序列,并且要对每个时间序列中的W个元素应用某些用户定义的函数。

目前我只是使用for循环,滑动窗口大小为W,在每次迭代中将函数应用于窗口中的元素。

我正在使用Matlab,但使用“for循环”非常低效,因此我希望能够向量化此操作。

作为解决方案,我考虑将长度为N的信号转换为大小为(N-1,W)的矩阵,其中每行都是不同窗口中的时间序列,并对该矩阵应用函数。

所以,我的问题是:

  1. 如何将我的初始时间序列转换为这样的矩阵?
  2. 假设我使用步长X滑动窗口。那么不会出现(N-1,W)矩阵,而是((N-1)/ X,W)。 ([1]中矩阵的每X行)

示例:

假设我的时间序列是:

T = [1, 5, 6, 8, 10, 14, 22]
W = 3
X = 1

=> 我很想了解

[[1, 5, 6], 
[5, 6, 8], 
[6, 8, 10],
[8, 10, 14],
[10, 14, 22]]

如果

W = 3
X = 2

=> 我希望能够获得

[[1, 5, 6], 
[6, 8, 10],
[10, 14, 22]]

在进行向量化之前,您需要拥有更多的先前信息。不过,我并没有看到可以避免使用for循环的方法... - 16per9
1
你需要计算什么样的操作?卷积不会有所帮助吗? - Imanol Luengo
不要轻易忽略循环,有时它们比其他替代方案更快。但我同意之前的评论,我们需要更多关于您需要在这些窗口上执行的操作的信息。 - beaker
2个回答

7
使用bsxfun正确创建索引,可以极大地提高效率:
ind = bsxfun(@plus, 1:W, (0:X:numel(T)-W).');
out = T(ind);  

创建正确的索引是第一步,由第一行代码所示。这段代码创建了一个二维矩阵,其中每行都是感兴趣窗口中要访问的元素。如果您想对代码如何生成索引有直观的理解,请特别查看第一个案例,其中X = 1;W = 3;
我们可以看到,第一行包含访问元素1、2、3。第二行包含访问元素2、3、4......一直到最后一行,即5、6、7。我们可以看到,我们必须在窗口中访问相邻的元素,因此基本索引需要从1、2、3开始,或者通常从1到W。现在我们需要将这些索引偏移,使它们在每个窗口中居中于T的正确元素。第一个窗口的偏移量只是0,第二个窗口的下一个偏移量只是1,一直到最后一行,即3。我们看到,对于每一行,随着行数的增加,基础索引增加1。因此,我们为第二行的每个基本索引添加1,然后为第三行的每个基本索引添加2,以此类推。如果您将基本索引与偏移索引相加,则最终获得正确的索引以访问T中的正确元素。
同样,如果X = 2;W = 3;,我们看到我们仍然有基本索引1、2、3。然而,现在要访问的正确元素是第一行的1、2、3,然后是第二行的3、4、5,然后是第三行的5、6、7。对于每一行,我们现在将基本索引偏移2而不是1。因此,对于第二行,我们为每个基本索引添加2,然后对于第三行,我们为每个基本索引添加4,以此类推。
通常,基本索引使用向量1:W创建,而偏移索引使用向量0:X:numel(T)-W创建。减去W是必需的,这样我们在采样信号时就不会越界了。为了创建我们刚才谈论的这些索引,bsxfun为我们处理了这个问题。
我们创建一个行向量1:W,它对应于基础索引,以及一个列向量(0:X:numel(T)-W),它对应于每个窗口的偏移量。请注意,第一个偏移量从0开始,然后我们增加X的数量来确保正确的中心被计算以放置我们的基础索引。我们一直持续到达到numel(T)-W元素,这是您所述的条件。通过使用bsxfun,创建了两个临时的二维矩阵,其中行向量被复制为与列向量中的行数相同的行数,并且列向量被复制为与行向量中的列数相同的列数。一旦将这两个矩阵相加,就会得到结果索引矩阵。
使用W = 3;X = 1;运行代码得到:
>> T = [1, 5, 6, 8, 10, 14, 22];
>> X = 1;
>> W = 3;
>> ind = bsxfun(@plus, 1:W, (0:X:numel(T)-W).')

ind =

     1     2     3
     2     3     4
     3     4     5
     4     5     6
     5     6     7

同样地,如果 W = 3;X = 2;,我们也会得到:
>> T = [1, 5, 6, 8, 10, 14, 22];
>> X = 2;
>> W = 3;
>> ind = bsxfun(@plus, 1:W, (0:X:numel(T)-W).')

ind =

     1     2     3
     3     4     5
     5     6     7

你可以自行验证这些索引是否对应于T中的正确元素,以便在这种情况下创建所需的矩阵。
最后,我们使用这个索引来访问矩阵并获取正确的元素:
out = T(ind);

对于X = 1;W = 3;执行此操作会得到:

>> out = T(ind)

out =

     1     5     6
     5     6     8
     6     8    10
     8    10    14
    10    14    22

同样,对于X = 2;W = 3;,结果如下:

>> out = T(ind)

out =

     1     5     6
     6     8    10
    10    14    22

0
基于rayryeng的答案,我编写了一个函数,可以实现这个功能,还有一些额外的功能。它旨在为单变量时间序列生成自回归指数。只需使用相同的索引并连接引用数据,就可以轻松地用于多元情况。
它返回预测变量X(根据您的要求)和回归器y的索引。此外,您可以选择在滑动窗口时对预测变量X应用“掩码”。例如,对于21步的窗口,您可以选择[T-2 T-3 T-5 T-8 T-13 T-21]作为X,T作为y
您还可以更改预测范围-将来多少步的y的指数。例如X=[T-1 T-2]和y=T+2
希望其他人也会发现这个有用。
%   get_Sliding_Indexes:
%       Useful for autoregression on a univariate time series.
%       Returns the indexes for the predictor and response variables
%       according to a sliding window.
%
%   Copyright (C) 20016  Florin Schimbinschi
%
%   Parameters:
%       numRecords - the number of records in the dataset
%
%       windowLag - number of past samples to take - it will be equal to 
%           the size of the predictor vector X. Default 10
%
%       predHorizon - the prediction horizon is the number of steps into 
%           the future that predictions are to be made. Default 1
%
%       windowPattern - by default the window will take all consecutive 
%           values in the past over the window lag size, however it is
%           possible to sample using a custom pattern. 
%           For example taking every second value can be done by setting
%           this parameter to 1:2:5. Default 1:windowLag
%
%       stepSize - number of steps taken when window is moved. Default 1
%   
%   Returns:
%       indX - predictor variable indexes
%       indY - response variable indexes
%
%
%      windowPattern = 1:2:9   __ structure between [] is moved to
%             /     \         /   the right by stepSize units
%   >------[(9-7-5-3-1)---(y)]--------------->
%            \_______/ \_/
%         X = [13579]   predHorizon = 3
%
%
%   Example on a multivariate time series (two) with 6 records:
%
%     data2d = [ .1  .2  .3  .4  .5  .6 
%               .11 .22 .33 .44 .55 .66]';
% 
%     [X, y] = getSlidingIndexes(size(data2d,1), 4)
%       X =
%            1     2     3     4
%            2     3     4     5
%       y =
%            5
%            6
%
%     Assuming we are interested in the second series (column):
%
%     series2 = data2d(:,2);
%
%     series2(X)
%     ans =
%         0.1100    0.2200    0.3300    0.4400
%         0.2100    0.3300    0.4400    0.5500
% 
%     series2(y)
%     ans =
%         0.5500
%         0.6600
%
function [indX, indY] = get_Sliding_Indexes(numRecords, ...
                        windowLag, predHorizon, windowPattern, stepSize)

    if ~exist('numRecords','var') || isempty(numRecords)
        error('The number of records in the dataset is not specified');
    end
    if ~exist('stepSize','var') || isempty(stepSize)
        stepSize = 1; % steps taken when moving the window
    end
    if ~exist('predHorizon','var') || isempty(predHorizon) 
        predHorizon = 1; % aiming to predict this many steps in the future
    end  
    if ~exist('windowLag','var') || isempty(windowLag) 
        windowLag = 10; % number of time steps to look back
    end
    if exist('windowLag','var') && (windowLag > numRecords)
        error('The size of the window is larger than the number of observations');
    end
    if ~exist('windowPattern','var') || isempty(windowPattern) 
        windowPattern = 1:windowLag; % pattern of sampling data
    end
    if exist('windowPattern','var') && windowPattern(end) > windowLag
        error('The window pattern must stop at the window lag specified');
    end

    % the number of samples in the window
    maxSample = max(windowPattern);

    indX = bsxfun(@plus, windowPattern, ...
        (0:stepSize:(numRecords - maxSample - predHorizon))');
    indY = bsxfun(@plus, max(windowPattern) + predHorizon, ...
        (0:stepSize:(numRecords - maxSample - predHorizon))');
end

您也可以在这里找到代码:https://au.mathworks.com/matlabcentral/fileexchange/58730-get-sliding-indexes-numrecords--windowlag--predhorizon--windowpattern--stepsize-


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接