您的a
矩阵是一维向量,与嵌套循环不兼容,嵌套循环计算二维空间中从每个点到另一个点的距离。因此,以下答案适用于在N-by-D
矩阵中查找所有成对距离的问题,就像您的循环对D=2
.
选项 1 - pdist
我认为您正在寻找pdist
距离'euclidean'
选项。
a = randn(10, 2); %// 2D, 10 samples
D = pdist(a,'euclidean'); %// euclidean distance
跟着它squareform
得到你想要的对角线上为零的方阵:
distances = squareform(D);
选项 2 - bsxfun
如果您没有pdist
统计工具箱中的 ,您可以使用以下方法轻松完成此操作bsxfun
:
da = bsxfun(@minus,a,permute(a,[3 2 1]));
distances = squeeze(sqrt(sum(da.^2,2)));
选项 3 - 重新制定的方程
您还可以使用欧几里得(2-范数)距离的另一种形式,
||A-B|| = sqrt ( ||A||^2 + ||B||^2 - 2*A.B )
u
在 MATLAB中为两个v
大小为 的数据数组编写此代码NxD
,
dot(u-v,u-v,2) == dot(u,u,2) + dot(v,v,2) - 2*dot(u,v,2) % useful identity
%// there are actually small differences from floating point precision, but...
abs(dot(u-v,u-v,2) - (dot(u,u,2) + dot(v,v,2) - 2*dot(u,v,2))) < 1e-15
使用重新制定的方程,解决方案变为:
aa = a*a';
a2 = sum(a.*a,2); % diag(aa)
a2 = bsxfun(@plus,a2,a2');
distances = sqrt(a2 - 2*aa);
如果选项 2 占用太多内存,您可能会使用此方法。
计时
对于大小为 1e3×3(N×D)的随机数据矩阵,这里是 100 次运行的时序(Core 2 Quad,4GB DDR2,R2013a)。
- 选项 1 (
pdist
):1.561150 秒(0.560947 秒pdist
)
- 选项 2 (
bsxfun
):2.695059 秒
- 选项 3(
bsxfun
替代):1.334880 秒
结果: (i) 用 计算bsxfun
,使用替代公式。(ii) pdist
+squareform
选项具有可比的性能。(iii) 之所以squareform
花费两倍的时间,pdist
可能是因为pdist
距离矩阵是对称的,所以只计算三角矩阵。如果您可以不使用方阵,那么您可以避免squareform
并在大约 40% 的时间内使用bsxfun
(0.5609/1.3348) 手动进行计算。