SVM con scikit learn funziona all'infinito e non completa mai l'esecuzione


76

Sto cercando di eseguire SVR usando scikit learn (python) su un set di dati di allenamento con 595605 righe e 5 colonne (caratteristiche) e test set di dati con 397070 righe. I dati sono stati pre-elaborati e regolarizzati.

Sono in grado di eseguire correttamente gli esempi di test, ma eseguendo usando il mio set di dati e lasciandolo funzionare per più di un'ora, non riuscivo ancora a vedere alcun output o terminazione del programma. Ho provato a eseguire utilizzando un IDE diverso e persino dal terminale, ma questo non sembra essere il problema. Ho anche provato a cambiare il valore del parametro 'C' da 1 a 1e3.

Sto affrontando problemi simili con tutte le implementazioni svm usando scikit.

Non sto aspettando abbastanza per completarlo? Quanto tempo dovrebbe richiedere questa esecuzione?

Dalla mia esperienza non dovrebbe richiedere più di qualche minuto.

Ecco la mia configurazione di sistema: Ubuntu 14.04, 8 GB di RAM, molta memoria libera, processore i7 di quarta generazione


Potresti fornire il codice? Inoltre, l'addestramento o il test richiede così tanto tempo? Che ne dici di piccoli set di dati di training / test?
amico

Sto solo leggendo i dati da un file CSV in un frame di dati Panda e passando alla funzione Scikit Learn. È tutto! Fornire il codice non sarebbe davvero d'aiuto qui
tejaskhot,

6
L'implementazione SVM di sklearn implica almeno 3 passaggi: 1) creazione di un oggetto SVR, 2) adattamento di un modello, 3) previsione del valore. Il primo passo descrive il kernel in uso, che aiuta a capire molto meglio i processi interni. Il secondo e il terzo passaggio sono piuttosto diversi e dobbiamo sapere almeno quale di essi impiega così tanto tempo. Se si sta allenando, allora potrebbe essere ok, perché l'apprendimento a volte è lento. Se sta testando, probabilmente c'è un bug, perché il test in SVM è molto veloce. Inoltre, potrebbe essere la lettura CSV che impiega così tanto tempo e non SVM. Quindi tutti questi dettagli possono essere importanti.
amico

sto affrontando lo stesso problema anche tramite svm ma qualcuno può dirmi quanto tempo ci vorrà dopo la normalizzazione?
kashyap kitchlu,

Risposte:


70

Le SVM con kernel richiedono il calcolo di una funzione di distanza tra ciascun punto nel set di dati, che è il costo dominante di . La memorizzazione delle distanze è un peso per la memoria, quindi vengono ricalcolate al volo. Per fortuna, la maggior parte delle volte sono necessari solo i punti più vicini al limite di decisione. Le distanze calcolate di frequente vengono archiviate in una cache. Se la cache viene bloccata, il tempo di esecuzione aumenta fino a .O ( n caratteristiche × n 3 osservazioni )O(nfeatures×nobservations2)O(nfeatures×nobservations3)

È possibile aumentare questa cache richiamando SVR come

model = SVR(cache_size=7000)

In generale, questo non funzionerà. Ma non tutto è perduto. È possibile sottocampionare i dati e utilizzare il resto come set di convalida oppure è possibile scegliere un modello diverso. Al di sopra della gamma di osservazione di 200.000, è saggio scegliere studenti lineari.

Kernel SVM può essere approssimato, approssimando la matrice del kernel e alimentandola a un SVM lineare. Ciò consente di scambiare precisione e prestazioni in tempi lineari.

Un mezzo popolare per raggiungere questo obiettivo è usare circa 100 centri cluster trovati da kmeans / kmeans ++ come base della funzione del kernel. Le nuove funzionalità derivate vengono quindi inserite in un modello lineare. Funziona molto bene in pratica. Strumenti come sophia-ml e vowpal wabbit sono il modo in cui Google, Yahoo e Microsoft fanno questo. L'input / output diventa il costo dominante per semplici studenti lineari.

Nell'abbondanza di dati, i modelli non parametrici funzionano più o meno allo stesso modo per la maggior parte dei problemi. Le eccezioni sono input strutturati, come testo, immagini, serie storiche, audio.

Ulteriori letture


16

