xticks barplot python scipy sparse-matrix

python - barplot - pandas plot



OperaciĆ³n de suma extremadamente lenta en la matriz LIL dispersa en Python (1)

He escrito este código en Python que está dando los resultados esperados pero es extremadamente extremadamente lento. El cuello de botella es la suma de múltiples filas de scipy.sparse.lil_matrix. ¿Cómo puedo hacerlo rápido?

# D1 is a 1.5M x 1.3M sparse matrix, read as scipy.sparse.lil_matrix. # D2 is a 1.5M x 111 matrix, read as numpy.array # F1 is a csv file, read using csv.reader for row in F1: user_id = row[0] clust = D2[user_id, 110] neighbors = D2[ D2[:, 110] == clust][:,1] score = np.zeros(1300000) for neigh in neighbors: score = score + D1 [neigh, :] # the most expensive operation toBeWritten = np.argsort(score)[:,::-1].A[0,:]

Por favor, avíseme si hay algo más que no sea muy óptimo.


Primero una demostración con una matriz muy pequeña

In [523]: idx=np.arange(0,8,2) In [526]: D=np.arange(24).reshape(8,3) In [527]: Dll=sparse.lil_matrix(D) In [528]: D[idx,:].sum(axis=0) Out[528]: array([36, 40, 44]) In [529]: Dll[idx,:].sum(axis=0) Out[529]: matrix([[36, 40, 44]], dtype=int32) In [530]: timeit D[idx,:].sum(axis=0) 100000 loops, best of 3: 17.3 µs per loop In [531]: timeit Dll[idx,:].sum(axis=0) 1000 loops, best of 3: 1.16 ms per loop In [532]: score=np.zeros(3) # your looping version In [533]: for i in idx: .....: score = score + Dll[i,:] In [534]: score Out[534]: matrix([[ 36., 40., 44.]]) In [535]: %%timeit .....: score=np.zeros(3) .....: for i in idx: score = score + Dll[i,:] .....: 100 loops, best of 3: 2.76 ms per loop

Para algunas operaciones, el formato csr es más rápido:

In [537]: timeit Dll.tocsr()[idx,:].sum(axis=0) 1000 loops, best of 3: 955 µs per loop

o si preconvierto a csr:

In [538]: Dcsr=Dll.tocsr() In [539]: timeit Dcsr[idx,:].sum(axis=0) 1000 loops, best of 3: 724 µs per loop

Todavía lento en comparación con denso.

Iba a hablar sobre trabajar con los atributos de datos de la matriz dispersa como una forma de seleccionar filas más rápido. Pero si el único propósito para seleccionar estas filas es sumar sus valores, no es necesario que hagamos eso.

Las matrices dispersas suman en filas o columnas haciendo un producto de matriz con una columna o una matriz de fila de unos. Y acabo de responder otra pregunta con la misma respuesta.

https://.com/a/37120235/901925 Efficiently compute columnwise sum of sparse array where every non-zero element is 1

Por ejemplo:

In [588]: I=np.asmatrix(np.zeros((1,Dll.shape[0]))) In [589]: I[:,idx]=1 In [590]: I Out[590]: matrix([[ 1., 0., 1., 0., 1., 0., 1., 0.]]) In [591]: I*Dll Out[591]: matrix([[ 36., 40., 44.]]) In [592]: %%timeit I=np.asmatrix(np.zeros((1,Dll.shape[0]))) I[:,idx]=1 I*Dll .....: 1000 loops, best of 3: 919 µs per loop

Para esta pequeña matriz no ayudó a la velocidad, pero con el tiempo de Dcsr reduce a 215 µs (es mucho mejor para las matemáticas). Con matrices grandes, esta versión del producto mejorará.

=================

Acabo de descubrir, en otra pregunta, que una selección de fila A_csr[[1,1,0,3],:] se realiza realmente con un producto de matriz. Construye una matriz csr ''extractor'' que se parece a

matrix([[0, 1, 0, 0], [0, 1, 0, 0], [1, 0, 0, 0], [0, 0, 0, 1]])

https://.com/a/37245105/901925