2011-02-09 22 views
10

Tengo un Matrix escaso en R que aparentemente es demasiado grande para ejecutar as.matrix() (aunque tampoco es súper grande). La llamada as.matrix() en cuestión está dentro de la función svd(), por lo que me pregunto si alguien sabe una implementación diferente de SVD que no requiere la primera conversión a una matriz densa.SVD para matriz dispersa en R

+0

No encuentro nada para R. Un montón de cosas para C, Fortran, Python, etc. –

+0

Tal vez probé SVDLIBC. Se construye como una biblioteca C, así que si funciona bien podría en el futuro incluirlo como un módulo (aunque mi ambición probablemente no durará tanto, si la historia sirve de guía ...). –

+2

¿Qué tal esto http://cran.r-project.org/web/packages/irlba/ Un método rápido y eficiente de la memoria para calcular unos pocos valores singulares aproximados y vectores singulares de matrices grandes. –

Respuesta

10

El paquete irlba tiene un SVD muy rápido implementación para matrices dispersas.

+1

El comentario que menciona el paquete 'irlba' (el tercero en la pregunta) se retrasó un año cuando se publicó. Su respuesta duplica el comentario * otro año * más tarde ... –

+1

@ Ferdinand.kraft Pido disculpas, ya que me perdí el comentario.Esta página es el primer resultado cuando uno busca "R svd sparse", y considerando que 'irlba' es el mejor paquete R para svd escaso, parece una respuesta adecuada. Si el autor del comentario desea publicar una respuesta, me gustaría subirla y eliminar la mía. – Zach

6

Así que esto es lo que terminé haciendo. Es relativamente sencillo para escribir una rutina que vuelca una matriz dispersa (clase dgCMatrix) a un archivo de texto en formato "Texto escasa" de SVDLIBC, a continuación, llamar al ejecutable svd, y leer archivos de los tres texto resultante de nuevo en R.

El La trampa es que es bastante ineficiente. Me toma unos 10 segundos leer & escribir los archivos, pero el cálculo SVD real toma solo unos 0,2 segundos más o menos. Aún así, esto es, por supuesto, mucho mejor que no poder realizar el cálculo en absoluto, así que estoy feliz. =)

+0

Pregunta de seguimiento publicada en http://stackoverflow.com/questions/5009026/extract-long-from-r-object. –

+1

Darse una marca de verificación sin ofrecer ningún ejemplo de datos o código de solución parece contrario a los principios de SO. –

+0

Ya no estoy en la compañía donde hice esto, así que no tengo acceso a ese código. Quería decir que la marca significaba "esta es la solución que en realidad terminé usando". Es bastante diferente de las otras sugerencias, y muy sencillo de implementar. Para arrancar, es realmente la forma "incorrecta" de hacerlo, porque requiere escribir archivos de texto que representan matrices numéricas. Entonces no sé si realmente vale la pena copiar como ejemplo. –

8

Puede hacer un poco muy impresionante de escasa SVD en R mediante la proyección aleatoria como se describe en http://arxiv.org/abs/0909.4061

Aquí hay un código de ejemplo:

# computes first k singular values of A with corresponding singular vectors 
incore_stoch_svd = function(A, k) { 
    p = 10    # may need a larger value here 
    n = dim(A)[1] 
    m = dim(A)[2] 

    # random projection of A  
    Y = (A %*% matrix(rnorm((k+p) * m), ncol=k+p)) 
    # the left part of the decomposition works for A (approximately) 
    Q = qr.Q(qr(Y)) 
    # taking that off gives us something small to decompose 
    B = t(Q) %*% A 

    # decomposing B gives us singular values and right vectors for A 
    s = svd(B) 
    U = Q %*% s$u 
    # and then we can put it all together for a complete result 
    return (list(u=U, v=s$v, d=s$d)) 
} 
+0

Guau, genial. Tendré que intentar eso. –

+2

Así que lo probé y parece que no da muy buenos resultados a menos que lo haga 'p', en cuyo caso no ahorra muchos recursos. Como prueba, hice una matriz aleatoria dispersa de 10000x12000 con 1000 entradas distintas de cero capturadas como runif (1000), que debería tener valores propios alrededor de 0.999 o 1. Pero este método muestra los primeros valores propios como '0.8461391, 0.8423876, 0.8353727, 0.8321352, 0.8271768 , 0.8203687'. –

+2

Lea el documento original. Si sus valores propios tienen el mismo valor, entonces no le ahorrará mucho tal como está. En tales casos, necesita hacer algunas iteraciones para cuadrar su matriz fuente para obtener una mejor dispersión. –

3

rARPACK es el paquete que necesita. Funciona como un encanto y es Superfast porque se paraleliza a través de C y C++.

+0

En 2017, el archivo DESCRIPCIÓN de rArpack v0.11.0 dice: Ahora rARPACK se convierte en un simple shell del paquete RSpectra. – knb

+0

Saltando en incluso años más tarde, tengo que decir que RARPACK y RSpectra son paquetes increíbles. irlba tiene un lugar especial en mi corazón, pero RSpectra es increíblemente rápido – Zach

Cuestiones relacionadas