Оптимизация кода, удаление цикла for

Я пытаюсь удалить выбросы из серии тиковых данных, следуя Brownlees & Gallo 2006 (если вам это интересно).

Код работает нормально, но, учитывая, что я работаю с очень длинными векторами (самый большой из них имеет 20 м наблюдений, и после 20 часов он не был завершен), мне было интересно, как его ускорить.

Что я сделал до сих пор:
я изменил формат времени и даты на числовой двойной, и я увидел, что это экономит довольно много времени при обработке и МНОГО ПАМЯТИ.
Я выделил память для векторов:

[n] = size(price);
 x = price;
    score = nan(n,'double');           %using tic and toc I saw that nan requires less time than zeros
    trimmed_mean = nan(n,'double');
    sd = nan(n,'double');
    out_mat = nan(n,'double');

Вот петля, которую я хотел бы удалить. Я читал, что векторизация значительно ускорит работу, особенно при использовании длинных векторов.

for i = k+1:n
    trimmed_mean(i) = trimmean(x(i-k:i-1 & i+1:i+k),10,'round');  %trimmed mean computed on the 'k' closest observations to 'i' (i is excluded)
    score(i) = x(i) - trimmed_mean(i);
    sd(i) = std(x(i-k:i-1 & i+1:i+k)); %same as the mean
    tmp = abs(score(i)) > (alpha .* sd(i) + gamma);
    out_mat(i) = tmp*1;
end

Вот что я пытался сделать

trimmed_mean=trimmean(regroup_matrix,10,'round',2);
score=bsxfun(@minus,x,trimmed_mean);
sd=std(regroup_matrix,2);
temp = abs(score) > (alpha .* sd + gamma);
out_mat = temp*1;

Но учитывая, что я совершенно новичок в Matlab, я не знаю, как правильно построить матрицу соседних наблюдений. Я просто думаю, что это должно быть в форме: regroup_matrix= nan (n,2*k).

РЕДАКТИРОВАТЬ: Чтобы быть конкретным, то, что я пытаюсь сделать (и я не могу):
Учитывая вектор-столбец "x" (n, 1) для каждого наблюдения "i" в "x", я хочу возьмите "k" соседние наблюдения с "i" (от ik до i-1 и от i+1 до i+k) и поместите эти наблюдения в строки матрицы (n, 2*k).

РЕДАКТИРОВАТЬ 2: я внес несколько изменений в код и думаю, что приближаюсь к решению. Я разместил еще один вопрос, касающийся того, что, по моему мнению, сейчас является проблемой:
Matlab: заполнение строк матрицы с использованием скользящих интервалов из вектора-столбца без цикла for

То, что я пытаюсь сделать сейчас, это:

[n] = size(price,1);
x = price;
[j1]=find(x);
matrix_left=zeros(n, k,'double');
matrix_right=zeros(n, k,'double');
toc
matrix_left(j1(k+1:end),:)=x(j1-k:j1-1);

matrix_right(j1(1:end-k),:)=x(j1+1:j1+k);

matrix_group=[matrix_left matrix_right];
trimmed_mean=trimmean(matrix_group,10,'round',2);
score=bsxfun(@minus,x,trimmed_mean);
sd=std(matrix_group,2);
temp = abs(score) > (alpha .* sd + gamma);
outmat = temp*1;

У меня проблемы с созданием matrix_left и matrix_right. j1, который я использую для индексации, представляет собой вектор-столбец с индексами ценовых наблюдений. Выход просто

j1=[1:1:n]

цена представляет собой вектор-столбец двойного размера с размером (n, 1)


person Gio    schedule 07.02.2014    source источник
comment
x выглядит как вектор, но x(i,tmp) = price(i-1,tmp) может расширить его до двумерной матрицы. Это намеренно?   -  person aschepler    schedule 07.02.2014
comment
k не инициализирован.   -  person Daniel    schedule 07.02.2014
comment
@aschepler Нет, это не намеренно, это опечатка. k инициализируется, я вставляю его как параметр при вызове функции. то же самое для альфы и гаммы.   -  person Gio    schedule 08.02.2014
comment
Какое значение вы хотите присвоить «regroup_matrix» после его инициализации?   -  person McMa    schedule 10.02.2014
comment
@McMa каждая строка матрицы должна состоять из следующих элементов x (i-k:i-1 и i+1:i+k). Если конкретность может помочь, я в настоящее время использую k = 5. Я думаю, что нужно построить две отдельные матрицы, а затем объединить их.   -  person Gio    schedule 10.02.2014
comment
знаете ли вы, что выражение i-k:i-1 & i+1:i+k будет возвращать двоичный вектор с истинами всякий раз, когда ни i-k:i-1, ни i-k:i-1 & i+1:i+k не равны нулю? этот синтаксис кажется немного странным. Вернемся к вашему вопросу: попробуйте создать вектор-строку из значений x, а затем создать матрицу с reshape(x,M,N).   -  person McMa    schedule 10.02.2014
comment
@McMa Я понятия не имел, я не могу достаточно отметить, что я новичок в Matlab, а индексы с индексами - это то, чего я до сих пор не понимаю. Это не входило в мои намерения и могло бы объяснить, почему результаты кажутся немного странными. Вернемся к моему вопросу: не могли бы вы объяснить мне, как?   -  person Gio    schedule 10.02.2014


Ответы (2)


Для изменения формы вы можете сделать следующее:

idxArray = bsxfun(@plus,(k:n)',[-k:-1,1:k]);
reshapedArray = x(idxArray);
person Jonas    schedule 10.02.2014
comment
большое спасибо, это был правильный путь. Я просто немного изменил его, чтобы он соответствовал моим потребностям, так как вы пишете код, он также принимал отрицательные индексы (для первых k наблюдений) и индексы вне ряда (для последних k наблюдений). - person Gio; 10.02.2014

Благодаря Джонасу, который показал мне путь, я придумал это:

idxArray_left=bsxfun(@plus,(k+1:n)',[-k:-1]);           %matrix with index of left neighbours observations
idxArray_fill_left=bsxfun(@plus,(1:k)',[1:k]);          %for observations from 1:k I take the right neighbouring observations, this way when computing mean and standard deviations there will be no problems.
matrix_left=[idxArray_fill_left; idxArray_left];        %Just join the two matrices and I have the complete matrix of left neighbours
idxArray_right=bsxfun(@plus,(1:n-k)',[1:k]);            %same thing as left but opposite.
idxArray_fill_right=bsxfun(@plus,(n-k+1:n)',[-k:-1]);
matrix_right=[idxArray_right; idxArray_fill_right];      
idx_matrix=[matrix_left matrix_right];                  %complete index matrix, joining left and right indices
neigh_matrix=x(idx_matrix);                             %exactly as proposed by Jonas, I fill up a matrix of observations from 'x', following idx_matrix indexing
trimmed_mean=trimmean(neigh_matrix,10,'round',2);
score=bsxfun(@minus,x,trimmed_mean);
sd=std(neigh_matrix,2);
temp = abs(score) > (alpha .* sd + gamma);
outmat = temp*1;  

Еще раз большое спасибо Йонасу. Вы действительно сделали мой день!
Спасибо также всем, кто заглянул в вопрос и попытался помочь!

person Gio    schedule 10.02.2014