是否有任何节省内存的方法来计算两个稀疏矩阵的皮尔逊相关系数?

时间:2018-10-13 07:30:08

标签: python scipy

vec1和vec2均为1x200000稀疏矩阵。 我想计算它们之间的皮尔逊相关系数(相当于scipy.stats.pearsonr)。有什么办法吗?

2 个答案:

答案 0 :(得分:1)

定义2个稀疏矩阵:

 function ajax_response(response) {
   var deferred = $.Deferred().resolve(response);
   return deferred.promise();
 }
 $(function() {

   $.ajax = ajax_response([1, 2, 3]);
   $.ajax('GET', 'some/url/i/fancy').done(function(data) {
     console.log(data); // [1, 2, 3]
   });
 });

相同的值:

In [15]: M1 = sparse.random(1,1000)
In [16]: M2 = sparse.random(1,1000)

In [17]: stats.pearsonr(M1.A[0], M2.A[0])
Out[17]: (0.20251345569257148, 1.0257264375653503e-10)

但是我不能用稀疏矩阵做到这一点:

In [23]: x=M1.A[0]; y=M2.A[0]
In [24]: x1=x-x.mean(); y1=y-y.mean()
In [25]: (x1*y1).sum()/np.sqrt((x1*x1).sum()*(y1*y1).sum())
Out[25]: 0.20251345569257148

从稀疏矩阵中减去非零值意味着它不再稀疏。


忽略手段:

In [27]: M1.mean()
Out[27]: 0.0050088190479221925
In [28]: M1 - M1.mean()
...
NotImplementedError: subtracting a nonzero scalar from a sparse matrix is not supported

答案 1 :(得分:1)

通常不考虑20万个元素,您可以将它们转换为密集矩阵并使用scipy.stats.pearsonr

不过,请参考下面的稀疏向量实现。

请注意,数字错误很大,因此最后一个断言通常会失败。 另外请注意,技巧是将标量减法放在和之外,以使所有运算稀疏。

import numpy as np
from scipy import sparse
from scipy.stats import pearsonr

def create_sparse_vector(n):
    return sparse.random(n,1)

def dense_pearsonr(x, y): 
    r, p = pearsonr(x.A.squeeze(), y.A.squeeze())
    return r

def sparse_pearsonr(x, y): 
    n = x.shape[0]
    assert(n == y.shape[0])
    mx = x.mean()
    my = y.mean()
    sx = np.sqrt(np.sum(x.multiply(x) - 2*mx*x) + mx**2)
    sy = np.sqrt(np.sum(y.multiply(y) - 2*my*y) + my**2)
    a = np.sum(x.multiply(y)) - n*mx*my
    b = sx*sy
    c = a / b 
    return min(max(c,-1.0),1.0)

N = 200000 
x = sparse.random(N,1)
y = sparse.random(N,1)
r1 = dense_pearsonr(x,y)
r2 = sparse_pearsonr(x,y)
print(r1)
print(r2)
assert(np.isclose(r1,r2)) # Warning: Assertion fails because of too big numerical error