【问题标题】:How to apply corr2 functions in Multidimentional arrays in Matlab?如何在 Matlab 的多维数组中应用 corr2 函数?
【发布时间】:2014-12-18 22:27:33
【问题描述】:

假设我有两个矩阵 A 和 B

A = rand(4,5,3);
B = rand(4,5,6)

我想应用函数'corr2'来计算相关系数。

corr2(A(:,:,1),B(:,:,1))
corr2(A(:,:,1),B(:,:,2))
corr2(A(:,:,1),B(:,:,3))
...
corr2(A(:,:,1),B(:,:,6))
...
corr2(A(:,:,2),B(:,:,1))
corr2(A(:,:,2),B(:,:,2))
...
corr2(A(:,:,3),B(:,:,6))

如何避免使用循环来创建这样的向量化?

【问题讨论】:

    标签: matlab multidimensional-array vectorization


    【解决方案1】:

    侵入corr2 的 m 文件以创建用于处理 3D 数组的自定义矢量化版本。这里建议使用bsxfun 的两种方法(当然!)

    方法#1

    szA = size(A);
    szB = size(B);
    
    a1 = bsxfun(@minus,A,mean(mean(A)));
    b1 = bsxfun(@minus,B,mean(mean(B)));
    
    sa1 = sum(sum(a1.*a1));
    sb1 = sum(sum(b1.*b1));
    
    v1 = reshape(b1,[],szB(3)).'*reshape(a1,[],szA(3));
    v2 = sqrt(sb1(:)*sa1(:).');
    
    corr3_out = v1./v2; %// desired output
    

    corr3_outAB 的所有3D 切片之间存储corr2 结果。

    因此,对于A = rand(4,5,3), B = rand(4,5,6),我们将corr3_out 作为6x3 数组。

    方法 #2

    通过使用reshape 来节省对summean 的调用次数略有不同 -

    szA = size(A);
    szB = size(B);
    dim12 = szA(1)*szA(2);
    
    a1 = bsxfun(@minus,A,mean(reshape(A,dim12,1,[])));
    b1 = bsxfun(@minus,B,mean(reshape(B,dim12,1,[])));
    
    v1 = reshape(b1,[],szB(3)).'*reshape(a1,[],szA(3));
    v2 = sqrt(sum(reshape(b1.*b1,dim12,[])).'*sum(reshape(a1.*a1,dim12,[])));
    
    corr3_out = v1./v2; %// desired output
    

    基准测试

    基准代码 -

    %// Create random input arrays
    N = 55; %// datasize scaling factor
    A = rand(4*N,5*N,3*N);
    B = rand(4*N,5*N,6*N);
    
    %// Warm up tic/toc
    for k = 1:50000
        tic(); elapsed = toc(); 
    end
    
    %// Run vectorized and loopy approach codes on the input arrays
    
    %// 1. Vectorized approach
    %//... solution code (Approach #2) posted earlier
    %// clear variables used
    
    %// 2. Loopy approach
    tic
    s_A=size(A,3);
    s_B=size(B,3);
    out1 = zeros(s_B,s_A);
    for ii=1:s_A
        for jj=1:s_B
            out1(jj,ii)=corr2(A(:,:,ii),B(:,:,jj));
        end
    end
    toc
    

    结果 -

    -------------------------- With BSXFUN vectorized solution 
    Elapsed time is 1.231230 seconds.
    -------------------------- With loopy approach
    Elapsed time is 139.934719 seconds.
    

    MATLAB-JIT 爱好者在这里大展身手! :)

    【讨论】:

    • 是的。这就是诀窍。对于大型矩阵,您可能会获得 1000 倍的改进
    • 如果有人感兴趣,这里是循环方法的运行时,当 corr2 代码被内联为与基准测试中使用的相同数据大小时 - Elapsed time is 83.948572 seconds. 这避免了所有不必要的错误检查和那些东西。我将在下一次修订中添加这些内容。
    • 迫不及待想看到你的下一个版本
    • @user2502865 哦!我的意思是下一次修订(如果需要,如您需要更多更改或编辑)。但这已准备好进行检查! :) 你试过代码吗? :)
    • 下周我将在大量数据上检查此代码。之后,我会为这个问题选择最佳答案。
    【解决方案2】:

    一些例子,但没有比循环更好的了。正如 Divakar 在下面的评论中所说,这不是矢量化解决方案。

    代码:

    A = rand(4,5,1000);
    B = rand(4,5,200);
    s_A=size(A,3);
    s_B=size(B,3);
    
    %%% option 1
    tic
    corr_AB=cell2mat(arrayfun(@(indx1) arrayfun(@(indx2) corr2(A(:,:,indx1),B(:,:,indx2)),1:s_B),1:s_A,'UniformOutput',false));
    toc
    
    %%% option 2
    tic
    indx1=repmat(1:s_A,s_B,1);
    indx1=indx1(:);
    indx2=repmat(1:s_B,1,s_A);
    indx2=indx2(:);
    indx=[indx1,indx2];
    
    corr_AB=arrayfun(@(i) corr2(A(:,:,indx(i,1)),B(:,:,indx(i,2))),1:size(indx,1));
    toc
    
    %%% option 3
    tic
    a=1;
    for i=1:s_A
        for j=1:s_B
            corr_AB(a)=corr2(A(:,:,i),B(:,:,j));
            a=a+1;
        end
    end
    toc
    

    输出:

    Elapsed time is 9.655696 seconds.
    Elapsed time is 9.398979 seconds.
    Elapsed time is 8.489744 seconds.
    

    【讨论】:

    • 我现在正在检查这个。你的代码有什么解释吗?
    • 一些编辑,因为另一个没有按预期执行。在这种情况下,我没有看到避免循环的简单方法。欲了解更多信息,请阅读 arrayfun
    • 非常感谢。 @AsantosRibeiro
    • 似乎没有比 for 循环更好的方法了 - arrayfun can be significantly slower than an explicit loop in matlab. Why? 出于同样的原因,araryfun 并不是真正的矢量化解决方案。
    • 这是一个非常棒的问题。哈哈
    猜你喜欢
    • 2018-06-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多