如何分别计算不同维度的欧氏距离?
How to separately compute the Euclidean Distance in different dimension?
我在使用pdist
时遇到了一个问题,如果你能给我一些建议,我将不胜感激。 pdist(D)
通常给出多个维度的距离总和,但是,我想单独获取距离。例如我有一个数据集 S
是一个 10*2 矩阵,我使用 pdist(S(:,1))
和 pdist(S(:,2))
来分别获取距离,但是当数据有很多时这看起来效率很低方面。有没有其他方法可以更有效地实现这一目标?提前致谢!
假设您只想要点的各个维度之间的绝对差异,那么 pdist
就太过分了。您可以使用以下简单函数
function d = pdist_1d(S)
idx = nchoosek(1:size(S,1),2);
d = abs(S(idx(:,1),:) - S(idx(:,2),:));
end
其中 returns S
中所有行对之间的绝对成对差异。
在这种情况下
dist = pdist_1d(S)
给出与
相同的结果
dist = cell2mat(arrayfun(@(dim)pdist(S(:,dim))',1:size(S,2),'UniformOutput',false));
另一种选择是使用 bsxfun
:
,因为您只是简单地获取坐标的绝对差值
>> D = randi(20, 10, 2) % generate sample data
D =
17 12
14 10
8 4
7 11
19 13
2 18
11 14
5 19
19 12
20 8
从这里开始,我们置换数据,使坐标(列)延伸到第 3 个维度,第一个参数的行位于第 1 维,第二个参数的行位于第 2 维:
>> dist = bsxfun(@(x,y)abs(x-y), permute(D, [1 3 2]), permute(D, [3 1 2]))
dist =
ans(:,:,1) =
0 3 9 10 2 15 6 12 2 3
3 0 6 7 5 12 3 9 5 6
9 6 0 1 11 6 3 3 11 12
10 7 1 0 12 5 4 2 12 13
2 5 11 12 0 17 8 14 0 1
15 12 6 5 17 0 9 3 17 18
6 3 3 4 8 9 0 6 8 9
12 9 3 2 14 3 6 0 14 15
2 5 11 12 0 17 8 14 0 1
3 6 12 13 1 18 9 15 1 0
ans(:,:,2) =
0 2 8 1 1 6 2 7 0 4
2 0 6 1 3 8 4 9 2 2
8 6 0 7 9 14 10 15 8 4
1 1 7 0 2 7 3 8 1 3
1 3 9 2 0 5 1 6 1 5
6 8 14 7 5 0 4 1 6 10
2 4 10 3 1 4 0 5 2 6
7 9 15 8 6 1 5 0 7 11
0 2 8 1 1 6 2 7 0 4
4 2 4 3 5 10 6 11 4 0
这会产生一个 3 维对称矩阵,其中
dist(p, q, d)
给出维度 d
中点 p
和 q
与
之间的距离
dist(p, q, d) == dist(q, p, d)
如果你想要 p
和 q
在所有(或多个)维度上的距离,你应该使用 squeeze
把它放在一个向量中:
>> squeeze(dist(3, 5, :))
ans =
11
9
请注意,如果您使用的是 MATLAB 2016b 或更高版本(或 Octave),则无需 bsxfun
:
即可创建相同的距离矩阵
dist = abs(permute(D, [1 3 2]) - permute(D, [3 1 2]))
这种方法的缺点是它创建了完整的对称矩阵,因此每个距离生成两次,这可能会成为内存问题。
我在使用pdist
时遇到了一个问题,如果你能给我一些建议,我将不胜感激。 pdist(D)
通常给出多个维度的距离总和,但是,我想单独获取距离。例如我有一个数据集 S
是一个 10*2 矩阵,我使用 pdist(S(:,1))
和 pdist(S(:,2))
来分别获取距离,但是当数据有很多时这看起来效率很低方面。有没有其他方法可以更有效地实现这一目标?提前致谢!
假设您只想要点的各个维度之间的绝对差异,那么 pdist
就太过分了。您可以使用以下简单函数
function d = pdist_1d(S)
idx = nchoosek(1:size(S,1),2);
d = abs(S(idx(:,1),:) - S(idx(:,2),:));
end
其中 returns S
中所有行对之间的绝对成对差异。
在这种情况下
dist = pdist_1d(S)
给出与
相同的结果dist = cell2mat(arrayfun(@(dim)pdist(S(:,dim))',1:size(S,2),'UniformOutput',false));
另一种选择是使用 bsxfun
:
>> D = randi(20, 10, 2) % generate sample data
D =
17 12
14 10
8 4
7 11
19 13
2 18
11 14
5 19
19 12
20 8
从这里开始,我们置换数据,使坐标(列)延伸到第 3 个维度,第一个参数的行位于第 1 维,第二个参数的行位于第 2 维:
>> dist = bsxfun(@(x,y)abs(x-y), permute(D, [1 3 2]), permute(D, [3 1 2]))
dist =
ans(:,:,1) =
0 3 9 10 2 15 6 12 2 3
3 0 6 7 5 12 3 9 5 6
9 6 0 1 11 6 3 3 11 12
10 7 1 0 12 5 4 2 12 13
2 5 11 12 0 17 8 14 0 1
15 12 6 5 17 0 9 3 17 18
6 3 3 4 8 9 0 6 8 9
12 9 3 2 14 3 6 0 14 15
2 5 11 12 0 17 8 14 0 1
3 6 12 13 1 18 9 15 1 0
ans(:,:,2) =
0 2 8 1 1 6 2 7 0 4
2 0 6 1 3 8 4 9 2 2
8 6 0 7 9 14 10 15 8 4
1 1 7 0 2 7 3 8 1 3
1 3 9 2 0 5 1 6 1 5
6 8 14 7 5 0 4 1 6 10
2 4 10 3 1 4 0 5 2 6
7 9 15 8 6 1 5 0 7 11
0 2 8 1 1 6 2 7 0 4
4 2 4 3 5 10 6 11 4 0
这会产生一个 3 维对称矩阵,其中
dist(p, q, d)
给出维度 d
中点 p
和 q
与
dist(p, q, d) == dist(q, p, d)
如果你想要 p
和 q
在所有(或多个)维度上的距离,你应该使用 squeeze
把它放在一个向量中:
>> squeeze(dist(3, 5, :))
ans =
11
9
请注意,如果您使用的是 MATLAB 2016b 或更高版本(或 Octave),则无需 bsxfun
:
dist = abs(permute(D, [1 3 2]) - permute(D, [3 1 2]))
这种方法的缺点是它创建了完整的对称矩阵,因此每个距离生成两次,这可能会成为内存问题。