matlab - 优化获取每个矢量与大数组中所有其他矢量之间的角度

时间:2013-08-02 22:41:42

标签: matlab optimization angle sparse-matrix

我试图获得大数组中每个向量之间的角度(1896378x4 -EDIT:这意味着我需要1.7981e+12个角度......太大了,但是如果有空间来优化代码,反正让我知道)。这太慢了 - 我还没有看到它完成。以下是优化我采取的步骤:

首先,逻辑上我(我想)我想要的(只需使用Bt=rand(N,4)进行测试):

    [ro,col]=size(Bt);
    angbtwn = zeros(ro-1); %too long to compute!! total non-zero = ro*(ro-1)/2
    count=1;
    for ii=1:ro-1
        for jj=ii+1:ro
            angbtwn(count) = atan2(norm(cross(Bt(ii,1:3),Bt(jj,1:3))), dot(Bt(ii,1:3),Bt(jj,1:3))).*180/pi;
            count=count+1;
        end
    end

所以,我虽然尝试对它进行矢量化,并且摆脱了非内置函数:

[ro,col]=size(Bt);
% angbtwn = zeros(ro-1); %TOO LONG!
for ii=1:ro-1
    allAxes=Bt(ii:ro,1:3);
    repeachAxis = allAxes(ones(ro-ii+1,1),1:3);
    c = [repeachAxis(:,2).*allAxes(:,3)-repeachAxis(:,3).*allAxes(:,2)
        repeachAxis(:,3).*allAxes(:,1)-repeachAxis(:,1).*allAxes(:,3)
        repeachAxis(:,1).*allAxes(:,2)-repeachAxis(:,2).*allAxes(:,1)];
    crossedAxis = reshape(c,size(repeachAxis));
    normedAxis = sqrt(sum(crossedAxis.^2,2));
    dottedAxis = sum(repeachAxis.*allAxes,2);
    angbtwn(1:ro-ii+1,ii) = atan2(normedAxis,dottedAxis)*180/pi;
end
angbtwn(1,:)=[]; %angle btwn vec and itself
%only upper left triangle are values...

还是太长了,甚至预先分配......所以我尝试做稀疏,但没有正确执行:

[ro,col]=size(Bt);
%spalloc:
angbtwn = sparse([],[],[],ro,ro,ro*(ro-1)/2);%zeros(ro-1); %cell(ro,1)
for ii=1:ro-1
    ...same
    angbtwn(1:ro-ii+1,ii) = atan2(normedAxis,dottedAxis)*180/pi; %WARNED: indexing = >overhead
    % WHAT? Can't index sparse?? what's the point of spalloc then?
end

因此,如果我的逻辑可以改进,或者稀疏是真的要走的路,而我无法正确实现,请告诉我改进的地方。感谢您的帮助。

2 个答案:

答案 0 :(得分:0)

您是否试图在Bt中获取每个矢量之间的角度?如果Bt有200万个向量,每个向量(显然)需要一个内部产品来获得它们之间的角度。我不知道任何类型的优化都有助于在一台机器上的MATLAB中以合理的时间完成此操作。

在任何情况下,您都可以将此问题转换为单位向量矩阵之间的矩阵乘法:

N=1000;
Bt=rand(N,4); % for testing. A matrix of N (row) vectors of length 4.
[ro,col]=size(Bt);

magnitude = zeros(N,1); % the magnitude of each row vector.
units = zeros(size(Bt)); % the unit vectors

% Compute the unit vectors for the row vectors
for ii=1:ro
  magnitude(ii) = norm(Bt(ii,:));
  units(ii,:) = Bt(ii,:) / magnitude(ii);
end

angbtwn = acos(units * units') * 360 / (2*pi);

但是在矩阵乘法期间你会因为大的N而耗尽内存。

答案 1 :(得分:0)

您可能希望使用距pdist距离的'cosine'来计算1-cos(angbtwn)
这种方法的另一个好处是,它不会计算n^2值,但只会计算.5*(n-1)*n个唯一值:)