Я могу получить улучшение скорости x100 , вычислив его вручную.
An=bsxfun(@minus,A,mean(A,1)); %%% zero-mean
Bn=bsxfun(@minus,B,mean(B,1)); %%% zero-mean
An=bsxfun(@times,An,1./sqrt(sum(An.^2,1))); %% L2-normalization
Bn=bsxfun(@times,Bn,1./sqrt(sum(Bn.^2,1))); %% L2-normalization
C=sum(An.*Bn,1); %% correlation
Вы можете сравнить, используя этот код:
A=rand(60,25000);
B=rand(60,25000);
tic;
C=zeros(1,size(A,2));
for i = 1:size(A,2)
C(i)=corr(A(:,i), B(:,i));
end
toc;
tic
An=bsxfun(@minus,A,mean(A,1));
Bn=bsxfun(@minus,B,mean(B,1));
An=bsxfun(@times,An,1./sqrt(sum(An.^2,1)));
Bn=bsxfun(@times,Bn,1./sqrt(sum(Bn.^2,1)));
C2=sum(An.*Bn,1);
toc
mean(abs(C-C2)) %% difference between methods
Вот время вычислений:
Elapsed time is 10.822766 seconds.
Elapsed time is 0.119731 seconds.
Разница между двумя результатами очень мала:
mean(abs(C-C2))
ans =
3.0968e-17
РЕДАКТИРОВАТЬ: объяснение
bsxfun
выполняет операцию столбец за столбцом (или строка за строкой в зависимости от ввода).
An=bsxfun(@minus,A,mean(A,1));
Эта строка удалит (@minus
) среднее значение каждого столбца (mean(A,1)
) для каждого столбца A
... Таким образом, по сути, столбцы A
имеют нулевое среднее значение.
An=bsxfun(@times,An,1./sqrt(sum(An.^2,1)));
Эта строка умножает (@times) каждый столбец на обратную его норму. Так что это делает их L-2 нормализованными.
После того, как столбцы будут иметь нулевое среднее значение и нормализованы по L2, для вычисления корреляции вам нужно просто сделать скалярное произведение каждого столбца An
с каждым столбцом B
. Таким образом, вы умножаете их поэлементно An.*Bn
, а затем суммируете каждый столбец: sum(An.*Bn);
.