给定:维度为{S1, S2}
的向量的两组D
。 S1
由N*D
矩阵表示,因此S2
由M*D
矩阵表示。
我正在寻找一种优雅的方式来获取s1
S1
中s2
中S2
中每个向量dist = norm(s1 - s2);
和相应距离。
一个简单的方法当然是有两个for循环并得到
{{1}}
然而,必须有一种更优雅和有效的方法来做到这一点。
答案 0 :(得分:9)
烨。拥有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
代表 B inary S ingleton E X pansion FUN 强> ction。 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
,我们将创建一个S1
长的新矩阵。第一个输入将自身复制为3D矩阵,其中每个切片等于N x D
,即S2
。 N
现在是一个3D矩阵,但它以这样一种方式表示,即原始矩阵中的每一行都是3D矩阵中的一个切片,其中每个切片只包含一行。对于@minus
行,这会重复。
我们现在应用i
操作,其效果是对于此新矩阵中的每个输出切片i
,这为您提供了点S2
之间的组件明智差异在S1
中S2
中的所有其他点。例如,对于切片#1,行#1为您提供S1
中的点#1和S2
中的点#1之间的组件明智差异。第2行为您提供S1
中的第1点和第2点sum((...).^2, 2)
之间的组件明智差异,依此类推。
N
:我们希望找到一个点与另一个点之间的欧几里德距离,因此我们将每个列的平均距离相加。这会生成一个新的3D矩阵,其中每个切片包含N
个值,其中每个M
点的距离都为S2
。例如,第一个切片将为您提供S1
中#1点的距离与out = reshape(..., size(S1,1), size(S2,1));
中所有其他点的距离。
M x N
:我们现在对其进行整形,使其成为(i,j)
矩阵,以便i
的每对行和列对都为您提供点{{1}之间的距离} S1
中的j
和S2
中的[dist,ind] = min(out, [], 2);
,从而完成了计算。
执行S1
确定S2
中某点与dist
中其他点之间的最小距离。 ind
会给你最小的距离,dist
会告诉你它是哪个向量。因此,对于i
中的每个元素,它会为您提供S1
中的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
中的第一个向量,S1
中与此最接近的向量是第一个,距离为5.3852。同样,S2
中的第二个向量,{{1}}中最接近的向量是第二个向量,距离为6.您可以对其他值重复此操作,并查看它是否正确。
答案 1 :(得分:5)
一行怎么样?
[dist, ind] = min(pdist2(S2,S1));
ind
是S2
中S1
中每个向量的最近向量的索引,dist
给出了相应的最小距离。
S1 = [1 2 3; 4 5 6; 7 8 9; 10 11 12];
S2 = [-1 -1 -1; 0 9 8];
结果
dist =
5.385164807134504 6.000000000000000 7.141428428542850 10.954451150103322
ind =
1 2 2 2