【问题标题】:Efficient way to compute multiple euclidean distances Matlab计算多个欧几里德距离Matlab的有效方法
【发布时间】:2013-03-22 17:02:44
【问题描述】:

我正在训练我自己的自组织地图来聚类颜色值。现在我想制作某种U-matrix 来显示节点与其直接邻居之间的欧几里得距离。我现在的问题是,我的算法效率很低!!肯定有一种方法可以更有效地计算?

function displayUmatrix(dims,weights) %#dims is [30 30], size(weights) = [900 3], 
                                      %#consisting of values between 1 and 0

hold on; 
axis off;
A = zeros(dims(1), dims(2), 3);
B = reshape(weights',[dims(1) dims(2) size(weights,1)]);
if size(weights,1)==3
    for i=1:dims(1)
        for j=1:dims(2)
            if i~=1
                if j~=1
                    A(i,j,:)=A(i,j,:)+(B(i,j,:)-B(i-1,j-1,:)).^2;
                end
                A(i,j,:)=A(i,j,:)+(B(i,j,:)-B(i-1,j,:)).^2;
                if j~=dims(2)
                    A(i,j,:)=A(i,j,:)+(B(i,j,:)-B(i-1,j+1,:)).^2;
                end
            end
            if i~=dims(1)
                if j~=1
                    A(i,j,:)=A(i,j,:)+(B(i,j,:)-B(i+1,j-1,:)).^2;
                end
                A(i,j,:)=A(i,j,:)+(B(i,j,:)-B(i+1,j,:)).^2;
                if j~=dims(2)
                    A(i,j,:)=A(i,j,:)+(B(i,j,:)-B(i+1,j+1,:)).^2;
                end
            end 
            if j~=1
                A(i,j,:)=A(i,j,:)+(B(i,j,:)-B(i,j-1,:)).^2;
            end
            if j~=dims(2)
                A(i,j,:)=A(i,j,:)+(B(i,j,:)-B(i,j+1,:)).^2;
            end
            C(i,j)=sum(A(i,j,:));
        end
    end
    D = flipud(C);
    maximum = max(max(D));
    D = D./maximum;
    imagesc(D)
else
    error('display function does only work on 3D input');
end
hold off;
drawnow;

结束

谢谢,马克斯

【问题讨论】:

  • 我建议您沿 3 个维度中的每一个维度使用 2D 卷积核,以一次获得每个点与其所有邻居之间的总距离,然后将其平方。不过,我不确定这是否是您想要的,因为在您的代码中,在添加计算距离之前,您会在每一步对其进行平方。不过,您可以对 B 矩阵进行多次卷积,例如与内核 [1 -1; 0 -1] 一次性得到所有的 B(i, j, :) - B(i - 1, j + 1, :)。 (如果我错了,请有人纠正我)。但不确定它会更快。
  • 感谢您的快速回答。我想说这无论如何都会提高代码的可读性。我会在 Matlab 文档中查找它。

标签: arrays matlab euclidean-distance


【解决方案1】:

您可以通过以下方式计算每个点到其右侧邻居的(平方)距离:

sum((B(:,1:end-1,:) - B(:,2:end,:)).^2, 3)

同样,您计算每个点到下一个点的距离,以及两条对角线上的距离。对于边界上的点,您没有所有这些值,因此您用零填充它们。然后,您将距离相加,然后将它们除以一个点必须获得的与所有邻居的平均距离。

这是我的代码:

%calculate distances to neighbors
right = sum((B(:,1:end-1,:)- B(:,2:end,:)).^2, 3);
bottom = sum((B(1:end-1,:,:)- B(2:end,:,:)).^2, 3); zeros();
diag1 = sum((B(1:end-1,1:end-1,:)- B(2:end,2:end,:)).^2, 3);
diag2 = sum((B(2:end,2:end,:)- B(1:end-1,1:end-1,:)).^2, 3);

%pad them with zeros to the correct size
rightPadded = [right zeros(dim(1) , 1)];
leftPadded = [zeros(dim(1) , 1) right];

botomPadded = [bottom; zeros(1,dim(2))];
upPadded = [zeros(1,dim(2));bottom];

bottomRight = zeros(dim(1), dim(2));
bottomRight(1:end-1,1:end-1) = diag1;
upLeft = zeros(dim(1), dim(2));
upLeft(2:end,2:end) = diag1;

bottomLeft = zeros(dim(1), dim(2));
bottomLeft(1:end-1,2:end) = diag2;
upRight = zeros(dim(1), dim(2));
upRight(2:end,1:end-1) = diag2;

%add distances to all neighbors
sumDist = rightPadded + leftPadded + bottomRight + upLeft + bottomLeft + upRight;

%number of neighbors a point has
neighborNum = zeros(dim(1), dim(2)) + 8;
neighborNum([1 end],:) = 5;
neighborNum(:,[1 end]) = 5;
neighborNum([1 end],[1 end]) = 3;

%divide summed distance by number of neighbors
avgDist = sumDist./neighborNum;

它都是矢量化的,所以它应该比你的版本更快。 如果您想要精确的 U 矩阵,您可以将平均距离与相邻距离交错。

【讨论】:

  • 做得很好,谢谢,这对时间复杂度有很大帮助!
猜你喜欢
  • 2017-03-21
  • 1970-01-01
  • 2017-05-03
  • 2014-07-17
  • 2013-04-07
  • 2017-10-09
  • 1970-01-01
相关资源
最近更新 更多