SVM, das scikit learn verwendet, wird endlos ausgeführt und schließt die Ausführung nie ab


76

Ich versuche, SVR mit Scikit Learn (Python) auf einem Trainingsdatensatz mit 595605 Zeilen und 5 Spalten (Features) und einem Testdatensatz mit 397070 Zeilen auszuführen. Die Daten wurden vorverarbeitet und reguliert.

Ich kann die Testbeispiele erfolgreich ausführen. Wenn ich jedoch meinen Datensatz verwende und ihn länger als eine Stunde laufen lasse, sehe ich immer noch keine Ausgabe oder Programmbeendigung. Ich habe versucht, mit einer anderen IDE und sogar vom Terminal auszuführen, aber das scheint nicht das Problem zu sein. Ich habe auch versucht, den Parameterwert 'C' von 1 auf 1e3 zu ändern.

Ich stehe vor ähnlichen Problemen bei allen SVM-Implementierungen mit Scikit.

Warte ich nicht genug, bis es fertig ist? Wie lange sollte diese Ausführung dauern?

Nach meiner Erfahrung sollte es nicht länger als ein paar Minuten dauern.

Hier ist meine Systemkonfiguration: Ubuntu 14.04, 8 GB RAM, viel freier Speicher, i7-Prozessor der 4. Generation


Könnten Sie den Code bereitstellen? Auch dauert das Training oder Testen so lange? Wie wäre es mit kleineren Trainings- / Testdatensätzen?
Freund

Ich lese gerade Daten aus einer CSV-Datei in einen Pandas-Datenrahmen und übergebe sie an die Scikit-Lernfunktion. Das ist alles! Die Bereitstellung von Code würde hier nicht wirklich helfen
Tejaskhot

6
Die SVM-Implementierung von sklearn umfasst mindestens drei Schritte: 1) Erstellen eines SVR-Objekts, 2) Anpassen eines Modells, 3) Vorhersagen des Werts. Der erste Schritt beschreibt den verwendeten Kernel, wodurch die inneren Prozesse besser verstanden werden. Zweiter und dritter Schritt sind ziemlich unterschiedlich, und wir müssen zumindest wissen, welcher von ihnen so lange dauert. Wenn es sich um ein Training handelt, ist es möglicherweise in Ordnung, da das Lernen manchmal langsam ist. Wenn es sich um einen Test handelt, liegt wahrscheinlich ein Fehler vor, da das Testen in SVM sehr schnell ist. Außerdem kann es sein, dass das CSV-Lesen so lange dauert und nicht SVM. All diese Details können also wichtig sein.
Freund

Ich stehe dem gleichen Problem auch durch SVM gegenüber, aber kann mir jemand sagen, wie viel Zeit es nach der Normalisierung dauern wird?
Kashyap Kitchlu

Antworten:


69

Kernelisierte SVMs erfordern die Berechnung einer Abstandsfunktion zwischen jedem Punkt im Datensatz, was die dominierenden Kosten von . Die Speicherung der Entfernungen ist eine Belastung für das Gedächtnis, so dass sie sofort neu berechnet werden. Zum Glück werden die meiste Zeit nur die Punkte benötigt, die der Entscheidungsgrenze am nächsten liegen. Häufig berechnete Entfernungen werden in einem Cache gespeichert. Wenn der Cache überlastet wird, steigt die Laufzeit auf .O ( n Merkmale × n 3 Beobachtungen )O(nfeatures×nobservations2)O(nfeatures×nobservations3)

Sie können diesen Cache erhöhen, indem Sie SVR as aufrufen

model = SVR(cache_size=7000)

Im Allgemeinen wird dies nicht funktionieren. Aber es ist nicht alles verloren. Sie können die Daten subsampeln und den Rest als Validierungssatz verwenden oder ein anderes Modell auswählen. Oberhalb des Beobachtungsbereichs von 200.000 ist es ratsam, lineare Lernende auszuwählen.

Die Kernel-SVM kann approximiert werden, indem die Kernelmatrix approximiert und einer linearen SVM zugeführt wird. Auf diese Weise können Sie den Kompromiss zwischen Genauigkeit und Leistung in linearer Zeit ziehen.

Ein beliebtes Mittel, um dies zu erreichen, ist die Verwendung von etwa 100 Cluster-Zentren, die von kmeans / kmeans ++ als Grundlage für Ihre Kernelfunktion ermittelt wurden. Die neu abgeleiteten Merkmale werden dann in ein lineares Modell eingespeist. Das funktioniert in der Praxis sehr gut. Tools wie Sophia-ml und Vowpal Wabbit sind, wie Google, Yahoo und Microsoft dies tun. Input / Output wird zu den dominierenden Kosten für einfache lineare Lernende.

In der Datenfülle verhalten sich nichtparametrische Modelle für die meisten Probleme ungefähr gleich. Die Ausnahmen sind strukturierte Eingaben wie Text, Bilder, Zeitreihen, Audio.

Weitere Lektüre


