是的。拥有bsxfun 和permute 的强大力量,有sum 的一面,还有reshape 的破折号。这是第一部分,您将计算S1 中的一个点与S2 中的另一个点之间的成对距离:
out = reshape(sqrt(sum(bsxfun(@minus, S1, permute(S2, [3 2 1])).^2, 2)), size(S1,1), size(S2,1));
您现在需要做的最后一件事是确定S2 中与每个S1 最接近的向量。这可以使用min 来完成:
[dist,ind] = min(out, [], 2);
dist 将包含S1 中的点与S2 中的点之间的最小距离,ind 会告诉您那是哪个点。
这段代码看起来很吓人,但让我们把它分解成小块。
permute(S2, [3 2 1]):这采用矩阵S2,它是一个M x D 矩阵并打乱维度使其成为1 x D x M 矩阵......现在我们为什么要这样做?让我们进入下一部分,它会更有意义。
-
bsxfun(@minus, S1, ...):bsxfun 代表 Binary Singleton EXpansion FUNction。 bsxfun 所做的是,如果您有两个输入,其中一个或两个输入都具有单个维度,或者如果两个输入中的任何一个只有一个值为 1 的维度,则每个输入都在其单个维度中复制以匹配大小另一个输入,然后将逐元素操作应用于这些输入以产生您的输出。在这种情况下,我想将这两个新形成的输入相减。
因此,鉴于S1 是N x D...或者从技术上讲,这是N x D x 1,并且鉴于S2 是M x D,我将其置换为1 x D x M,我们将创建一个长度为N x D x M 的新矩阵。第一个输入将自身复制为一个 3D 矩阵,其中每个切片等于S1,即N x D。 S2 现在是一个 3D 矩阵,但它的表示方式是原始矩阵中的每一行都是 3D 矩阵中的一个切片,其中每个切片仅包含一行。这会为 N 行重复。
我们现在应用@minus 操作,其效果是对于这个新矩阵中的每个输出切片i,这为您提供了S2 中的点i 与所有S1 中的其他点。例如,对于切片#1,行#1 为您提供S2 中的点#1 和S1 中的点#1 之间的组件差异。第 2 行为您提供了 S2 中的第 1 点和 S1 中的第 2 点之间的组件差异,依此类推。
sum((...).^2, 2):我们想找到一个点和另一个点之间的欧几里得距离,所以我们将这些距离在每一列上独立求和。这会产生一个新的 3D 矩阵,其中每个切片包含 N 值,其中每个 M 点都有 N 距离。例如,第一个切片将为您提供从 S2 中的点 #1 到 S1 中的所有其他点的距离。
out = reshape(..., size(S1,1), size(S2,1));:我们现在对其进行整形,使其成为M x N 矩阵,以便(i,j) 的每一行和列对为您提供S1 和@987654379 中i 点之间的距离@ in S2,从而完成计算。
执行[dist,ind] = min(out, [], 2); 确定S1 中的一个点与S2 中的其他点之间的最小距离。 dist 会告诉你最小的距离,而ind 会告诉你它是哪个向量。因此,对于dist 中的每个元素,它会为您提供S1 中的点i 与S2 之一之间的最小距离,而ind 会告诉您哪个向量属于S2。
我们可以通过使用您提出的遍历每对点并计算范数的方法来验证这是否为我们提供了正确的结果。让我们创建S1 和S2:
S1 = [1 2 3; 4 5 6; 7 8 9; 10 11 12];
S2 = [-1 -1 -1; 0 9 8];
展示更整齐:
>> S1
S1 =
1 2 3
4 5 6
7 8 9
10 11 12
>> S2
S2 =
-1 -1 -1
0 9 8
使用循环方法,我们有以下代码:
out = zeros(size(S1,1), size(S2,1));
for ii = 1 : size(S1,1)
for jj = 1 :size(S2,1)
out(ii,jj) = norm(S1(ii,:) - S2(jj,:));
end
end
我们得到这个矩阵:
>> out
out =
5.3852 8.6603
10.4881 6.0000
15.6525 7.1414
20.8327 10.9545
同样,如果我们运行我编写的代码,我们也会得到:
>> out = reshape(sqrt(sum(bsxfun(@minus, S1, permute(S2, [3 2 1])).^2, 2)), size(S1,1), size(S2,1))
out =
5.3852 8.6603
10.4881 6.0000
15.6525 7.1414
20.8327 10.9545
为了完成这个过程,让我们找到最小的距离和对应的向量:
>> [dist,ind] = min(out, [], 2);
>> dist
dist =
5.3852
6.0000
7.1414
10.9545
>> ind
ind =
1
2
2
2
因此,对于S1 中的第一个向量,S2 中与此最近的向量是第一个向量,距离为 5.3852。同样,S1 的第二个向量,S2 中最接近的向量是第二个,距离为 6。您可以对其他值重复此操作,看看是否正确。