数组与稀疏矩阵的相关性

iro*_*onv 3 python numpy scipy sparse-matrix

我有一个稀疏矩阵(x)和一个数组(y).我想计算矩阵中每列与数组之间的相关性.下面显示的是一种非常简单的方法,这种方法很慢.我希望有人会有更快/更好的方法.

import numpy as np
from scipy.sparse import rand as r1
from numpy.random import rand as r2

np.random.seed(1000)

nrow,ncol = 50000,4000
x = r1(nrow, ncol, format='csr', density=.05)
y = (r2(nrow)<=.6).astype(int)

correl = [(n,np.corrcoef(np.asarray(x[:,n].todense()).reshape(-1), y)[0,1]) for n in xrange(ncol)]
print correl[:10]
Run Code Online (Sandbox Code Playgroud)

Pau*_*zer 6

使用稀疏性您可以轻松获得> 50x的加速:

import numpy as np
from scipy.sparse import rand as r1
from numpy.random import rand as r2
from time import time

np.random.seed(1000)

nrow,ncol = 5000,4000
x = r1(nrow, ncol, format='csc', density=.05)
y = (r2(nrow)<=.6).astype(int)

t = []
t.append(time())
correl = [np.corrcoef(np.asarray(x[:,n].todense()).reshape(-1), y)[0,1] for n in xrange(ncol)]

t.append(time())

yy = y - y.mean()
xm = x.mean(axis=0).A.ravel()
ys = yy / np.sqrt(np.dot(yy, yy))
xs = np.sqrt(np.add.reduceat(x.data**2, x.indptr[:-1]) - nrow*xm*xm)

correl2 = np.add.reduceat(x.data * ys[x.indices], x.indptr[:-1]) / xs

t.append(time())

print 'results equal --', np.allclose(correl, correl2)
print 'run time (sec) -- OP: {}, new: {}'.format(*np.diff(t))
Run Code Online (Sandbox Code Playgroud)

样本输出:

results equal -- True
run time (sec) -- OP: 1.38134884834, new: 0.0178880691528
Run Code Online (Sandbox Code Playgroud)

说明:为了能够利用稀疏性我们标准化密集的y无论如何.然后计算x和y之间的原始相关性.因为此时y已经是零均值,所以x的平均值是不固定的.因此,它仍然除以x的标准偏差.在这里我们也可以通过计算原始第二时刻并减去平方均值来避免通过密集矩阵.

实施细节:请注意,我已经冒昧地切换到csc更合适的地方.我们使用np.add.reduceat矢量化方式沿着"参差不齐"的列执行求和.indicescsc稀疏矩阵的表示中,便于选择对应于x中非零元素的y元素.