I have a matrix M1 , each row of which is a time-dependent signal.
And I have another matrix, M2, of the same dimensions, each row of which is also a time dependent
I think it's this: (please correct if wrong!)
import numpy as np
M1 = np.array ([
[1, 2, 3, 4],
[2, 3, 1, 4.5]
])
M2 = np.array ([
[10, 20, 33, 40],
[20, 35, 15, 40]
])
v = np.diagonal (np.corrcoef (M1, M2), M1.shape [0])
print (v)
Which prints:
[ 0.99411402 0.96131896]
Since it's got only one dimension, I can think of it as a column-vector...
not knowing enough of numpy array magic, I'd just pick out the rows, feed each pair individually to corrcoeff
[np.corrcoef(i,j)[0][1] for i,j in zip(a,b)]
for a np.array column output
c, c.shape = np.array([np.corrcoef(i,j)[0][1] for i,j in zip(a,b)]), (a.shape[0], 1)
I'm sure there's better using numpy broadcast/indexing features
Based on this solution to finding correlation matrix between two 2D
arrays, we can have a similar one for finding correlation vector that computes correlation between corresponding rows in the two arrays. The implementation would look something like this -
def corr2_coeff_rowwise(A,B):
# Rowwise mean of input arrays & subtract from input arrays themeselves
A_mA = A - A.mean(1)[:,None]
B_mB = B - B.mean(1)[:,None]
# Sum of squares across rows
ssA = (A_mA**2).sum(1);
ssB = (B_mB**2).sum(1);
# Finally get corr coeff
return np.einsum('ij,ij->i',A_mA,B_mB)/np.sqrt(ssA*ssB)
We can further optimize the part to get ssA
and ssB
by introducing einsum
magic there too!
def corr2_coeff_rowwise2(A,B):
A_mA = A - A.mean(1)[:,None]
B_mB = B - B.mean(1)[:,None]
ssA = np.einsum('ij,ij->i',A_mA,A_mA)
ssB = np.einsum('ij,ij->i',B_mB,B_mB)
return np.einsum('ij,ij->i',A_mA,B_mB)/np.sqrt(ssA*ssB)
Sample run -
In [164]: M1 = np.array ([
...: [1, 2, 3, 4],
...: [2, 3, 1, 4.5]
...: ])
...:
...: M2 = np.array ([
...: [10, 20, 33, 40],
...: [20, 35, 15, 40]
...: ])
...:
In [165]: corr2_coeff_rowwise(M1, M2)
Out[165]: array([ 0.99411402, 0.96131896])
In [166]: corr2_coeff_rowwise2(M1, M2)
Out[166]: array([ 0.99411402, 0.96131896])
Runtime test -
In [97]: M1 = np.random.rand(256,200)
...: M2 = np.random.rand(256,200)
...:
In [98]: out1 = np.diagonal (np.corrcoef (M1, M2), M1.shape [0])
...: out2 = corr2_coeff_rowwise(M1, M2)
...: out3 = corr2_coeff_rowwise2(M1, M2)
...:
In [99]: np.allclose(out1, out2)
Out[99]: True
In [100]: np.allclose(out1, out3)
Out[100]: True
In [101]: %timeit np.diagonal (np.corrcoef (M1, M2), M1.shape [0])
...: %timeit corr2_coeff_rowwise(M1, M2)
...: %timeit corr2_coeff_rowwise2(M1, M2)
...:
100 loops, best of 3: 9.5 ms per loop
1000 loops, best of 3: 554 µs per loop
1000 loops, best of 3: 430 µs per loop
20x+
speedup there with einsum
over the built-in np.corrcoef
!