1

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

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

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

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

谢谢你,克里斯

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

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.
4

1 回答 1

4

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

一种有效计算所需相关性的快速方法是使用corrMATLAB 中的函数。该函数将接受 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,您可以提高函数的性能。现在,我希望这能为您提供一些指导,让您了解如何计算种子时间过程和许多目标时间过程之间的相关性,而无需循环遍历并分别计算每个时间过程。corrzscorebsxfun

于 2012-09-16T04:09:16.483 回答