Uso de una matriz dispersa frente a una matriz numpy
El paquete de matrices dispersas scipy
, y otros similares en MATLAB, se basó en ideas desarrolladas a partir de problemas de álgebra lineal, como la resolución de grandes ecuaciones lineales dispersas (por ejemplo, implementaciones de diferencias finitas y elementos finitos). Así que cosas como el producto de matrices (el producto dot
para matrices de numpy) y los solucionadores de ecuaciones están bien desarrollados.
Mi experiencia aproximada es que un producto de matrices csr
dispersas tiene que tener un 1% de dispersidad para ser más rápido que la operación dot
densa equivalente – en otras palabras, un valor no cero por cada 99 ceros. (pero vea las pruebas más abajo)
Pero la gente también intenta usar matrices dispersas para ahorrar memoria. Pero hay que tener en cuenta que una matriz de este tipo tiene que almacenar 3 matrices de valores (al menos en el formato coo
). Así que la sparsity tiene que ser inferior a 1/3 para empezar a ahorrar memoria. Obviamente no vas a ahorrar memoria si primero construyes la matriz densa, y creas la dispersa a partir de ella.
El paquete scipy
implementa muchos formatos dispersos. El formato coo
es el más fácil de entender y construir. Construya uno de acuerdo con la documentación y mire sus atributos .data
, .row
y .col
(matrices de 3 1d).
csr
y csc
se construyen típicamente a partir del formato coo
, y comprimen los datos un poco, haciéndolos un poco más difíciles de entender. Pero tienen la mayor parte de la funcionalidad matemática.
También es posible indexar el formato csr
, aunque en general esto es más lento que el caso equivalente de matriz densa/array. Otras operaciones como el cambio de valores (especialmente de 0 a distinto de cero), la concatenación, el crecimiento incremental, también son más lentos.
lil
(listas de listas) también es fácil de entender, y mejor para la construcción incremental. dok
es en realidad una subclase de diccionario.
Un punto clave es que una matriz dispersa se limita a 2d, y en muchos aspectos se comporta como la clase np.matrix
(aunque no es una subclase).
Una búsqueda de otras preguntas utilizando scikit-learn
y sparse
podría ser la mejor manera de encontrar los pros / contras de la utilización de estas matrices. He respondido a varias preguntas, pero conozco mejor el lado ‘sparse’ que el lado ‘learn’. Creo que son útiles, pero tengo la sensación de que el ajuste no es siempre el mejor. Cualquier personalización está en el lado learn
. Hasta ahora el paquete sparse
no ha sido optimizado para esta aplicación.
Acabo de probar algunos productos matriciales, utilizando el método sparse.random
para crear una matriz dispersa con una dispersidad especificada. La multiplicación de matrices dispersas se comportó mejor de lo que esperaba.
In : M=sparse.random(1000,1000,.5)In : timeit M1=M*M1 loops, best of 3: 2.78 s per loopIn : timeit Ma=M.toarray(); M2=Ma.dot(Ma)1 loops, best of 3: 4.28 s per loop
Es un problema de tamaño; para matrices más pequeñas el dot
denso es más rápido
In : M=sparse.random(100,100,.5)In : timeit M1=M*M100 loops, best of 3: 3.24 ms per loopIn : timeit Ma=M.toarray(); M2=Ma.dot(Ma)1000 loops, best of 3: 1.44 ms per loop
Pero compara la indexación
In : timeit M.tocsr()10 loops, best of 3: 86.4 ms per loopIn : timeit Ma1000000 loops, best of 3: 318 ns per loopIn : timeit Ma=M.toarray();Ma10 loops, best of 3: 23.6 ms per loop