16

SVM löst ein Optimierungsproblem quadratischer Ordnung.

Ich habe nichts hinzuzufügen, was hier nicht gesagt wurde. Ich möchte nur einen Link auf die Sklearn-Seite über SVC setzen, der verdeutlicht, was los ist:

Die Implementierung basiert auf libsvm. Die Komplexität der Anpassungszeit ist mehr als quadratisch mit der Anzahl der Abtastungen, was es schwierig macht, einen Datensatz mit mehr als ein paar 10000 Abtastungen zu skalieren.

Wenn Sie keinen Kernel verwenden möchten und eine lineare SVM ausreicht, gibt es LinearSVR, die viel schneller ist, da sie einen Optimierungsansatz als lineare Regressionen verwendet. Sie müssen Ihre Daten jedoch normalisieren, falls Sie dies noch nicht getan haben, da dadurch eine Regularisierung des Schnittkoeffizienten angewendet wird, was wahrscheinlich nicht das ist, was Sie möchten. Wenn Ihr Datenmittelwert weit von Null entfernt ist, kann er nicht zufriedenstellend gelöst werden.

Sie können auch den stochastischen Gradientenabstieg verwenden, um das Optimierungsproblem zu lösen. Sklearn verfügt über SGDRegressor . Sie müssen verwenden loss='epsilon_insensitive', um ähnliche Ergebnisse wie bei linearer SVM zu erzielen. Siehe die Dokumentation. Ich würde jedoch nur den Gradientenabstieg als letzten Ausweg verwenden, da dies eine starke Anpassung der Hyperparameter impliziert, um zu vermeiden, dass man in lokalen Minima stecken bleibt. Verwenden LinearSVRSie, wenn Sie können.


Ich hatte einen Datensatz mit vielen Zeilen. SVC hat mir zu lange gedauert, ungefähr 150.000 Datenzeilen. Ich habe Ihren Vorschlag mit LinearSVR verwendet und eine Million Zeilen dauern nur ein paar Minuten. PS fand auch, dass LogisticRegression-Klassifizierer ähnliche Ergebnisse wie LinearSVR (in meinem Fall) liefert und sogar noch schneller ist.
jeffery_the_wind

8

Haben Sie die Skalierung in Ihren Vorverarbeitungsschritt einbezogen? Ich hatte dieses Problem beim Ausführen meiner SVM. Mein Datensatz umfasst ca. 780.000 Stichproben (Zeile) mit 20 Merkmalen (Spalte). Mein Trainingsset umfasst ~ 235.000 Proben. Es stellt sich heraus, dass ich vergessen habe, meine Daten zu skalieren! Wenn dies der Fall ist, versuchen Sie, dieses Bit zu Ihrem Code hinzuzufügen:

skaliere Daten auf [-1,1]; SVM-Geschwindigkeit erhöhen:

aus sklearn.preprocessing importieren MinMaxScaler
skalieren = MinMaxScaler (feature_range = (- 1,1)). anpassen (X_train)
X_train = skalieren.transformieren (X_train)
X_test = skalieren.transformieren (X_test)


2
Kann jemand erklären, warum dies die SVM-Anpassung beschleunigt?
Mittwoch,

1
Gibt es einen Grund, warum Sie sich für MinMaxScaler entschieden haben? StandardScaler zum Beispiel?
Raspi

@Ippier: Im Wesentlichen reduzieren Sie den möglichen Grenzraum für jede Option auf eine Weise, die den Aufwand für Ihre Maschine erheblich verringert.
wie

7

Mit solch einem riesigen Datensatz, denke ich, sind Sie besser dran, wenn Sie ein neuronales Netzwerk, Deep Learning, zufällige Gesamtstrukturen (die überraschend gut sind) usw. verwenden.

Wie in früheren Antworten erwähnt, ist die benötigte Zeit proportional zur dritten Potenz der Anzahl der Trainingsmuster. Sogar die Vorhersagezeit ist in Bezug auf die Anzahl der Testvektoren polynomisch.

Wenn Sie wirklich SVM verwenden müssen, würde ich empfehlen, die GPU zu verwenden, um die Größe des Trainingsdatensatzes zu erhöhen oder zu verringern. Versuchen Sie zunächst anhand eines Beispiels (möglicherweise 10.000 Zeilen) der Daten, festzustellen, ob es sich nicht um ein Problem mit dem Datenformat oder der Datenverteilung handelt.

Wie in anderen Antworten erwähnt, sind lineare Kernel schneller.


3

Ich bin kürzlich auf ein ähnliches Problem gestoßen, weil ich vergessen habe, Features in meinem Datensatz zu skalieren, mit denen früher die Art von Ensemble-Modellen trainiert wurde. Das Versäumnis, die Daten zu skalieren, kann der wahrscheinliche Schuldige sein, auf den Shelby Matlock hingewiesen hat. Sie können verschiedene in sklearn verfügbare Skalierer ausprobieren, z. B. RobustScaler :

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

