Optimización del filtro de marca de tiempo en MATLAB - Trabajar con conjuntos de datos muy grandes
Estoy escribiendo un programa en MATLAB (debo usar MATLAB y realmente no puedo usar un MEX) para filtrar grandes cantidades de datos.
Uno de los filtros que necesito implementar requiere que compare un vector de marca de tiempo frente a una lista de los tiempos "malos" conocidos en torno a los cuales no pueden aparecer otras marcas de tiempo.
Un vector típico de marca de tiempo tiene aproximadamente 2,000,000 entradas, y tengo una lista de aproximadamente 300,000 "malos tiempos".
Aquí hay un ejemplo de trabajo, siTIME=[1, 2.3, 5.5, 9.1, 10];
yBAD_TIMES=[5.2, 9.3];
, y tenemos una toleranciatolerance=0.25;
, entonces todas las marcas de tiempo enTIME
Entre4.95 and 5.45
y9.05 and 9.55
debe ser borrado. Esto significa que el vector limpiadoTIME_CLEAN
debe ser igual aTIME_CLEAN=[1, 2.3, 5.5, 10];
.
Este problema es sencillo de resolver, y lo he resuelto de 4 o 5 formas diferentes. Sin embargo, para un trabajo de marca de tiempo de 1,000,000, este problema puede tardar una hora en calcularse.
Estoy buscando resolver este tipo de problema en menos de 2 minutos en una estación de trabajo Core-i7 para que este filtro sea viable con tantas entradas de tiempo.
He incluido una versión de trabajo de este código. Entiendo la vectorización de código y funciones tales comobsxfun()
puede ayudar, pero la mejora es marginal en relación con el tipo de eficiencia que necesito para este filtro.
¿Hay formas muy inteligentes de resolver este problema de una manera muy eficiente? Cualquier ayuda sería muy apreciada.
PD El código de abajo está completo; genera todos los datos necesarios para configurar el problema y lo resuelve (¡aunque MUY lentamente!). Cambiar elNO_OF_TIMESTAMPS
variable a algo más grande (como 1,000,000) para verlo arrastrarse!
clear all %% CLEAR WORKSPACE
close all %% CLOSE FIGURES
clc %% CLEAR COMMAND WINDOW
NO_OF_TIMESTAMPS=10000; %% NUMBER OF TIMESTAMPS IN ORIGINAL DATA
TOLERANCE=2; %% TOLERANCE AROUND TIMESTAMP
A=sort(randi(NO_OF_TIMESTAMPS/10,NO_OF_TIMESTAMPS,1)); %% GENERATE ARTIFICIAL TIMESTAMPS
B=unique(sort(round(randi([NO_OF_TIMESTAMPS/2,NO_OF_TIMESTAMPS*5],[NO_OF_TIMESTAMPS/10,1])/10))); %% GENERATE ARTIFICIAL LIST OF BAD TIMESTAMPS
B_LB=B-TOLERANCE; %% CREATE A LIST OF LOWERBOUND BAD TIMESTAMPS
B_UB=B+TOLERANCE; %% CREATE A LIST OF UPPERBPUND BAD TIMESTAMPS
B_RANGE=[B_LB B_UB]; %% AUGMENTED MATRIX COMPOSED OF VECTORS B_LB and B_UB
A_ROWS=size(A,1); %% SIZE OF A;
B_ROWS=size(B,1); %% SIZE OF B;
tic; %% START TIMER
A_TO_CLEAN=ones(A_ROWS,1); %% BOOLEAN VECTOR TO BE USED IN FILTERING
for ii=1:A_ROWS
for jj=1:B_ROWS
if A(ii)>=B_RANGE(jj,1) && A(ii)<=B_RANGE(jj,2) %% CHECK EACH MEMBER OF A VERSUS EACH MEMBER OF B_RANGE
A_TO_CLEAN(ii)=0; %% SET INDEX VECTOR A_TO_CLEAN = 0 SO THAT WE CAN DELETE LATER
break; %% A(ii) CAN ONLY BE ERASED ONCE, SO BREAK jj LOOP AND GO TO NEXT ii
end
end
end
CLEAN=A(~~A_TO_CLEAN); %% DELETE A VIA LOGICAL INDEXING
toc; %% END TIMER
clearvars -except A B_RANGE CLEAN %% ONLY SHOW RELEVANT VARIABLES