【问题标题】:How do I average columns block-wise?如何按块平均列?
【发布时间】:2014-09-21 21:26:24
【问题描述】:

比如说,我有以下矩阵:

[1 2 3 4 1 2 3 4

1 2 3 4 1 2 3 4

1 2 3 4 1 2 3 4]

我如何以编程方式平均每四列一次,这样我最终会得到 与:

[2.5 2.5

2.5 2.5

2.5 2.5]

?

谢谢,

汤姆

【问题讨论】:

    标签: matlab matrix average


    【解决方案1】:

    使用reshape 可以在不循环的情况下完成:

    A = [1 2 3 4 1 2 3 4
         1 2 3 4 1 2 3 4
         1 2 3 4 1 2 3 4]; %// data matrix
    N = 4; %// number of columns to average
    result = squeeze(mean(reshape(A,size(A,1), N, []), 2));
    

    如果你有图像处理工具箱,也可以使用blockproc

    result = blockproc(A, [size(A,1) N], @(x) mean(x.data, 2))
    

    【讨论】:

    • 有趣的重塑为 3d 并重新挤压方法 ;)
    • @Thomas 谢谢!我正在考虑删除我的答案,因为你的答案是第一个,但后来你删除了它。你为什么这么做?
    • 我注意到我在结果中交换了列/行,您的答案是正确的。
    【解决方案2】:

    一种基于sumreshape 的方法-

    reshape(sum(reshape(A,size(A,1),N,[]),2)/N,size(A,1),[])
    

    此处介绍了迄今为止发布的解决方案的一些基准。

    基准代码 -

    m = 1000; %// No. of rows in input
    n = 4000; %// No. of cols in input
    A = rand(m,n); %// Input with random data
    N = 4; %// number of columns to average;
    num_runs = 200; %// No. of iterations
    
    disp('----------------- With sum+reshape');
    tic
    for k1 = 1:num_runs
        out1 = reshape(sum(reshape(A,size(A,1),N,[]),2)/N,size(A,1),[]);
    end
    toc,clear out1
    
    disp('----------------- With mean+reshape');
    tic
    for k1 = 1:num_runs
        out2 = squeeze(mean(reshape(A,size(A,1), N, []), 2));
    end
    toc,clear out2
    
    disp('----------------- With blockproc');
    tic
    for k1 = 1:num_runs
        out3 = blockproc(A, [size(A,1) N], @(x) mean(x.data, 2));
    end
    toc,clear out3
    
    disp('----------------- With filter');
    tic
    for k1 = 1:num_runs
        B = filter(ones(1,N)/N,1,A,[],2);
        out4 = B(:,N:N:end);
    end
    toc,clear out4 B
    

    结果 -

    ----------------- With sum+reshape
    Elapsed time is 4.011844 seconds.
    ----------------- With mean+reshape
    Elapsed time is 3.945733 seconds.
    ----------------- With blockproc
    Elapsed time is 59.018457 seconds.
    ----------------- With filter
    Elapsed time is 31.220875 seconds.
    

    【讨论】:

    • +1 使用sum 代替慢速mean 是个好主意。还有很好的基准测试!
    • @LuisMendo 是的,似乎使用基本的确实给我们带来了性能!+1 也已经为您服务了!忘了说squeeze也挤爆了性能!
    • @Divakar 好主意,但是对我(Matlab2011b,Win7)来说,mean+reshape 可靠地击败了其他人。另一个快速解决方案是display([2.5 2.5; 2.5 2.5; 2.5 2.5]) :D
    • @LuisMendo 所以我运行这些没有。迭代次数,现在似乎在 mean+reshape 和 sum+reshape 之间并驾齐驱!很抱歉之前的混乱:)
    • @Divakar 在所有其他条件相同的情况下(此处并非完全如此),mean 应该会慢一些,因为它会在调用 sum 之前进行检查
    【解决方案3】:

    一个简单的方法是滥用filter

    A = [1 2 3 4 1 2 3 4 ;
         1 2 3 4 1 2 3 4 ;
         1 2 3 4 1 2 3 4 ]
    
    N = 4;
    
    B = filter(ones(1,N)/N,1,A,[],2)
    C = B(:,N:N:end)
    

    给予:

    C =
    
        2.5000    2.5000
        2.5000    2.5000
        2.5000    2.5000
    

    这似乎比所有重塑和挤压动作要快得多;)虽然没有证据。

    【讨论】:

    • @Thomas,你是对的。只是一个错字,现在应该可以工作了。
    • 现在工作。我认为现在整个问题都得到了很好的探索;)
    • 使用filterconv 是一种有趣的方法,但它计算出的结果是N 的倍数(然后您必须使用N:N:end 进行下采样)。 +1,虽然
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-01
    • 1970-01-01
    • 2023-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多