vectores valor una seleccionar programacion posicion matriz matrices listas for extraer elementos agregar matlab matrix correlation

valor - ¿Cuál es una forma rápida de calcular la correlación columna por columna en matlab



seleccionar elementos de una matriz matlab (2)

Tengo dos matrices muy grandes (60x25000) y me gustaría calcular la correlación entre las columnas solo entre las dos matrices. Por ejemplo:

corrVal(1) = corr(mat1(:,1), mat2(:,1); corrVal(2) = corr(mat1(:,2), mat2(:,2); ... corrVal(i) = corr(mat1(:,i), mat2(:,i);

Para matrices más pequeñas, simplemente puedo usar:

colCorr = diag( corr( mat1, mat2 ) );

pero esto no funciona para matrices muy grandes ya que me quedo sin memoria. Consideré dividir las matrices para calcular las correlaciones y luego combinar los resultados, pero me parece un desperdicio calcular la correlación entre las combinaciones de columnas que realmente no me interesan.

¿Hay una forma rápida de calcular directamente lo que me interesa?

Editar : he usado un ciclo en el pasado pero es solo una forma de ralentizarlo:

mat1 = rand(60,5000); mat2 = rand(60,5000); nCol = size(mat1,2); corrVal = zeros(nCol,1); tic; for i = 1:nCol corrVal(i) = corr(mat1(:,i), mat2(:,i)); end toc;

Esto lleva ~ 1 segundo

tic; corrVal = diag(corr(mat1,mat2)); toc;

Esto lleva ~ 0.2 segundos


Creo que el bucle obvio podría ser lo suficientemente bueno para su tamaño de problema. En mi computadora portátil, toma menos de 6 segundos hacer lo siguiente:

A = rand(60,25000); B = rand(60,25000); n = size(A,1); m = size(A,2); corrVal = zeros(1,m); for k=1:m corrVal(k) = corr(A(:,k),B(:,k)); end


Puedo obtener una mejora de velocidad x100 informándola a mano.

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

Puedes comparar usando ese código:

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

Aquí están los tiempos de computación:

Elapsed time is 10.822766 seconds. Elapsed time is 0.119731 seconds.

La diferencia entre los dos resultados es muy pequeña:

mean(abs(C-C2)) ans = 3.0968e-17

EDITAR: explicación

bsxfun realiza una operación columna por columna (o fila por fila dependiendo de la entrada).

An=bsxfun(@minus,A,mean(A,1));

Esta línea eliminará ( @minus ) la media de cada columna ( mean(A,1) ) para cada columna de A ... Así que básicamente hace que las columnas de A sean de media cero.

An=bsxfun(@times,An,1./sqrt(sum(An.^2,1)));

Esta línea multiplica (@times) cada columna por el inverso de su norma. Entonces los hace L-2 normalizado.

Una vez que las columnas son de media cero y L2-normalizada, para calcular la correlación, solo tiene que hacer el producto de puntos de cada columna de An con cada columna de B Entonces los multiplicas por elementos An.*Bn , y luego sumas cada columna: sum(An.*Bn); .