Вопрос:

Корреляция между массивом и разреженной матрицей

python numpy scipy sparse-matrix

370 просмотра

1 ответ

435 Репутация автора

У меня есть разреженная матрица (х) и массив (у). Я хотел бы вычислить корреляцию между каждым столбцом в матрице и массиве. Ниже показан очень простой и медленный подход. Я надеялся, что у кого-то будет более быстрый / лучший подход.

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]
Автор: ironv Источник Размещён: 10.01.2018 10:24

Ответы (1)


6 плюса

33183 Репутация автора

Решение

Используя разреженность, вы можете легко получить ускорение> 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))

Пример вывода:

results equal -- True
run time (sec) -- OP: 1.38134884834, new: 0.0178880691528

Пояснение: чтобы иметь возможность воспользоваться преимуществом разреженности, мы стандартизируем y, который в любом случае является плотным. А затем вычислить необработанную корреляцию между х и у. Поскольку у уже есть нулевое среднее значение, в этот момент среднее значение х отсутствует. Поэтому остается делить на стандартное отклонение х. Здесь также мы можем избежать прохождения плотной матрицы, вычислив необработанный 2-й момент и вычтя среднее значение в квадрате.

Детали реализации: Обратите внимание, что я взял на себя смелость перейти к тому, cscчто здесь больше подходит. Мы используем np.add.reduceatдля выполнения сумм вдоль «рваных» столбцов векторизованным способом. indicesИз cscпредставления разреженной матрицы удобно выбирать элементы y, соответствующие ненулевым элементам в x.

Автор: Paul Panzer Размещён: 10.01.2018 11:53
Вопросы из категории :
32x32