matlab - una - Matriz con elementos deslizantes de ventana
titulo grafica matlab (2)
Basado en la respuesta de Rayryeng, escribí una función que hace exactamente esto, más algunas funcionalidades adicionales. Está diseñado para generar índices de autoregresión en una serie temporal univariable. Se puede usar fácilmente para el caso multivariante simplemente usando los mismos índices y concatenando los datos referenciados.
Devuelve los índices a la variable de predicción X (según su solicitud) y para los regresores y también. Además, tiene la opción de aplicar una ''máscara'' a las variables de predicción X mientras desliza la ventana. Por ejemplo, con una ventana de 21 pasos, puede seleccionar [T-2 T-3 T-5 T-8 T-13 T-21] para X y T para y
También puede cambiar el horizonte de predicción: cuántos pasos en el futuro los índices de y son. Por ejemplo X = [T-1 T-2] e y = T + 2
Con suerte, alguien más encontrará esto útil.
% 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
También puede encontrar el código aquí: https://au.mathworks.com/matlabcentral/fileexchange/58730-get-sliding-indexes-numrecords--windowlag--predhorizon--windowpattern--stepsize-
Tengo series de tiempo, y estoy aplicando alguna función definida por el usuario a cada W elementos en series de tiempo.
En este momento solo estoy usando for loop, ventana deslizante de tamaño W y aplicar mi función a elementos en una ventana en cada iteración.
Estoy usando Matlab y es muy ineficiente con un "bucles for", así que me encantaría vectorizar esta operación.
Como solución, veo transformar la señal con longitud N en una matriz con tamaño (N - 1, W) donde cada fila es una serie de tiempo en diferentes ventanas y aplica función a esta matriz.
Entonces, mis preguntas son:
- ¿Cómo transformar mi serie de tiempo inicial a tal matriz?
- Digamos que estoy deslizando la ventana con el paso X. De modo que no aparecerá la matriz (N - 1, W), sino ((N - 1) / X, W). (Cada X fila de la matriz en [1])
Ejemplo:
Digamos que mi serie de tiempo es:
T = [1, 5, 6, 8, 10, 14, 22]
W = 3
X = 1
=> Me encantaría conseguir
[[1, 5, 6],
[5, 6, 8],
[6, 8, 10],
[8, 10, 14],
[10, 14, 22]]
Si
W = 3
X = 2
=> Me encantaría conseguir
[[1, 5, 6],
[6, 8, 10],
[10, 14, 22]]
Crear los índices correctos con bsxfun
sin duda ayudaría:
ind = bsxfun(@plus, 1:W, (0:X:numel(T)-W).'');
out = T(ind);
Crear los índices correctos es el primer paso, delineado por la primera línea de código. Lo que hace este código es que crea una matriz 2D donde cada fila son los elementos a acceder por ventana de interés. Si desea obtener una intuición sobre cómo el código genera los índices, observe específicamente el primer caso donde X = 1;
y W = 3;
.
Podemos ver que la primera fila consiste en acceder a los elementos 1, 2 y 3. La segunda fila consiste en acceder a los elementos 2, 3, 4 ... hasta la última fila, que es 5, 6, 7. Podemos ver que tenemos que acceder a los elementos vecinos en una ventana, por lo que los índices básicos deben ir de 1, 2, 3 o, en general, de 1 a W
Ahora necesitamos compensar estos índices para que estén centrados en los elementos correctos en T
por ventana. El desplazamiento para la primera ventana es simplemente 0, el siguiente desplazamiento para la segunda ventana es simplemente 1 hasta la última fila, que es 3. Vemos que para cada fila, agregamos 1 más a los índices base a medida que aumentan las filas. Por lo tanto, agregamos 1 a cada índice base para la segunda fila, luego 2 para cada índice base en la tercera fila y así sucesivamente. Si agrega los índices base con los índices de compensación, finalmente obtendrá los índices correctos para acceder a los elementos correctos en T
Del mismo modo si X = 2;
y W = 3;
, vemos que todavía tenemos índices base de 1, 2, 3. Sin embargo, los elementos correctos para acceder ahora son 1, 2, 3 para la primera fila, luego 3, 4, 5 para la segunda fila y luego 5, 6, 7 para la tercera fila. Para cada fila, ahora compensamos los índices base por 2 en lugar de 1 ahora. Por lo tanto, en la segunda fila agregamos 2 a cada índice base, luego agregamos 4 a cada índice base para la tercera fila y así sucesivamente.
En general, los índices base se crean usando un vector 1:W
y los índices de compensación se crean usando un vector 0:X:numel(T)-W
. La resta de W
es necesaria para que no salgamos de los límites cuando se muestrea la señal según el requisito. Para crear estos índices de los que acabamos de hablar, bsxfun
maneja esto para nosotros.
Creamos un vector de fila de 1:W
que corresponde a los índices base y un vector de columna de (0:X:numel(T)-W).''
que corresponde a los desplazamientos por ventana. Tenga en cuenta que el primer desplazamiento comienza en 0, luego aumentamos en X
cantidad para asegurarnos de que se calcula el centro correcto para colocar nuestros índices base en. Nos detenemos hasta que golpeemos los elementos numel(T)-W
, que es la condición que usted ha indicado. Al usar bsxfun
, se bsxfun
dos matrices 2D temporales donde el vector de fila se duplica para tantas filas como filas hay en el vector de columna y el vector de columna se duplica para tantas columnas como haya en el vector de fila. Una vez que agrega estas dos matrices, obtiene la matriz de índice resultante.
Ejecutando el código con W = 3;
y X = 1;
da:
>> 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
Del mismo modo si W = 3;
y X = 2;
también obtenemos:
>> 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
Puede verificar por sí mismo que estos índices corresponden a los elementos correctos en T
para crear su matriz deseada en este caso.
Finalmente usamos esto para indexar en nuestra matriz para captar los elementos correctos:
out = T(ind);
Haciendo esto para X = 1;
y W = 3;
da:
>> out = T(ind)
out =
1 5 6
5 6 8
6 8 10
8 10 14
10 14 22
Del mismo modo para X = 2;
y W = 3;
da:
>> out = T(ind)
out =
1 5 6
6 8 10
10 14 22