1

デフォルトでは、相関または共分散を計算するためのすべての組み込み関数は行列を返します。シード領域と他のさまざまな領域との間の相関を計算する効率的な関数を作成しようとしていますが、他の領域間の相関は必要ありません。したがって、完全な相関行列の計算は非効率的であると思います。

代わりに、各領域とシード領域の間の相関行列を計算し、対角線から外れた点の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 時間] マトリックスから [インデックス時間] マトリックスに再形成する必要があります。その再形成に対処できると思います。seedタイムコース [Time by 1] とtargetタイムコース [Time by NumTargets] の準備ができたら、より効率的な計算を実行できます。

目的の相関関係を効率的に計算する簡単な方法はcorr、MATLAB で関数を使用することです。この関数は 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;

私のマシンでは、並列操作は、corrT*N に比例する係数でループ メソッドよりも高速です。

corr基礎となる行列演算を自分で実行したい場合は、関数よりも少し速くすることができます。いずれにせよ、それらが何であるかを知ることは価値があります。2 つのベクトル間の相関は、基本的に正規化されたドット積であるため、上記の規則を使用して、次の方法で相関を計算できます。

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 に答える