Estoy tratando de escribir un algoritmo de agrupamiento espectral utilizando NumPy/SciPy para sistemas más grandes (pero aún tratables), haciendo uso de la biblioteca de álgebra lineal dispersa de SciPy. Desafortunadamente, estoy teniendo problemas de estabilidad con eigsh().Escaso eigsh de Scipy() para valores propios pequeños
Aquí está mi código:
import numpy as np
import scipy.sparse
import scipy.sparse.linalg as SLA
import sklearn.utils.graph as graph
W = self._sparse_rbf_kernel(self.X_, self.datashape)
D = scipy.sparse.csc_matrix(np.diag(np.array(W.sum(axis = 0))[0]))
L = graph.graph_laplacian(W) # D - W
vals, vects = SLA.eigsh(L, k = self.k, M = D, which = 'SM', sigma = 0, maxiter = 1000)
La biblioteca sklearn
se refiere al paquete scikit-learn, específicamente this method para calcular un laplaciano gráfico a partir de una matriz SciPy escasa.
_sparse_rbf_kernel
es un método que escribí para calcular las afinidades por pares de los puntos de datos. Funciona creando una matriz de afinidad dispersa a partir de datos de imagen, específicamente solo computando afinidades por pares para los 8 barrios alrededor de cada píxel (en lugar de pairwise para todos los píxeles con el método rbf_kernel
de scikit-learn, que para el registro tampoco soluciona esto))
Dado que el laplaciano no está normalizado, estoy buscando los autovalores más pequeños y los vectores propios correspondientes del sistema. Entiendo que ARPACK is ill-suited for finding small eigenvalues, pero estoy tratando de usar shift-invert para encontrar estos valores y todavía no estoy teniendo mucho éxito.
Con los argumentos anteriores (en concreto, sigma = 0
), me sale el siguiente error:
RuntimeError: Factor is exactly singular
Con sigma = 0.001
, me sale un error diferente:
scipy.sparse.linalg.eigen.arpack.arpack.ArpackNoConvergence: ARPACK error -1: No convergence (1001 iterations, 0/5 eigenvectors converged)
He probado los tres diferentes valores para mode
con el mismo resultado. ¿Alguna sugerencia para usar la biblioteca dispersa de SciPy para encontrar valores propios pequeños de un sistema grande?
Correcto, pero el problema es que quiero los autovalores más pequeños y sus autovectores asociados, no el más grande. La documentación explica que si se desean valores propios pequeños, se debe usar el modo shift-inverter para mejorar el rendimiento, que es lo que estaba tratando de hacer mediante el uso de 'sigma', en vano. – Magsol
Lo anterior debe darle exactamente lo que quiere. Nota: con sigma = 0, los autovalores transformados son w '= 1/(w-sigma) = 1/w. Por lo tanto, con 'which = 'LM'' obtienes los autovalores con ** ** ** grandes, o en otras palabras, los autovalores más pequeños del problema original. Si usa el modo shift-invert, necesita ajustar también el parámetro 'which' en consecuencia. –
Solo quería decir que esto fue extremadamente útil – YXD