Optimize nested for loop for calculating xcorr of matrix rows

冷暖自知 提交于 2019-12-10 11:04:44

问题


I have 2 nested loops which do the following:

  • Get two rows of a matrix
  • Check if indices meet a condition or not
  • If they do: calculate xcorr between the two rows and put it into new vector
  • Find the index of the maximum value of sub vector and replace element of LAG matrix with this value

I dont know how I can speed this code up by vectorizing or otherwise.

b=size(data,1);
F=size(data,2);
LAG= zeros(b,b);  

for i=1:b
    for j=1:b
        if j>i
            x=data(i,:);
            y=data(j,:);
            d=xcorr(x,y);
            d=d(:,F:(2*F)-1); 
            [M,I] = max(d);
            LAG(i,j)=I-1;
            d=xcorr(y,x);
            d=d(:,F:(2*F)-1);
            [M,I] = max(d);
            LAG(j,i)=I-1;
        end
    end
end

回答1:


First, a note on floating point precision...

You mention in a comment that your data contains the integers 0, 1, and 2. You would therefore expect a cross-correlation to give integer results. However, since the calculation is being done in double-precision, there appears to be some floating-point error introduced. This error can cause the results to be ever so slightly larger or smaller than integer values.

Since your calculations involve looking for the location of the maxima, then you could get slightly different results if there are repeated maximal integer values with added precision errors. For example, let's say you expect the value 10 to be the maximum and appear in indices 2 and 4 of a vector d. You might calculate d one way and get d(2) = 10 and d(4) = 10.00000000000001, with some added precision error. The maximum would therefore be located in index 4. If you use a different method to calculate d, you might get d(2) = 10 and d(4) = 9.99999999999999, with the error going in the opposite direction, causing the maximum to be located in index 2.

The solution? Round your cross-correlation data first:

d = round(xcorr(x, y));

This will eliminate the floating-point errors and give you the integer results you expect.

Now, on to the actual solutions...


Solution 1: Non-loop option

You can pass a matrix to xcorr and it will perform the cross-correlation for every pairwise combination of columns. Using this, you can forego your loops altogether like so:

d = round(xcorr(data.'));
[~, I] = max(d(F:(2*F)-1,:), [], 1);
LAG = reshape(I-1, b, b).';


Solution 2: Improved loop option

There are limits to how large data can be for the above solution, since it will produce large intermediate and output variables that can exceed the maximum array size available. In such a case for loops may be unavoidable, but you can improve upon the for-loop solution above. Specifically, you can compute the cross-correlation once for a pair (x, y), then just flip the result for the pair (y, x):

% Loop over rows:
for row = 1:b

  % Loop over upper matrix triangle:
  for col = (row+1):b

    % Cross-correlation for upper triangle:
    d = round(xcorr(data(row, :), data(col, :)));
    [~, I] = max(d(:, F:(2*F)-1));
    LAG(row, col) = I-1;

    % Cross-correlation for lower triangle:
    d = fliplr(d);
    [~, I] = max(d(:, F:(2*F)-1));
    LAG(col, row) = I-1;

  end

end


来源:https://stackoverflow.com/questions/47812252/optimize-nested-for-loop-for-calculating-xcorr-of-matrix-rows

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!