En función de la densidad de ceros en una matriz estas se pueden clasificar como dispersas ("sparse"), en las que valores igual a cero son dominantes, o densas ("dense"), en las que hay pocos registros iguales a cero. En aprendizaje automático es habitual encontrar matrices dispersas. Por ejemplo, en características que representan propiedades binarias o recuentos de ocurrencias. Almacena directamente en memoria las matrices dispersas como si las densas es un problema, ya que en la mayoría de los registros no se guarda información. Pero utiliza la memoria.
Las matrices dispersas
Las matrices dispersas son aquellas en las que la mayoría de los registros son cero. Este hecho hace que sea posible más eficaz trabajar con ellas guardando sólo las posiciones de los valores de los elementos distintos de cero. Lo que supone un importante ahorro en el a la hora de almacenar estas matrices en memoria o disco.
Otro problema de las matrices dispersas es a la hora de utilizarlas en operaciones matemáticas. Unas matrices muy grandes pueden no caber en memoria, haciendo más complicado llevar a cabo las operaciones.
Para medir el grado de dispersión de una matriz se puede utilizar un sencillo indicador ("sparsity"). La ratio entre el número de ceros en una matriz y el número total de elementos permite identificar aquellas matrices que pueden ser problemáticas. En Python se puede implementar esta métrica con el siguiente código.
import numpy as np def sparsity(sparse): return (sparse == 0).sum() / sparse.size sparsity(np.identity(3))
En donde se puede ver que la matriz identidad de orden 3 tiene un grado de dispersión de 0,66.
Cómo trabajar con matrices dispersas
La solución para trabajar con matrices dispersas es usar una estructura de datos diferente a la que se utiliza en matrices densas. En lugar de almacenar los valores unos detrás de otros se pueden utilizar diferentes estructuras como:
- Diccionarios: la llave del diccionario es la posición en la matriz y la clave es el valor del registro.
- Lista de listas: cada fila de la matriz se guarda como una lista y en cada una de las listas secundarias se guarda el índice de la columna y el valor.
- Lista de coordenadas: se crear una lista de tuplas en las que se almacena las coordenadas y el valor.
Matrices dispersas en Python
Las herramientas para transformar matrices densas en dispersar, trabajar con matrices dispersas y volver a convertir las matrices dispersas en densas se pueden encontrar en la librería SciPy. Además, la mayoría de las funciones de álgebra lineal tanto de SciPy como NumPy permiten utilizar estas matrices de forma transparente. Es decir, pueden utilizar matrices dispersas o de forma indiferente.
La función con la que se puede convertir una matriz densa en dispersa es csr_matrix()
. Posteriormente las matrices dispersas disponen de una propiedad todense()
con la que se obtiene una matriz densa. Esto es lo que se puede ver en el siguiente ejemplo:
from scipy.sparse import csr_matrix # Convertir un matriz densa en dispersa S = csr_matrix(np.identity(3)) # Representación de una matriz dispersa print(S) # Convertir un matriz dispersa en densa D = S.todense() # Representación de una matriz densa print(D)
(0, 0) 1.0 (1, 1) 1.0 (2, 2) 1.0 [[1. 0. 0.] [0. 1. 0.] [0. 0. 1.]]
En este ejemplo se pude ver como en la matriz dispensa solamente se almacena los valores que son diferentes de cero junto a sus coordenadas. Mientras que en la matriz densa se almacenar todos. Esto es un ahorro de memoria mayor a medida que crezca el grado de dispersión de la matriz.
Conclusiones
Las matrices son objetos que requieren bastante memoria. Cuando estas son dispersas y grandes es aconsejable almacenarlas de forma diferente para reducir el espacio que estas consumen en memoria.
Imágenes: Pixabay (Steve Buissinne)