带有滑动窗口元素的矩阵
Posted
技术标签:
【中文标题】带有滑动窗口元素的矩阵【英文标题】:Matrix with sliding window elements 【发布时间】:2016-08-16 11:43:19 【问题描述】:我有时间序列,我将一些用户定义的函数应用于时间序列中的每个 W 元素。
现在我只是使用 for 循环,大小为 W 的滑动窗口,并在每次迭代时将我的函数应用于窗口中的元素。
我正在使用 Matlab,它的“for 循环”效率非常低,所以我很想对这个操作进行矢量化。
作为一种解决方案,我看到将长度为 N 的信号转换为大小为 (N - 1, W) 的矩阵,其中每一行是不同窗口中的时间序列,并将函数应用于该矩阵。
所以,我的问题是:
-
如何将我的初始时间序列转换为这样的矩阵?
假设我正在使用步骤 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 循环的方法...... 你需要计算什么样的操作?卷积对您没有帮助吗? 不要这么快关闭循环;有时它们比替代品更快。但我同意之前的 cmets,我们需要更多关于您需要在这些窗口上执行的操作的信息。 【参考方案1】:使用bsxfun
创建正确的索引肯定会有所帮助:
ind = bsxfun(@plus, 1:W, (0:X:numel(T)-W).');
out = T(ind);
创建正确的索引是第一步,由第一行代码描述。这段代码所做的是它创建了一个 2D 矩阵,其中每一行是每个感兴趣的窗口要访问的元素。如果您想直观了解代码如何生成索引,请专门查看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
【讨论】:
【参考方案2】:根据 rayryeng 的回答,我编写了一个完全可以做到这一点的函数,以及一些额外的功能。它旨在为单变量时间序列上的自回归生成索引。通过简单地使用相同的索引并连接引用的数据,它可以很容易地用于多变量情况。
它将索引返回到预测变量 X(根据您的要求)和回归变量 y 也一样。此外,您可以选择在滑动窗口时对预测变量 X 应用“掩码”。例如,对于 21 步的窗口,您可以为 X 选择 [T-2 T-3 T-5 T-8 T-13 T-21] 和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-
【讨论】:
以上是关于带有滑动窗口元素的矩阵的主要内容,如果未能解决你的问题,请参考以下文章
Apache Spark - 处理临时 RDD 上的滑动窗口