Ответ 1
Я могу улучшить скорость 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
EDIT: описание
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);
.