2016-04-22 10 views
4

私は時系列を持ち、時系列のすべてのW要素にユーザー定義関数を適用しました。スライディングウィンドウ要素を含む行列

今私はちょうどforループ、サイズWのスライドウィンドウを使用しています。反復ごとにウィンドウ内の要素にmy関数を適用します。

私は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 
右のインデックスを作成

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

は、コードの最初の行で区切ら最初のステップです:

は=>私は最も確かに役立つはずbsxfunと右のインデックスを作成

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

あなたはベクトル化の前に多くの事前情報を持っている必要があります。それにもかかわらず、forループなしでやり遂げる方法はありません。 – 16per9

+1

どのような演算を計算する必要がありますか?コンボルーションはあなたを助けませんか? –

+0

ループをすばやく解除しないでください。時にはそれらは選択肢よりも高速です。しかし、私は前のコメントに同意します。これらのウィンドウで実行する必要がある操作に関する詳細情報が必要です。 – beaker

答えて

6

を取得するのが大好きです。このコードが行うことは、各行が関心のあるウィンドウごとにアクセスする要素である2D行列を作成することです。コードがどのようにインデックスを生成するかについての直感を得たい場合は、具体的に最初のケース、X = 1;W = 3;を見てください。

最初の行は要素1,2,3にアクセスしていることがわかります。2番目の行は要素2,3,4を最後の行、つまり5,6,7にアクセスすることで構成されています。ウィンドウ内の隣接する要素にアクセスする必要があることがわかるので、ベースインデックスは1,2,3、または一般に1からWになる必要があります。 オフセットこれらのインデックスは、ウィンドウごとにTの右側の要素の中央に配置する必要があります。最初のウィンドウのオフセットは単純に0で、2番目のウィンドウの次のオフセットは最後の行が3になるまで1になります。各行について、行が増加するにつれて基本インデックスに1を追加します。したがって、2番目の行の各基本索引に1を追加し、3番目の行の各基本索引に2を追加するなどの方法があります。オフセットインデックスを持つ基本インデックスを追加すると、最終的にTの右の要素にアクセスするための正しいインデックスが得られます。

同様にX = 2;W = 3;の場合、基本インデックスは1,2,3です。しかし、今アクセスする正しい要素は、第1行では1,2,3、第2行では3,4,5、第3行では5,6,7です。各行に対して、今は1の代わりにで基本インデックスをオフセットするようになりました。したがって、2番目の行は2を各基本索引に追加し、次に3番目の行の各基本索引に4を追加します。

一般に、ベースインデックスはベクトル1:Wを使用して作成され、オフセットインデックスはベクトル0:X:numel(T)-Wを使用して作成されます。 Wの減算は、要件に従って信号をサンプリングするときに境界から外れないようにするために必要です。先ほどお話したインデックスを作成するには、bsxfunがこれを処理します。

基本インデックスに対応する1:Wの行ベクトルと、ウィンドウあたりのオフセットに対応する(0:X:numel(T)-W).'の列ベクトルを作成します。最初のオフセットは0から始まり、次にXの量だけ増加して、正しい中心がベースインデックスを配置するように計算されることに注意してください。私たちがnumel(T)-W要素に達するまで停止します。これはあなたが述べた条件です。 bsxfunを使用すると、2つのテンポラリ2D行列が作成され、行ベクトルは行ベクトルと同じ数の行だけ複製され、列ベクトルは行ベクトルと同じ数の列に対して複製されます。これら2つの行列を足し合わせると、結果のインデックス行列が得られます。 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を入力します。

我々は最終的に右の要素をつかむために私たちの行列へのインデックスにこれを使用します。X = 1;W = 3;のためにこれを行う

out = T(ind); 

ができます:X = 2;W = 3;のための同様

>> out = T(ind) 

out = 

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

与える:

>> out = T(ind) 

out = 

    1  5  6 
    6  8 10 
    10 14 22 
0

rayryengの答えに基づいて、私はちょうどこれに加えていくつかの追加機能を加えた関数を書いた。これは、単変量時系列上の自己回帰の指標を生成するために設計されています。単純に同じインデックスを使用し、参照されるデータを連結することによって、多変量の場合に簡単に使用できます。

それは(あなたの要求に従って)と説明変数Yもための予測変数Xにインデックスを返します。さらに、ウィンドウをスライドさせながら、予測変数「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-

関連する問題