2012-09-06 18 views
18

Me gustaría escribir una función que normalice las filas de una matriz dispersa grande (de modo que sumen a una).Manera eficiente de normalizar una matriz dispersa de Scipy

from pylab import * 
import scipy.sparse as sp 

def normalize(W): 
    z = W.sum(0) 
    z[z < 1e-6] = 1e-6 
    return W/z[None,:] 

w = (rand(10,10)<0.1)*rand(10,10) 
w = sp.csr_matrix(w) 
w = normalize(w) 

Sin embargo, esto da la siguiente excepción:

File "/usr/lib/python2.6/dist-packages/scipy/sparse/base.py", line 325, in __div__ 
    return self.__truediv__(other) 
File "/usr/lib/python2.6/dist-packages/scipy/sparse/compressed.py", line 230, in __truediv__ 
    raise NotImplementedError 

¿Hay soluciones razonablemente simples? Miré this, pero aún no estoy seguro de cómo hacer la división.

+3

Esto es básicamente un duplicado de: http: //stackoverflow.c om/questions/12237954/multiplying-elements-in-a-sparse-array-with-rows-in-matrix ya que no importa si se trata de una división o multiplicación de elementos por fila. Por supuesto, si alguien tiene una mejor respuesta, genial :) – seberg

+0

Genial, ¡gracias! – sterne

+0

No estoy de acuerdo, este es un problema diferente. El duplicado que apuntó hace multiplicación de elemento, mientras que esta pregunta parece querer dividir cada fila por un valor diferente (en lugar de todos los elementos distintos de cero por el mismo valor). La siguiente solución de Aaron McDaid debería funcionar de manera eficiente (y no requiere ninguna copia de datos). – conradlee

Respuesta

29

Esto se ha implementado en scikit-learn sklearn.preprocessing.normalize.

from sklearn.preprocessing import normalize 
w_normalized = normalize(w, norm='l1', axis=1) 

axis=1 debería normalizar por filas, axis=0 para normalizar por columna. Use el argumento opcional copy=False para modificar la matriz en su lugar.

+2

Tenga en cuenta que si se normaliza por características (axis = 0), entonces la matriz devuelta es de tipo 'csc' incluso si w fuera un 'csr'. Esto puede ser desagradable si cuenta con que es un 'csr' – Leo

3

aquí está mi solución.

  • transpuesta Una suma
  • cálculo de cada col
  • formato de matriz diagonal B con recíproca de suma
  • A * B es igual a la normalización
  • transpuesta C

    import scipy.sparse as sp 
    import numpy as np 
    import math 
    
    minf = 0.0001 
    
    A = sp.lil_matrix((5,5)) 
    b = np.arange(0,5) 
    A.setdiag(b[:-1], k=1) 
    A.setdiag(b) 
    print A.todense() 
    A = A.T 
    print A.todense() 
    
    sum_of_col = A.sum(0).tolist() 
    print sum_of_col 
    c = [] 
    for i in sum_of_col: 
        for j in i: 
         if math.fabs(j)<minf: 
          c.append(0) 
         else: 
          c.append(1/j) 
    
    print c 
    
    B = sp.lil_matrix((5,5)) 
    B.setdiag(c) 
    print B.todense() 
    
    C = A*B 
    print C.todense() 
    C = C.T 
    print C.todense() 
    
Cuestiones relacionadas