X ist jetzt transformiert / skaliert und kann Ihrem gewünschten Modell zugeführt werden.


2

Das macht Sinn. IIUC, die Geschwindigkeit der Ausführung von Support-Vektor-Operationen ist an die Anzahl der Abtastwerte gebunden, nicht an die Dimensionalität. Mit anderen Worten, es wird nach CPU-Zeit und nicht nach RAM begrenzt. Ich bin mir nicht sicher, wie lange dies dauern soll, aber ich führe einige Benchmarks durch, um das herauszufinden.


1

Lassen Sie es über Nacht oder besser für 24 Stunden laufen. Wie ist Ihre CPU-Auslastung? Wenn keiner der Kerne zu 100% läuft, liegt ein Problem vor. Wahrscheinlich mit Gedächtnis. Haben Sie überprüft, ob Ihr Datensatz überhaupt in 8 GB passt? Hast du den SGDClassifier ausprobiert? Es ist eines der schnellsten dort. Es lohnt sich, es zu versuchen und zu hoffen, dass es in ungefähr einer Stunde fertig ist.


SGDClassifierunterstützt keine Kernel. Wenn das OP lineare SVM will, dann würde ich zuerst versuchen empfehlen LinearSVR. Es ist viel schneller als, SVRweil es das Problem mit einer linearen Regressionsbibliothek löst und ein globales Minimum garantiert ist (im Gegensatz zu Gradientenabstieg).
Ricardo Cruz

Schätzen Sie Ihren Kommentar. Könnten Sie näher erläutern, warum Kernel-Support ein Problem darstellt?
Diego

Aus der Dokumentation , Das The loss function to be used. Defaults to ‘hinge’, which gives a linear SVM.Gleiche gilt für SGDRegressor. SGDRegressorist gleichbedeutend mit SVR(kernel='linear'). Wenn es das ist, was OP will, ist das großartig. Ich hatte den Eindruck, er wollte SVM mit einem Kernel verwenden. Wenn das nicht der Fall ist, würde ich empfehlen, dass er es zuerst versucht LinearSVR.
Ricardo Cruz

1

Versuchen Sie, die Daten auf [-1,1] zu normalisieren. Ich hatte ein ähnliches Problem und nach der Normalisierung hat alles gut funktioniert. Sie können Daten einfach normalisieren, indem Sie Folgendes verwenden:

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


@Archie Dies ist eine Antwort auf eine Frage, keine Frage.
timleathart

1

Ich bin auf dieses Problem gestoßen und cache_sizewie andere vorschlagen, hilft das überhaupt nicht. Sie können diesen Beitrag und diesen als Hauptbeitrag sehen, der vorgeschlagen hat, den Code manuell zu ändern.

Wie Sie wissen SVCund SVRsind Optimierungsprobleme und sie hören auf, wenn die Fehlerspanne so gering ist, dass die weitere Optimierung zwecklos ist. Darin befindet sich also ein weiterer Parameter, max_itermit dem Sie festlegen können, wie viele Iterationen durchgeführt werden sollen.

Ich habe sklearnin Python und e1071in R verwendet und R ist viel schneller zum Ergebnis zu kommen, ohne das einzustellen max_iterund sklearndauert 2-4 mal länger. Die einzige Möglichkeit, die Rechenzeit für Python zu verkürzen, war die Verwendung von max_iter. Dies hängt von der Komplexität Ihres Modells, der Anzahl der Features, des Kernels und der Hyperparameter ab. Bei einem kleinen Datensatz, den ich für etwa 4000 Datenpunkte verwendet habe, max_iterwaren 10000die Ergebnisse überhaupt nicht unterschiedlich und akzeptabel.


0

Ich hatte gerade ein ähnliches Problem mit einem Datensatz, der nur 115 Elemente und nur ein einziges Merkmal enthält (internationale Flugliniendaten). Die Lösung bestand darin, die Daten zu skalieren. Was ich bisher in den Antworten vermisst habe, war die Verwendung einer Pipeline:

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

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

Sie können modelwie ein gewöhnliches Klassifizierungs- / Regressionsmodell trainieren und auf die gleiche Weise bewerten. Es ändert sich nichts, nur die Definition des Modells.


Was ist Pipeline? Sie importieren es nicht.
Bram Vanroy

0

Sie müssen Ihre Daten skalieren. Durch die Skalierung werden Ihre Datenpunkte auf einen Bereich von -1 bis 1 normalisiert, was zu einer schnelleren Konvergenz beiträgt.

Versuchen Sie es mit folgendem Code:

# X is your numpy data array.

from sklearn import preprocessing

X = preprocessing.scale(X)

Willkommen bei der Data Science SE! Können Sie erklären, wie Ihr Vorschlag dem OP helfen wird? Was Sie vorschlagen, ist eine Skalierung eines Arrays. Es ist nicht klar, wie sich dies auf den SVR-Algorithmus beim Scikit-Lernen auswirken kann oder nicht.
Stereo
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.