我有一个矩阵a
,我想计算从一个点到所有其他点的距离。因此,结果矩阵实际上应该有一个零(在我选择的点),并且应该在该特定点周围显示为某种数字圈。
这是我已经拥有的,但我似乎无法得到正确的结果。
a = [1 2 3 4 5 6 7 8 9 10]
for i = 2:20
a(i,:) = a(i-1,:) + 1;
end
N = 10
for I = 1:N
for J = 1:N
dx = a(I,1)-a(J,1);
dy = a(I,2)-a(J,2);
distance(I,J) = sqrt(dx^2 + dy^2)
end
end
您的a
矩阵是一维向量,与嵌套循环不兼容,嵌套循环计算二维空间中从每个点到每个点的距离。 因此,以下答案适用于在N-by-D
矩阵中查找所有成对距离的问题,就像您的循环在D=2
的情况下所做的那样。
选项 1 - 警区
我认为您正在寻找具有'euclidean'
距离选项的pdist
。
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 )
在 MATLAB 中为大小NxD
的两个数据数组u
和v
编写此数组,
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 x 3 (N-by-D) 的随机数据矩阵,以下是 100 次运行的计时(Core 2 四边形、4GB DDR2、R2013a)。
- 选项 1 (
pdist
): 1.561150 秒 (0.560947 秒 inpdist
)- 选项 2 (
bsxfun
): 2.695059 秒 - 选项 3(
bsxfun
备选):1.334880 秒
结果:(i)用bsxfun
进行计算,使用替代公式。(ii) pdist
+squareform
选项具有可比的性能。(iii)squareform
花费的时间是pdist
的两倍的原因可能是pdist
因为距离矩阵是对称的,因此只计算三角矩阵。 如果可以不使用方阵,则可以避免squareform
,并在使用bsxfun
(0.5609/1.3348)手动进行计算所需的时间的40%左右。
这就是我一直在寻找的,但感谢您的所有建议。
A = rand(5, 5);
select_cell = [3 3];
distance = zeros(size(A, 1), size(A, 2));
for i = 1:size(A, 1)
for j = 1:size(A, 2)
distance(i, j) = sqrt((i - select_cell(1))^2 + (j - select_cell(2))^2);
end
end
disp(distance)
您也可以通过使用矢量化来改进它:
distances = sqrt((x-xCenter).^2+(y-yCenter).^2
重要提示:data_matrix是 D X N,其中 D 是维度数,N 是数据点数!
final_dist_pairs=data_matrix'*data_matrix;
规范 = 诊断(final_dist_pairs);
final_dist_pairs = bsxfun(@plus, norms, norms') - 2 * final_dist_pairs;希望对您有所帮助!
% 另一件重要的事情,切勿使用 MATLAB 的 pdist 函数。这是一个顺序评估,类似于 for 循环,需要大量时间,可能在 O(N^2) 中