我有一个3 X 1000(以及后来的3 X 10 000)矩阵cord
,它包含我的像素的三维坐标。
我的意图是计算所有像素之间的距离,我用for循环(见下文)来做,但我将很快计算出巨大的矩阵,并且我想知道我是否可以将代码矢量化为让它更快......?
dist = zeros(size(cord,2),size(cord,2));
for i = 1:size(cord,2)
for j = 1:size(cord,2)
dist(i,j) = norm(cord(:,i)-cord(:,j));
dist(j,i) = dist(i,j);
end
end
答案 0 :(得分:3)
pdist
正是如此。需要squareform
才能以方形对称矩阵的形式得到结果:
dist = squareform(pdist(cord.'));
答案 1 :(得分:1)
方法1(使用bsxfun
进行矢量化评价) -
squeeze(sqrt(sum(bsxfun(@minus,cord,permute(cord,[1 3 2])).^2)))
不确定这是否会更快。
方法2 -
受此very smart approach
的启发以及海报的所有信用。这里发布的代码只是针对您的情况稍作自定义,并希望在运行时方面略微更好。这是 -
A = cord'; %//'
numA = size(cord,2);
helpA = ones(numA,9);
helpB = ones(numA,9);
for idx = 1:3
sqA_idx = A(:,idx).^2;
helpA(:,3*idx-1:3*idx) = [-2*A(:,idx), sqA_idx ];
helpB(:,3*idx-2:3*idx-1) = [sqA_idx , A(:,idx)];
end
dist1 = sqrt(helpA * helpB'); %// desired output
答案 2 :(得分:0)
从您的代码中,您已经认识到dist
矩阵是对称的
dist(i,j) = norm(cord(:,i)-cord(:,j));
dist(j,i) = dist(i,j);
您可以更改内部循环以解决此问题,并将所需计算量的大约一半减少
for j = i:size(cord,2)
此外,我们可以在每次迭代时避免dist(j,i) = dist(i,j);
,最后通过提取dist
的上三角形部分并将其转置添加到dist
矩阵来实现对称性
dist = zeros(size(cord,2),size(cord,2));
for i = 1:size(cord,2)
for j = i:size(cord,2)
dist(i,j) = norm(cord(:,i)-cord(:,j));
end
end
dist = dist + triu(dist)';
上面的添加很好,因为主对角线都是零。
它仍然表现不佳,所以我们应该利用矢量化。我们可以对内循环
进行如下操作dist = zeros(size(cord,2),size(cord,2));
for i = 1:size(cord,2)
dist(i,i+1:end) = sum((repmat(cord(:,i),1,size(cord,2)-i)-cord(:,i+1:end)).^2);
end
dist = dist + triu(dist)';
dist = sqrt(dist);
对于cord
中的每个元素,我们需要计算与跟随它的所有其他元素的距离。我们使用repmat
重现元素,以便我们可以从后面的每个元素中减去它,而不需要循环。差异被平方并求和并分配给dist
矩阵。我们处理对称性,然后取矩阵的平方根来完成norm
操作。
使用tic
和toc
,使用随机线(cord = rand(3,num);
)计算原始距离大约需要93秒。这个版本花了~2.8。