Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/matlab/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
MATLAB版本7中的pdist2等效项_Matlab_Vectorization_Euclidean Distance_Bsxfun - Fatal编程技术网

MATLAB版本7中的pdist2等效项

MATLAB版本7中的pdist2等效项,matlab,vectorization,euclidean-distance,bsxfun,Matlab,Vectorization,Euclidean Distance,Bsxfun,我需要在matlab中计算两个矩阵之间的欧氏距离。目前,我正在使用bsxfun并按如下方式计算距离(我附上一段代码): fea_测试的大小为4754x1024,fea_序列为6800x1024,使用his for循环导致执行for大约需要12分钟,我认为这太高了。 有没有办法更快地计算两个矩阵之间的欧几里德距离 我被告知,通过删除不必要的for循环,可以缩短执行时间。我也知道pdist2有助于减少计算时间,但因为我使用的是版本7。我没有matlab的pdist2函数。升级不是一个选项 任何帮助

我需要在matlab中计算两个矩阵之间的欧氏距离。目前,我正在使用bsxfun并按如下方式计算距离(我附上一段代码):

fea_测试的大小为4754x1024,fea_序列为6800x1024,使用his for循环导致执行for大约需要12分钟,我认为这太高了。 有没有办法更快地计算两个矩阵之间的欧几里德距离

我被告知,通过删除不必要的for循环,可以缩短执行时间。我也知道pdist2有助于减少计算时间,但因为我使用的是版本7。我没有matlab的pdist2函数。升级不是一个选项

任何帮助

问候,


Bhavya

您可以通过重复
fea_test
6800次和
fea_train
4754次来完全矢量化计算,如下所示:

rA = size(fea_test,1);
rB = size(fea_train,1);

[I,J]=ndgrid(1:rA,1:rB);

d = zeros(rA,rB);

d(:) = sqrt(sum(fea_test(J(:),:)-fea_train(I(:),:)).^2,2));
但是,这将导致产生大小为6800x4754x1024(*8字节用于双字节)的中间阵列,这将占用约250GB的RAM。因此,完全矢量化将不起作用

但是,您可以通过预分配和在必要时不计算平方根来减少距离计算的时间:

rA = size(fea_test,1);
rB = size(fea_train,1);
d = zeros(rA,rB);

for i = 1:rA
    test_data=fea_test(i,:);
    d(i,:)=sum( (test_data(ones(nB,1),:) -  fea_train).^2, 2))';
end

d = sqrt(d);

以下是用于计算欧几里德距离的矢量化实现,它比您的速度快得多(甚至比我的机器上快得多):

它基于这样一个事实:
|u-v | | | | ^2=| | u | | | ^2+| | v | ^2-2*u.v


考虑以下两种方法之间的粗略比较:

A = rand(4754,1024);
B = rand(6800,1024);

tic
D = pdist2(A,B,'euclidean');
toc

tic
DD = sqrt( bsxfun(@plus,sum(A.^2,2),sum(B.^2,2)') - 2*(A*B') );
toc
在我运行R2011b的WinXP笔记本电脑上,我们可以看到时间上的10倍改进:

Elapsed time is 70.939146 seconds.        %# PDIST2
Elapsed time is 7.879438 seconds.         %# vectorized solution
您应该知道,它不会给出与PDIST2完全相同的结果,直到最小的精度。。通过比较结果,您将看到微小的差异(通常接近浮点相对精度):



另一方面,我收集了大约10种不同的距离计算实现(有些只是彼此的小变化),并对它们进行了比较。与其他矢量化解决方案相比,您会惊讶于简单循环的速度有多快(感谢JIT)…

试试这个矢量化版本,它应该非常高效编辑:刚刚注意到我的答案与@Amro的答案相似

function K = calculateEuclideanDist(P,Q)
% Vectorized method to compute pairwise Euclidean distance
% Returns K(i,j) = sqrt((P(i,:) - Q(j,:))'*(P(i,:) - Q(j,:)))

[nP, d] = size(P);
[nQ, d] = size(Q);

pmag = sum(P .* P, 2);
qmag = sum(Q .* Q, 2);

K = sqrt(ones(nP,1)*qmag' + pmag*ones(1,nQ) - 2*P*Q');

end

repmat
对性能从来没有好处。在这种情况下,最好使用内联:将
repmat(test_data,nB,1)
替换为
test_data(one(1,n8),:)
@Jones谢谢您的回答,但这并没有减少代码中的for循环数。我已经有一个for循环,在该循环中可以找到该循环,并且执行时间仍然相同。@BhavyaPH:由于内存不足,减少
for
循环数的解决方案很可能无法在您的计算机上运行。另一种解决方案应该减少执行时间。您是否使用探查器进行比较?由于JIT,删除for循环并不总是最快的。看,还有很多其他问题。@Alex:谢谢。我知道你的解决方案基本上是一样的,只是我避免使用BSXFUN(而不是使用REPMAT等)在内存中创建临时矩阵。同意,BSXFUN是MATLAB中被低估和未知的函数之一。它不像repmat那样浪费内存。更多的用户需要学习如何在“矢量化”他们的代码时使用它。简单说明一下,我比较了PDIST2和您使用bsxfun和串行bsxfun的方法要快得多。然而,使用用于DD的bsxfun方法,parfor循环内部的性能实际上变得更差。但是,如果GPU存在,并且for循环不存在,那么向量化代码可以获得更好的性能……对吗?@CharlieParker,我想,您必须进行基准测试并查看。。我的观点是MATLAB中的for循环在过去名声不好,但现在也不那么差了。
Elapsed time is 70.939146 seconds.        %# PDIST2
Elapsed time is 7.879438 seconds.         %# vectorized solution
>> max( abs(D(:)-DD(:)) )
ans =
  1.0658e-013
function K = calculateEuclideanDist(P,Q)
% Vectorized method to compute pairwise Euclidean distance
% Returns K(i,j) = sqrt((P(i,:) - Q(j,:))'*(P(i,:) - Q(j,:)))

[nP, d] = size(P);
[nQ, d] = size(Q);

pmag = sum(P .* P, 2);
qmag = sum(Q .* Q, 2);

K = sqrt(ones(nP,1)*qmag' + pmag*ones(1,nQ) - 2*P*Q');

end