4

使用 MATLAB,想象一个 Nx6 数字数组,它表示 N 段,具有 3+3=6 个初始和结束点坐标。

假设我有一个function Calc_Dist( Segment_1, Segment_2 )将两个 1x6 数组作为输入,并且经过一些操作返回一个标量,即这两个段之间的最小欧几里得距离。

我想计算列表的所有 N 段之间的成对最小距离,但希望避免双循环这样做。

我无法理解 MATLAB 函数的文档bsxfun,所以我无法完成这项工作。为了一个最小的例子(距离计算显然不正确):

function scalar = calc_dist( segment_1, segment_2 )
         scalar = sum( segment_1 + segment_2 )
end

和主要

Segments = rand( 1500, 6 )
Pairwise_Distance_Matrix = bsxfun( @calc_dist, segments, segments' )

有什么办法可以做到这一点,还是我被迫使用双循环?

谢谢你的任何建议

4

2 回答 2

3

不幸的是,我没有看到任何比双循环“更智能”(即阅读速度更快)的解决方案。出于速度考虑,我将这些点组织为一个 6× N数组,而不是其他方式,因为在 MATLAB 中列访问比行访问快得多。

所以:

N = 150000;
Segments = rand(6, N);
Pairwise_Distance_Matrix = Inf(N, N);
for i = 1:(N-1)
        for j = (i+1):N
                Pairwise_Distance_Matrix(i,j) = calc_dist(Segments(:,i), Segments(:,j));
        end;
end;

Minimum_Pairwise_Distance = min(min(Pairwise_Distance_Matrix));

与常识相反,现在 MATLAB 中的显式循环比arrayfun,cellfunstructfun;之类的更快。bsxfun在速度方面胜过其他一切,但不适用于您的情况。

于 2014-10-06T15:10:36.563 回答
3

我认为你需要pdist而不是bsxfun. pdist可以以两种不同的方式使用,其中第二种适用于您的问题:

  • 具有内置的距离函数,以字符串形式提供,例如'euclidean''hamming'

  • 使用自定义距离函数,您提供的句柄。

第二种情况,距离函数

必须是形式

     function D2 = distfun(XI, XJ),

将包含 的单行的1×N向量、包含 的多行的× 矩阵作为参数,并返回距离的 ×向量,其第 个元素是观测值和之间的距离。XIXM2NXJXM21D2JXIXJ(J,:)

尽管文档没有说明,但很可能第二种方法不如第一种有效(谁知道,双循环甚至可能更快),但您可以使用它。您需要定义您的功能,使其满足规定的条件。使用您的示例函数很容易:对于这一部分,您将使用bsxfun

function scalar = calc_dist( segment_1, segment_2 )
    scalar = sum(bsxfun(@plus, segment_1, segment_2), 2);
end

另请注意

  • pdist适用于行(而不是列),这是您所需要的。
  • pdist通过利用任何距离函数必须具有的属性来减少操作。即,已知元素到自身的距离为零;由于对称性,每对的距离只能计算一次。如果要以矩阵的形式排列输出,请使用squareform.

所以,在你的实际距离函数被适当修改后(这可能是困难的部分),使用:

distances = squareform(pdist(segments, @calc_dist));

例如:

N = 4;
segments = rand(N,6);
distances = squareform(pdist(segments, @calc_dist));

生产

distances =
         0    6.1492    7.0886    5.5016
    6.1492         0    6.8559    5.2688
    7.0886    6.8559         0    6.2082
    5.5016    5.2688    6.2082         0
于 2014-10-06T15:24:39.733 回答