|
Wenn Ihr SVM-Modell overfittet, können Sie es durch Senken des C-Werts regularisieren. |
Das folgende Codebeispiel mit Scikit-Learn lädt den Iris-Datensatz, skaliert die Merkmale und trainiert anschließend ein lineares SVM-Modell (mithilfe der Klasse LinearSVC und C=1 sowie der in Kürze erklärten Funktion Hinge Loss), um Blumen der Art Iris virginica zu erkennen:
import numpy as np
from sklearn import datasets
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.svm import LinearSVC
iris = datasets.load_iris()
X = iris["data"][:, (2, 3)] # Länge, Breite der Kronblätter
y = (iris["target"] == 2).astype(np.float64) # Iris virginica
svm_clf = Pipeline([
("scaler", StandardScaler()),
("linear_svc", LinearSVC(C=1, loss="hinge")),
])
svm_clf.fit(X, y)
Das dabei erhaltene Modell sehen Sie auf der linken Seite von Abbildung 5-4.
Anschließend können Sie mit dem Modell wie bisher Vorhersagen vornehmen:
>>> svm_clf.predict([[5.5, 1.7]])
array([1.])
|
Im Gegensatz zu Klassifikatoren, die mit der logistischen Regression arbeiten, geben SVM-Klassifikatoren keine Wahrscheinlichkeiten für die einzelnen Kategorien aus. |
Statt der Klasse LinearSVC könnten Sie auch die Klasse SVC mit einem linearen Kernel verwenden. Beim Erstellen des SVC-Modells würden wir SVC(kernel="linear", C=1) schreiben. Eine weitere Möglichkeit bietet die Klasse SGDClassifier mit SGD Classifier(loss="hinge", alpha=1/(m*C)). Diese verwendet das stochastische Gradientenverfahren (siehe Kapitel 4), um einen linearen SVM-Klassifikator zu trainieren. Sie konvergiert nicht so schnell wie die Klasse LinearSVC, ist dafür aber beim Verarbeiten riesiger Datenmengen, die sich nicht im Speicher unterbringen lassen (Out-of-Core-Training), sowie bei Online-Klassifikationsaufgaben nützlich.
|
Die Klasse LinearSVC regularisiert den Bias-Term, daher sollten Sie den Trainingsdatensatz durch Subtrahieren des Mittelwerts zunächst zentrieren. Dies geschieht automatisch, wenn Sie die Daten mit dem StandardScaler skalieren. Außerdem sollten Sie dafür sorgen, dass der Hyperparameter loss auf "hinge" gesetzt ist, da dies nicht der Standardeinstellung entspricht. Um schließlich eine kürzere Rechenzeit zu erreichen, sollten Sie den Hyperparameter dual auf False setzen, es sei denn, es gibt mehr Merkmale als Trainingsdatenpunkte (wir werden uns in diesem Kapitel noch mit Dualität beschäftigen). |
Nichtlineare SVM-Klassifikation
Auch wenn lineare SVM-Klassifikatoren sehr effizient sind und in vielen Fällen überraschend gut funktionieren, sind viele Datensätze nicht einmal annähernd linear separierbar. Eine Möglichkeit zum Umgang mit nichtlinearen Datensätzen ist das Hinzufügen zusätzlicher Merkmale, wie etwa polynomielle Merkmale (wie in Kapitel 4); in manchen Fällen erhalten Sie dabei einen linear separierbaren Datensatz. Betrachten Sie das Diagramm auf der linken Seite von Abbildung 5-5: Es stellt einen einfachen Datensatz mit einem einzigen Merkmal x1 dar. Dieser Datensatz ist, wie Sie sehen, nichtlinear separierbar. Wenn Sie aber ein zweites Merkmal x2 = (x1)2 hinzufügen, ist der sich dabei ergebende zweidimensionale Datensatz ausgezeichnet linear separierbar.
Abbildung 5-5: Hinzufügen von Merkmalen, um einen linear separierbaren Datensatz zu erhalten
Dieser Ansatz lässt sich mit Scikit-Learn umsetzen, indem Sie eine Pipeline erstellen, die aus einem PolynomialFeatures-Transformer (wie in »Polynomielle Regression« besprochen) und anschließend einem StandardScaler sowie einem LinearSVC besteht. Probieren wir dies anhand des Datensatzes moons aus. Dabei handelt es sich um einen Spieldatensatz, bei dem die Datenpunkte als zwei ineinander verschränkte Halbkreise geformt sind (siehe Abbildung 5-6). Sie können diesen Datensatz mit der funktion make_moons() erzeugen:
from sklearn.datasets import make_moons
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import PolynomialFeatures
X, y = make_moons(n_samples=100, noise=0.15)
polynomial_svm_clf = Pipeline([
("poly_features", PolynomialFeatures(degree=3)),
("scaler", StandardScaler()),
("svm_clf", LinearSVC(C=10, loss="hinge"))
])
polynomial_svm_clf.fit(X, y)
Abbildung 5-6: Linearer SVM-Klassifikator mit polynomiellen Merkmalen
Polynomieller Kernel
Das Hinzufügen polynomieller Merkmale lässt sich einfach umsetzen und funktioniert bei vielen Machine-Learning-Algorithmen sehr gut (nicht nur bei SVMs). Allerdings können Polynome niedrigen Grades nicht gut mit komplexen Datensätzen umgehen, höhergradige Polynome dagegen erzeugen eine riesige Anzahl Merkmale, wodurch das Modell zu langsam wird.
Glücklicherweise können wir bei SVMs eine beinahe magische mathematische Technik einsetzen, den Kerneltrick (ihn stellen wir gleich vor). Dieser ermöglicht es, das gleiche Ergebnis wie beim Hinzufügen vieler polynomieller Merkmale zu erhalten, ohne diese explizit hinzuzufügen – das funktioniert auch für Polynome sehr hohen Grades. Dadurch umgehen wir die kombinatorische Explosion der Merkmalsanzahl, da wir überhaupt keine Merkmale hinzufügen müssen. Die Klasse SVC verwendet diesen Trick. Probieren wir ihn auf dem Datensatz moons aus:
from sklearn.svm import SVC
poly_kernel_svm_clf = Pipeline([
("scaler", StandardScaler()),
("svm_clf", SVC(kernel="poly", degree=3, coef0=1, C=5))
])
poly_kernel_svm_clf.fit(X, y)
Dieser Code trainiert einen SVM-Klassifikator mit einem polynomiellen Kernel 3. Grades. Sie sehen ihn auf der linken Seite von Abbildung