MATLAB:2个向量中所有索引的快速相关计算

时间:2017-07-17 08:13:57

标签: matlab pearson-correlation

我有2个向量A和B,每个长度为10,000。对于ind=1:10000中的每一个,我想计算Pearson与A(1:ind)B(1:ind)的相关性。当我在for循环中执行此操作时,需要花费太多时间。 parfor不适用于我的机器中超过2名工人。有没有办法快速执行此操作并将结果保存在矢量C中(显然长度为10,000,其中第一个元素是NaN)?我找到了问题Fast rolling correlation in Matlab,但这与我需要的有点不同。

2 个答案:

答案 0 :(得分:2)

您可以使用此方法计算累积相关系数:

function result = cumcor(x,y)
    n = reshape(1:numel(x),size(x));
    sumx = cumsum(x);
    sumy = cumsum(y);
    sumx2 = cumsum(x.^2);
    sumy2 = cumsum(y.^2);
    sumxy = cumsum(x.*y);
    result = (n.*sumxy-sumx.*sumy)./(sqrt((sumx.^2-n.*sumx2).*(sumy.^2-n.*sumy2)));
end

答案 1 :(得分:1)

<强>解决方案

我建议采用以下方法:

  1. Pearson相关性可以使用MDN来计算: the following formula

  2. 有效地计算上述每个随机变量的累积均值是非常容易的 (X,Y,XY,X ^ 2,Y ^ 2)。

  3. 给定累计均值2,我们可以计算出X和Y的累积std。

  4. 给定X,Y和累积均值的累积std,我们可以计算出累积的皮尔森系数。
  5. <强>代码

    %defines inputs
    N = 10000;
    X = rand(N,1);
    Y = rand(N,1);
    
    %calculates accumolative mean for X, Y, X^2, Y^2, XY
    EX = accumMean(X);
    EY = accumMean(Y);
    EX2 = accumMean(X.^2);
    EY2 = accumMean(Y.^2);
    EXY = accumMean(X.*Y);
    
    %calculates accumolative pearson correlation
    accumPearson = zeros(N,1);
    for ii=2:N
        stdX = (EX2(ii)-EX(ii)^2).^0.5;
        stdY = (EY2(ii)-EY(ii)^2).^0.5;
        accumPearson(ii) = (EXY(ii)-EX(ii)*EY(ii))/(stdX*stdY);
    end
    
    %accumulative mean function, to be defined in an additional m file.
    function [ accumMean ] = accumMean( vec )
    accumMean = zeros(size(vec));
    accumMean(1) = vec(1);
    for ii=2:length(vec)
       accumMean(ii) = (accumMean(ii-1)*(ii-1) +vec(ii))/ii;
    end
    
    end
    

    <强>运行

    对于N = 10000:

    Elapsed time is 0.002096 seconds.
    

    对于N = 1000000:

    Elapsed time is 0.240669 seconds.
    

    <强>正确性

    测试上面代码的正确性可以通过corr函数计算累积皮尔逊系数,并将其与上面代码给出的结果进行比较来完成:

    %ground truth for correctness comparison
    gt = zeros(N,1)
    for z=1:N
        gt(z) = corr(X(1:z),Y(1:z));
    end
    

    不幸的是,我没有统计和机器学习工具箱,所以我不能进行这项检查。 我认为这是一个好的开始,你可以从这里继续:)