2012-01-18 3 views
3

Учитывая квадратичную матрицу размером 1 млн., Я хочу рассчитать матрицу диагональной степени.Как вычислить матрицу диагональной степени от огромной матрицы (scipy.sparse)?

Матрица диагональной степени определяется как диагональная матрица, в которой есть количество ненулевых значений для каждой строки.

Матрица, назовем ее A в формате scipy.sparse.csr_matrix.

Если моя машина будет иметь достаточно сил, я бы просто сделать

diagonal_degrees = [] 
for row in A: 
    diagonal_degrees.append(numpy.sum(row!=0)) 

Я даже пытался, но это приводит к

ValueError: array is too big. 

Так что я пытался использовать разреженную структуру SciPy. Я думал об этом пути:

diagonal_degrees = [] 
CSC_format = A.tocsc() # A is in scipys CSR format. 
for i in range(CSC_format.shape[0]): 
    row = CSC_format.getrow(i) 
    diagonal_degrees.append(numpy.sum(row!=0)) 

У меня два вопроса:

  1. Есть ли более эффективный способ, я, возможно, упустили из виду?
  2. Хотя docs of scipy sparse state:

All conversions among the CSR, CSC, and COO formats are efficient, linear-time operations.

Почему я получаю

SparseEfficiencyWarning: changing the sparsity structure of a csr_matrix is expensive. lil_matrix is more efficient. 

в то время как переход от КСО CSC?

+0

Вы получаете сообщение об ошибке при установке элемента в 'csr_matrix'. «Изменение структуры разреженности» не имеет ничего общего с преобразованием между различными разреженными матричными форматами. Это когда вы добавляете «плотный» предмет (ы). –

+2

Если все, что вам нужно сделать, это подсчет ненулевых элементов, ['nonzero'] (http://docs.scipy.org/doc/scipy/reference/generated/scipy.sparse.csr_matrix.nonzero.html#scipy .sparse.csr_matrix.nonzero) выглядит многообещающим. – Avaris

+1

Как уже указывал @avaris, вы можете просто сделать diag_deg, _ = np.histogram (x.nonzero() [0], np.arange (x.shape [0] +1)) ' –

ответ

4

Если вам нужно только подсчитать ненулевые элементы, то может быть полезным метод nonzero.

Точный код будет (с помощью Joe Kington и matehat):

diag_deg, _ = np.histogram(x.nonzero()[0], np.arange(x.shape[0]+1)) 

# generating a diagonal matrix with diag_deg 
dim = x.shape[0] 
diag_mat = np.zeros((dim**2,)) 
diag_mat[np.arange(0, dim**2, dim+1)] = diag_deg 
diag_mat.reshape((dim, dim)) 

Хотя для больших массивов (dim ~ 1 million), как отмечает Aufwind, np.zeros((dim**2,)) дает исключение: ValueError: Maximum allowed dimension exceeded. Альтернативным решением является использование разреженных матриц:

diag_mat = sparse.coo_matrix((dim, dim)) 
diag_mat.setdiag(diag_deg) 
+2

Чтобы добавить к большому решению, если вы хотите создать диагональную матрицу из 'diag_deg', он может написать' diag_mat = np.zeros ((x.shape [0] ** 2,)) 'then' diag_mat [ np.arange (0, x.shape [0] ** 2, x.shape [0] +1)] = diag_deg' и, наконец, 'diag_mat.reshape ((x.shape [0], x.shape [0])) '.Извините за редкий код ... Я не хотел создавать для этого новый ответ;) – matehat

+0

@matehat: Спасибо за завершение решения. Пусть 'dim = x.shape [0]' К сожалению 'np.zeros ((dim ** 2,))' приводит к превышению значения ValueError: Maximum allowed dimension, когда 'dim' слишком велико. В моем случае 'dim' составляет около * миллиона *. Поэтому при работе с матрицами с высокой размерностью нужно выбрать другой способ. Например: 'diag_mat = sparse.coo_matrix ((dim, dim))', а затем 'diag_mat.setdiag (diag_deg)'. – Aufwind

+0

@Avaris: Возможно, вы хотите объединить эти два комментария в свой ответ. Таким образом, он становится более полным и лучше читать для людей, сталкивающихся с аналогичной проблемой. – Aufwind

Смежные вопросы