使用 BSXFUN - MATLAB 对 MANDIST(曼哈顿距离)进行矢量化

Vectorizing MANDIST (Manhattan distance) with BSXFUN - MATLAB

我正在尝试编写一个函数来计算所有行向量的一对一曼哈顿距离,有一个名为 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 的源代码声明如下:

The Manhattan distance between two vectors P(:,i) and P(:,j) is calculated as out(i,j) = sum(abs(data(:,i) - data(:,j))).

要创建 mandist 的矢量化版本,您可以使用 permute to create singleton dimensions and then let 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.4f\n', 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.4f\n', toctime/maxrun);

结果--

>> mdtest
elapsed time: 1.1753
elapsed time: 0.7733