具有滑动 window 个元素的矩阵

Matrix with sliding window elements

我有时间序列,我将一些用户定义的函数应用于时间序列中的每个 W 元素。

现在我只是使用 for 循环,滑动 window 大小 W,并在每次迭代时将我的函数应用于 window 中的元素。

我正在使用 Matlab,它使用 "for loops" 时效率非常低,所以我很想对这个操作进行矢量化。

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

所以,我的问题是:

  1. 如何将我的初始时间序列转换为这样的矩阵?
  2. 假设我在第 X 步滑动 window。因此不会出现 (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]]

使用 bsxfun 创建正确的索引肯定会有所帮助:

ind = bsxfun(@plus, 1:W, (0:X:numel(T)-W).');
out = T(ind);  

创建正确的索引是第一步,由第一行代码描述。这段代码的作用是创建一个二维矩阵,其中每一行都是根据 window 兴趣访问的元素。如果您想直观地了解代码是如何生成索引的,请专门查看 X = 1;W = 3;.

的第一种情况

我们可以看到第一行由访问元素 1、2、3 组成。第二行由访问元素 2、3、4... 直到最后一行,即 5、6、7 . 我们可以看到我们必须访问 window 中的相邻元素,因此基本索引需要从 1、2、3 或通常从 1 到 W。我们现在需要 偏移 这些索引,以便它们以 T 每个 window 中的正确元素为中心。第一个 window 的偏移量只是 0,第二个 window 的下一个偏移量只是 1,直到最后一行为 3。我们看到,对于每一行,我们在基本索引随着行的增加。因此,我们为第二行的每个基本索引加 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).' 的列向量,它对应于每个 window 的偏移量。请注意,第一个偏移量从 0 开始,然后我们增加 X 量以确保计算出正确的中心以放置我们的基本索引。我们停止,直到我们达到 numel(T)-W 个元素,这就是您所说的条件。通过使用 bsxfun,创建了两个临时 2D 矩阵,其中行向量复制的行数与列向量中的行数相同,列向量复制的列数与列向量中的列数相同。行向量。将这两个矩阵相加后,您将得到结果索引矩阵。

运行 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

根据 rayryeng 的回答,我编写了一个函数来执行此操作,外加一些附加功能。它旨在为单变量时间序列的自回归生成索引。通过简单地使用相同的索引并连接引用的数据,它可以很容易地用于多变量情况。

它 returns 预测变量 X 的索引(根据您的要求)和回归变量 y也是。此外,您还可以选择在滑动 window 的同时将 'mask' 应用于预测变量 X。例如,window 有 21 个步骤,您可以 select [T-2 T-3 T-5 T-8 T-13 T-21] for 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-