【问题标题】:Vectorizing MANDIST (Manhattan distance) with BSXFUN - MATLAB使用 BSXFUN 向量化 MANDIST(曼哈顿距离) - MATLAB
【发布时间】:2015-03-22 02:46:54
【问题描述】:

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

现在我想一次性全部添加,可以吗?

【问题讨论】:

    标签: matlab matrix lambda vectorization bsxfun


    【解决方案1】:

    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);
    

    【讨论】:

    • 再次感谢 Divakar,有一件事我不太明白,为什么不需要 repmat
    • @ramgorur 好吧,bsxfun 在后台进行复制/扩展,这正是 repmat 所做的。所以,实际上你不需要在那里使用repmat。希望这是有道理的!
    【解决方案2】:

    是的,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
    

    【讨论】:

    • 很高兴看到运行时!
    猜你喜欢
    • 1970-01-01
    • 2012-06-18
    • 1970-01-01
    • 1970-01-01
    • 2020-10-19
    • 1970-01-01
    • 1970-01-01
    • 2018-05-24
    • 1970-01-01
    相关资源
    最近更新 更多