具有滑动 window 个元素的矩阵
Matrix with sliding window elements
我有时间序列,我将一些用户定义的函数应用于时间序列中的每个 W 元素。
现在我只是使用 for 循环,滑动 window 大小 W,并在每次迭代时将我的函数应用于 window 中的元素。
我正在使用 Matlab,它使用 "for loops" 时效率非常低,所以我很想对这个操作进行矢量化。
作为解决方案,我看到将长度为 N 的信号转换为大小为 (N - 1, W) 的矩阵,其中每一行都是不同 windows 的时间序列,并将函数应用于该矩阵。
所以,我的问题是:
- 如何将我的初始时间序列转换为这样的矩阵?
- 假设我在第 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
我有时间序列,我将一些用户定义的函数应用于时间序列中的每个 W 元素。
现在我只是使用 for 循环,滑动 window 大小 W,并在每次迭代时将我的函数应用于 window 中的元素。
我正在使用 Matlab,它使用 "for loops" 时效率非常低,所以我很想对这个操作进行矢量化。
作为解决方案,我看到将长度为 N 的信号转换为大小为 (N - 1, W) 的矩阵,其中每一行都是不同 windows 的时间序列,并将函数应用于该矩阵。
所以,我的问题是:
- 如何将我的初始时间序列转换为这样的矩阵?
- 假设我在第 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