我正试图写一个函数来计算所有行向量的一对一曼哈顿距离,有一个内置的函数mandist()
,属于ANN工具箱——
data = rand(4,2);
disp(data)
mandist(data')
>> mdtest
0.7996 0.8884
0.5735 0.4954
0.9732 0.3516
0.6341 0.7142
ans =
0 0.6191 0.7104 0.3397
0.6191 0 0.5435 0.2793
0.7104 0.5435 0 0.7018
0.3397 0.2793 0.7018 0
我想知道是否可以用bsxfun
优化mandist()
。bsxfun
版本如下所示--
[r,~] = size(rand);
abs(bsxfun(@minus, ...
repmat(permute(data, [1 3 2]),1,r), ...
repmat(permute(data, [3 1 2]),r,1)))
上面的语句可以生成所有计算abs(a - b)
-的矩阵
ans(:,:,1) =
0 0.2261 0.1736 0.1656
0.2261 0 0.3997 0.0605
0.1736 0.3997 0 0.3392
0.1656 0.0605 0.3392 0
ans(:,:,2) =
0 0.3930 0.5368 0.1742
0.3930 0 0.1438 0.2188
0.5368 0.1438 0 0.3626
0.1742 0.2188 0.3626 0
现在我想一次把它们全部加起来,有可能吗?
mandist.m
的源代码声明如下:
两个向量p(:,i)和p(::,j)之间的曼哈顿距离为计算为out(i,j)=sum(abs(data(:,i)-data(:,j))。
要创建mandist
的矢量化版本,您可以使用permute
创建singleton dimensions
,然后让bsxfun
在它们身上施展魔咒,以获得最终输出-
out = sum(abs(bsxfun(@minus,permute(data,[1 3 2]),permute(data,[3 1 2]))),3);
是的,bsxfun
再次比mandist
快--
clear all
data = rand(500,500);
[~,col] = size(data);
maxrun = 20 ;
%warm up
for k = 1:50000
tic(); elapsed = toc();
end
toctime = 0 ;
for i = 1:maxrun
tic
mandist(data');
toctime = toctime + toc ;
end
fprintf('elapsed time: %0.4fn', toctime/maxrun);
toctime = 0 ;
for i = 1:maxrun
tic
sum(abs(bsxfun(@minus,permute(data,[1 3 2]),...
permute(data,[3 1 2]))),3);
toctime = toctime + toc ;
end
fprintf('elapsed time: %0.4fn', toctime/maxrun);
结果——
>> mdtest
elapsed time: 1.1753
elapsed time: 0.7733