J'ai 2 vecteurs A et B, chacun de longueur 10 000. Pour chacun de ind=1:10000
, je veux calculer la corrélation de Pearson de A(1:ind)
et B(1:ind)
. Quand je fais cela dans une boucle for, cela prend trop de temps. Parfor ne fonctionne pas avec plus de 2 travailleurs dans ma machine. Y at-il un moyen de faire cette opération rapide et enregistrer les résultats dans un vecteur C (apparemment de longueur 10.000 où le premier élément est NaN)? J'ai trouvé la question Fast rolling correlation in Matlab, mais c'est un peu différent de ce dont j'ai besoin.MATLAB: Calcul de corrélation rapide pour tous les indices dans 2 vecteurs
Répondre
Vous pouvez utiliser cette méthode pour calculer le coefficient de corrélation cumulative:
function result = cumcor(x,y)
n = reshape(1:numel(x),size(x));
sumx = cumsum(x);
sumy = cumsum(y);
sumx2 = cumsum(x.^2);
sumy2 = cumsum(y.^2);
sumxy = cumsum(x.*y);
result = (n.*sumxy-sumx.*sumy)./(sqrt((sumx.^2-n.*sumx2).*(sumy.^2-n.*sumy2)));
end
Solution
Je suggère l'approche suivante:
corrélation de Pearson peut être calculé en utilisant the following formula:
calculer la moyenne accumulative de chacun des variabiles aléatoires ci-dessus efficacement est facilement facile (X, Y, XY, X^2, Y^2).
donné la moyenne cumulative calculée en 2, on peut calculer la accumulative std de X et Y.
- compte tenu de la accumulative std de X, Y et accumulative moyenne ci-dessus, on peut calculer le coefficient de Pearson accumulatif.
code
%defines inputs
N = 10000;
X = rand(N,1);
Y = rand(N,1);
%calculates accumolative mean for X, Y, X^2, Y^2, XY
EX = accumMean(X);
EY = accumMean(Y);
EX2 = accumMean(X.^2);
EY2 = accumMean(Y.^2);
EXY = accumMean(X.*Y);
%calculates accumolative pearson correlation
accumPearson = zeros(N,1);
for ii=2:N
stdX = (EX2(ii)-EX(ii)^2).^0.5;
stdY = (EY2(ii)-EY(ii)^2).^0.5;
accumPearson(ii) = (EXY(ii)-EX(ii)*EY(ii))/(stdX*stdY);
end
%accumulative mean function, to be defined in an additional m file.
function [ accumMean ] = accumMean(vec)
accumMean = zeros(size(vec));
accumMean(1) = vec(1);
for ii=2:length(vec)
accumMean(ii) = (accumMean(ii-1)*(ii-1) +vec(ii))/ii;
end
end
Durée
pour N = 10 000:
Elapsed time is 0.002096 seconds.
pour N = 1000000:
Elapsed time is 0.240669 seconds.
Correctness
Test de l'exactitude du code ci-dessus pourrait être fait par calculatoire le coefficient accumulative pearson par fonction Corr, et en le comparant au résultat donné du code ci-dessus:
%ground truth for correctness comparison
gt = zeros(N,1)
for z=1:N
gt(z) = corr(X(1:z),Y(1:z));
end
Malheureusement, je n'ai pas la boîte à outils Statistiques et Machine Learning, donc je ne peux pas faire cette vérification. Je pense que c'est un bon point de départ bien, et vous pouvez continuer d'ici :)