2015-12-08 47 views
6

Ho una matrice molto grande che sto cercando di eseguire su glmnet su un server con molta memoria. Funziona bene anche su molto grandi insiemi di dati fino a un certo punto, dopo che ottengo il seguente errore:Limite dimensione vettore R: "i vettori lunghi (argomento 5) non sono supportati in .C"

Error in elnet(x, ...) : long vectors (argument 5) are not supported in .C 

Se ho capito bene questo è causato da una limitazione in R che non può avere alcuna vettore con lunghezza maggiore di INT_MAX. È corretto? Ci sono soluzioni disponibili a questo che non richiedono una completa riscrittura di glmnet? Qualcuno degli interpreti R alternativi (Riposte, ecc.) Affronta questa limitazione?

Grazie!

+0

Durante il codice, si esegue un subset della matrice? Potrei sbagliarmi ma non puoi eseguire una subsetting della matrice se la matrice ha più di 36 miliardi di elementi. In tal caso devi sottoporre a matrice la matrice come se fosse un enorme vettore atomico (che in effetti è dato dal fatto che una matrice è solo un vecotr con un attributo dimesion). – SabDeM

+0

Nel mio codice sto usando un file bigmatrix supportato per evitare questi problemi, ma quando eseguo glmnet devo passarlo come una matrice R come questa: 'theMatrix [,]'. – Danny

+2

Ciao Danny. Il mio commento non è direttamente correlato alla domanda, ma mb aiuterà. Dai un'occhiata al pacchetto pirls di Michael Kane - https://github.com/kaneplusplus/pirls. Mb questo risolutore funziona con i vettori lunghi. –

risposta

4

Poiché la versione 3 R supporta i vettori lunghi. Un vettore lungo viene indicizzato da double. Un vettore lungo può essere una base per una matrice o un array di dimensioni superiori a 2 purché ogni dimensione sia sufficientemente piccola per essere indicizzabile con uno integer. I vettori lunghi non possono essere passati al codice nativo tramite .C e .Fortran. Il messaggio di errore che stai ricevendo è perché un vettore lungo viene passato tramite .C.

I vettori lunghi possono essere passati tramite .Call. Quindi, finché il codice nativo di glmnet potrebbe supportare i vettori lunghi (indici a 64 bit) o ​​potrebbe essere modificato/compilato per supportarlo, uno solo dovrebbe modificare l'interfaccia tra R e il codice nativo di glmnet. Puoi farlo manualmente in C e c'è anche un nuovo pacchetto chiamato dotCall64 per questa attività. Parte della modifica dell'interfaccia sta decidendo quando copiare gli argomenti - .C/.Fortran fa una copia preventiva, ma non si vuole farlo inutilmente con strutture di dati di grandi dimensioni.

Penso che la difficoltà di cambiare il codice nativo di glmnet per supportare indici a 64 bit dipende dal codice reale (che ho solo guardato ma non ho mai lavorato). È facile convertire tutti i numeri interi (o in modo esplicito o implicitamente interi a 32 bit) nel codice Fortran a 64 bit. I problemi arrivano quando alcuni numeri interi devono rimanere a 32 bit, e ciò avverrà per es. per i vettori interi passati da/a codice R, perché R usa numeri interi a 32 bit (anche nei vettori lunghi in effetti). Ci sono questi vettori interi passati in glmnet. Quanto è difficile la modifica dipende da quanto è pulito il codice Fortran originale (ad esempio se utilizza variabili intere separate per l'indicizzazione e l'accesso ai valori di matrici di interi, ecc.).

Implementazioni sperimentali di sottoinsiemi di R, come Riposte, non aiuteranno.

+0

Grazie per le informazioni, ma alcuni scavi sembrano indicare che per passare da .C a .Call sono necessarie importanti modifiche al codice Fortran sottostante. Questo è esattamente quello che sto cercando di evitare. Sembra che semplicemente non ci sia una soluzione adatta alle mie esigenze. – Danny

+1

Ho aggiornato la mia risposta. Penso che la difficoltà dipenda dal codice reale, quindi le persone che hanno lavorato con quel codice potrebbero dare la migliore risposta. La mia ipotesi: dopo un giorno o due di programmazione avresti fatto o avere una buona stima. Certamente questo non dovrebbe essere una completa riscrittura. –

+0

Sembra averlo fatto! La chiave per me era il pacchetto dotCall64. L'uso di .Call è stato un po 'oltre il tempo e la complessità ho tempo per ora, ma con dotCall64 ho semplicemente dovuto ricomporre le chiamate .Fortran e aggiungere un elenco di tipi di dati per le variabili di input. Identificare i tipi di dati corretti ha richiesto un po 'di tempo, ma non era troppo difficile. Ci sono ancora alcuni problemi con la memoria, ma penso che sarò in grado di aggirarli. Grazie mille Tomas! – Danny

2

C'è una nota in cui si afferma ?"long vector":

However, compiled code typically needs quite extensive changes. Note that the .C and .Fortran interfaces do not accept long vectors, so .Call (or similar) has to be used.

elnet rende .Fortran chiamate. Dovresti modificare la funzione per utilizzare .Call, magari tramite un wrapper C che chiama il codice FORTRAN ed eventualmente riscrivere e compilare il codice FORTRAN pertinente per gestire i vettori lunghi.

+0

Grazie per le informazioni, ma alcuni scavi sembrano indicare che per passare da .C a .Call è necessario apportare importanti modifiche al codice Fortran sottostante. Questo è esattamente quello che sto cercando di evitare. Sembra che semplicemente non ci sia una soluzione adatta alle mie esigenze. – Danny

+0

No, se il codice sottostante è incorporato in vettori a 32 bit, temo che tu sia bloccato con esso. – James