SVM risolve un problema di ottimizzazione dell'ordine quadratico.

Non ho nulla da aggiungere che non sia stato detto qui. Voglio solo pubblicare un link nella pagina sklearn su SVC che chiarisca cosa sta succedendo:

L'implementazione si basa su libsvm. La complessità del tempo di adattamento è più che quadratica con il numero di campioni che rende difficile il ridimensionamento del set di dati con più di un paio di 10000 campioni.

Se non si desidera utilizzare i kernel e è sufficiente un SVM lineare, è disponibile LinearSVR che è molto più veloce perché utilizza un approccio di ottimizzazione per le regressioni lineari. Dovrai però normalizzare i tuoi dati, nel caso in cui non lo avessi già fatto, poiché applica la regolarizzazione al coefficiente di intercettazione, che probabilmente non è quello che desideri. Significa che se la media dei tuoi dati è lontana da zero, non sarà in grado di risolverlo in modo soddisfacente.

Ciò che è possibile utilizzare è anche la discesa gradiente stocastica per risolvere il problema di ottimizzazione. Sklearn include SGDRegressor . Devi usare loss='epsilon_insensitive'per avere risultati simili a SVM lineare. Vedi la documentazione Userei solo la discesa del gradiente come ultima risorsa, perché implica una grande modifica degli iperparametri al fine di evitare di rimanere bloccati nei minimi locali. Usa LinearSVRse puoi.


Ho avuto un set di dati con molte righe. SVC ha iniziato a impiegare troppo tempo per me circa 150.000 righe di dati. Ho usato il tuo suggerimento con LinearSVR e un milione di righe richiede solo un paio di minuti. PS ha anche riscontrato che il classificatore LogisticRegression produce risultati simili a LinearSVR (nel mio caso) ed è ancora più veloce.
jeffery_the_wind,

8

Hai incluso il ridimensionamento nella fase di pre-elaborazione? Ho avuto questo problema durante l'esecuzione del mio SVM. Il mio set di dati è ~ 780.000 campioni (riga) con 20 funzioni (col). Il mio set di allenamento è di ~ 235k campioni. Si è scoperto che ho appena dimenticato di ridimensionare i miei dati! In questo caso, prova ad aggiungere questo bit al tuo codice:

ridimensionare i dati su [-1,1]; aumentare la velocità SVM:

da sklearn.preprocessing import MinMaxScaler
ridimensionamento = MinMaxScaler (feature_range = (- 1,1)). fit (X_train)
X_train = scaling.transform (X_train)
X_test = scaling.transform (X_test)


2
Qualcuno può spiegare perché questo accelera l'adattamento SVM?
Lppier,

1
C'è un motivo per cui hai scelto MinMaxScaler invece di qualsiasi altro? StandardScaler per esempio?
raspi,

@Ippier: essenzialmente stai riducendo il possibile spazio al contorno per ogni opzione in un modo che riduca il livello di sforzo molto meno per la tua macchina.
Ike,

7

Con un set di dati così grande penso che staresti meglio usando una rete neurale, l'apprendimento profondo, una foresta casuale (sono sorprendentemente buoni), ecc.

Come menzionato nelle risposte precedenti, il tempo impiegato è proporzionale alla terza potenza del numero di campioni di addestramento. Anche il tempo di previsione è polinomiale in termini di numero di vettori di test.

Se devi davvero utilizzare SVM, ti consiglio di utilizzare GPU per accelerare o ridurre le dimensioni del set di dati di allenamento. Prova prima con un campione (forse 10.000 righe) dei dati per vedere se non si tratta di un problema con il formato o la distribuzione dei dati.

Come menzionato in altre risposte, i kernel lineari sono più veloci.


3

Di recente ho riscontrato un problema simile perché ho dimenticato di ridimensionare le funzionalità nel mio set di dati che in precedenza era stato utilizzato per formare il tipo di modello di ensemble. L'incapacità di ridimensionare i dati potrebbe essere il probabile colpevole, come indicato da Shelby Matlock. Puoi provare diversi scaler disponibili in sklearn, come RobustScaler :

from sklearn.preprocessing import RobustScaler scaler = RobustScaler() X = scaler.fit_transfrom(X)

X è ora trasformato / ridimensionato e pronto per essere inviato al modello desiderato.


2

