MATLAB:与种子区域的相关性

时间:2012-09-15 23:38:56

标签: matlab correlation bsxfun

默认情况下,用于计算相关性或协方差的所有内置函数都返回矩阵。我正在尝试编写一个有效的函数来计算种子区域和其他各个区域之间的相关性,但我不需要其他区域之间的相关性。我认为计算完整的相关矩阵因此效率低下。

我可以改为计算每个区域和种子区域之间的相关矩阵,选择其中一个偏离对角点并存储它,但我觉得在这种情况下循环效率也很低。

更具体地说,我的三维空间中的每个点都有一个时间维度。我试图计算给定点与给定半径内空间中所有点之间的平均相关性。我希望重复这个过程数十万次,对于许多不同的半径长度,等等,所以我希望尽可能高效。

那么,计算单个向量与其他几个向量之间的相关性的最佳方法是什么,而不计算我将忽略的相关性?

谢谢你, 克里斯

编辑:这是我现在的代码......

function [corrMap] = TIME_meanCorrMap(A,radius)
% Even though the variable is "radius", we work with cubes for simplicity...
% So, the radius is the distance (in voxels) from the center of the cube an edge.
denom = ((radius*2)^3)-1;
dim = size(A);
corrMap = zeros(dim(1:3));
for x = radius+1:dim(1)-radius
    rx = [x-radius : x+radius];
    for y = radius+1:dim(2)-radius
        ry = [y-radius : y+radius];
        for z = radius+1:dim(3)-radius
            rz = [z-radius : z+radius];
            corrCoefs = zeros(1,denom);
            seed = A(x,y,z,:);
            i=0;
            for xx = rx
                for yy = ry
                    for zz = rz
                        if ~all([x y z] == [xx yy zz])
                            i = i + 1;
                            temp = corrcoef(seed,A(xx,yy,zz,:));
                            corrCoeffs(i) = temp(1,2);
                        end
                    end
                end
            end
            corrMap = mean(corrCoeffs);
        end
    end
end

编辑:这里有一些时间来补充接受的答案。 使用bsxfun()进行规范化,并使用矩阵乘法来计算相关性:

tic; for i=1:10000                                                                
    x=rand(100);
    xz = bsxfun(@rdivide,bsxfun(@minus,x,mean(x)),std(x));
    cc = xz(:,2:end)' * xz(:,1) ./ 99;
end; toc
Elapsed time is 6.928251 seconds.

使用zscore()进行标准化,矩阵乘法计算相关性:

tic; for i=1:10000                                    
    x=rand(100);                                          
    xz = zscore(x);                                       
    cc = xz(:,2:end)' * xz(:,1) ./ 99;
end; toc
Elapsed time is 7.040677 seconds.

使用bsxfun()进行标准化,使用corr()计算相关性。

tic; for i=1:10000                                    
    x=rand(100);
    xz = bsxfun(@rdivide,bsxfun(@minus,x,mean(x)),std(x));
    cc = corr(x(:,1),x(:,2:end));
end; toc
Elapsed time is 11.385707 seconds.

1 个答案:

答案 0 :(得分:4)

当然可以改进您当前使用的for循环。如果您有足够的RAM,则可以使用矩阵乘法并行化相关计算。但是,它需要您将四维数据矩阵A展开为不同的形状。您很可能正在处理三维体素fMRI数据,在这种情况下,您必须从[x y z time]矩阵重新整形为[index time]矩阵。我会假设你可以处理重塑。在您的seed时间课程[时间1]和target时间课程[时间由NumTargets]准备就绪后,您可以执行更高效的计算。

有效计算所需相关性的快捷方法是使用MATLAB中的corr函数。这个函数将接受2个矩阵参数,它将非常有效地计算参数1的列和参数2的列之间的所有成对相关性,例如

T = 200; %time samples
N = 20;  %number of other voxels

seed = randn(T,1);     %data from seed voxel
targets = randn(T,N);  %data from target voxels

%here is the for loop method
tic
for n = 1:N
   tmp = corrcoef(seed, targets(:,n));
   tmpcc = tmp(1,2);
end
looptime = toc;

%here is the parallel method
tic
cc = corr(seed, targets);
matrixtime = toc;

在我的机器上,corr中的并行操作比循环方法快一个与T * N成比例的因子。

如果您愿意自己执行基础矩阵操作,则可能比corr函数快一点,并且无论如何都值得知道它们是什么。两个向量之间的相关性基本上是一个归一化的点积,因此使用上面的约定可以用以下方式计算相关性

zseed = zscore(seed);  %normalize the seed timecourse by z-scoring
ztargets= zscore(targets);  %normalize the target timecourses by z-scoring
ztargets = ztargets';      %flip columns and rows for convenience
cc2 = ztargets*zseed./(T-1);    %compute many dot products with one matrix multiplication

上面的代码基本上是corr函数将执行的操作,这就是它比循环快得多的原因。请注意,大多数操作时间都在zscore操作中,如果使用corr命令高效计算zscore,则可以提高bsxfun函数的性能。现在,我希望这能为你提供一些方向,让你了解如何计算种子时间段和许多目标时间段之间的相关性,而无需循环遍历并分别计算每个时间段。