Questo ha senso. IIUC, la velocità di esecuzione delle operazioni del vettore di supporto è vincolata dal numero di campioni, non dalla dimensionalità. In altre parole, è limitato dal tempo della CPU e non dalla RAM. Non sono sicuro di quanto tempo dovrebbe essere necessario, ma sto eseguendo alcuni benchmark per scoprirlo.


1

Lasciare funzionare durante la notte o meglio per 24 ore. Qual è il tuo utilizzo della CPU? Se nessuno dei core funziona al 100%, allora hai un problema. Probabilmente con la memoria. Hai verificato se il tuo set di dati si adatta a 8 GB? Hai provato SGDClassifier? È uno dei più veloci lì. Vale la pena provare prima sperando che si completi in circa un'ora.


SGDClassifiernon supporta i kernel. Se l'OP vuole SVM lineare, allora consiglierei prima di provare LinearSVR. È molto più veloce di SVRperché risolve il problema utilizzando una libreria di regressione lineare e il minimo globale è garantito (a differenza del gradiente discendente).
Ricardo Cruz,

Apprezzo il tuo commento. Potresti spiegare perché il supporto del kernel è un problema?
Diego,

Dalla documentazione , The loss function to be used. Defaults to ‘hinge’, which gives a linear SVM.stessa cosa per SGDRegressor. SGDRegressorè equivalente all'utilizzo SVR(kernel='linear'). Se questo è ciò che vuole OP, va benissimo. Avevo l'impressione che volesse usare SVM con un kernel. In caso contrario, consiglierei di provare prima LinearSVR.
Ricardo Cruz,

1

Prova a normalizzare i dati su [-1,1]. Ho affrontato un problema simile e alla normalizzazione tutto ha funzionato bene. Puoi normalizzare facilmente i dati usando:

from sklearn import preprocessing X_train = preprocessing.scale(X_train) X_test = preprocessing.scale(X_test)


@Archie Questa è una risposta a una domanda, non a una domanda.
timleathart,

1

Ho riscontrato questo problema e, cache_sizecome suggeriscono altri, non aiuta affatto. Puoi vedere questo post e questo come il principale collaboratore che ha suggerito di cambiare il codice manualmente.

Come sapete, SVCe SVRsono problemi di ottimizzazione e si arresta quando il margine di errore è così poco in cui l'ulteriore ottimizzazione è inutile. Quindi c'è un altro parametro in questi, max_iterdove puoi impostare quante iterazioni dovrebbe fare.

Ho usato sklearnin Python e e1071in R e R è molto più veloce ottenere il risultato senza impostare il max_itere sklearnrichiede 2-4 volte più a lungo. L'unico modo in cui potevo ridurre il tempo di calcolo per Python era usare max_iter. E 'relativo alla complessità del modello, numero di caratteristiche, noccioli e iperparametri, ma per i piccoli set di dati che ho usato per circa 4000 punto dati e max_iterfu 10000i risultati non erano diversi a tutti e era accettabile.


0

Ho appena avuto un problema simile con un set di dati che contiene solo 115 elementi e una sola funzione (dati di compagnie aeree internazionali). La soluzione era ridimensionare i dati. Quello che mi mancava nelle risposte finora è stato l'uso di una pipeline:

from sklearn.svm import SVR
from sklearn.preprocessing import StandardScaler, MinMaxScaler

model = Pipeline([('scaler', StandardScaler()),
                  ('svr', SVR(kernel='linear'))])

Puoi allenarti modelcome un normale modello di classificazione / regressione e valutarlo allo stesso modo. Non cambia nulla, solo la definizione del modello.


Che cosa è Pipeline? Non lo stai importando.
Bram Vanroy,

0

Devi ridimensionare i tuoi dati. Il ridimensionamento normalizzerà i punti di dati in un intervallo compreso tra -1 e 1, il che consentirà una convergenza più rapida.

Prova a utilizzare il seguente codice:

# X is your numpy data array.

from sklearn import preprocessing

X = preprocessing.scale(X)

benvenuto in Data Science SE! Potresti spiegare in che modo il tuo suggerimento aiuterà OP? Quello che stai suggerendo è un ridimensionamento di un array. Non è chiaro come ciò possa o meno influire sull'algoritmo SVR in scikit learn.
Stereo
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.