Μηχανές Διανυσμάτων Υποστήριξης (SVM)

2.2.5

Μηχανές Διανυσμάτων Υποστήριξης (SVM)

Ενημέρωση 2020-03-25 Ανάγνωση 3 λεπτά
Σύνοψη
  • Οι SVM μαθαίνουν ένα όριο απόφασης που μεγιστοποιεί το περιθώριο μεταξύ κλάσεων, δίνοντας έμφαση στη γενίκευση.
  • Τα μαλακά περιθώρια εισάγουν μεταβλητές χαλάρωσης ώστε να επιτρέπονται κάποιες λανθασμένες ταξινομήσεις, ενώ η ποινή \(C\) εξισορροπεί το πλάτος του περιθωρίου και τα σφάλματα.
  • Τα τεχνάσματα πυρήνα αντικαθιστούν τα εσωτερικά γινόμενα με συναρτήσεις πυρήνα, επιτρέποντας μη γραμμικά όρια απόφασης χωρίς ρητή επέκταση χαρακτηριστικών.
  • Η τυποποίηση χαρακτηριστικών και η ρύθμιση υπερπαραμέτρων (π.χ. \(C\), \(\gamma\)) είναι κρίσιμες για καλή απόδοση.

Εισαγωγή #

Αυτή η μέθοδος πρέπει να ερμηνεύεται μέσα από τις υποθέσεις της, τις συνθήκες δεδομένων και τον τρόπο με τον οποίο οι επιλογές παραμέτρων επηρεάζουν τη γενίκευση.

Αναλυτική Επεξήγηση #

Μαθηματική Διατύπωση #

Για γραμμικά διαχωρίσιμα δεδομένα λύνουμε

$$ \min_{\mathbf{w}, b} \ \frac{1}{2} \lVert \mathbf{w} \rVert_2^2 \quad \text{s.t.} \quad y_i(\mathbf{w}^\top \mathbf{x}_i + b) \ge 1. $$

Στην πράξη χρησιμοποιούμε την παραλλαγή μαλακού περιθωρίου με μεταβλητές χαλάρωσης \(\xi_i \ge 0\):

$$ \min_{\mathbf{w}, b, \boldsymbol{\xi}} \ \frac{1}{2} \lVert \mathbf{w} \rVert_2^2 + C \sum_{i=1}^{n} \xi_i \quad \text{s.t.} \quad y_i(\mathbf{w}^\top \mathbf{x}_i + b) \ge 1 - \xi_i. $$

Η αντικατάσταση των εσωτερικών γινομένων \(\mathbf{x}_i^\top \mathbf{x}_j\) με πυρήνες \(K(\mathbf{x}_i, \mathbf{x}_j)\) δίνει μη γραμμικά όρια απόφασης.

Πειράματα σε Python #

Ο παρακάτω κώδικας προσαρμόζει SVM με γραμμικό πυρήνα και με πυρήνα RBF σε ένα μη γραμμικά διαχωρίσιμο σύνολο δεδομένων που δημιουργήθηκε με make_moons. Ο πυρήνας RBF αποτυπώνει πολύ καλύτερα το καμπύλο όριο.

from __future__ import annotations

import japanize_matplotlib
import matplotlib.pyplot as plt
import numpy as np
from sklearn.datasets import make_moons
from sklearn.metrics import accuracy_score
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC

def run_svm_demo(
    n_samples: int = 400,
    noise: float = 0.25,
    random_state: int = 42,
    title: str = "Decision boundary of RBF-SVM",
    xlabel: str = "feature 1",
    ylabel: str = "feature 2",
) -> dict[str, float]:
    """Train linear and RBF SVMs and plot the RBF decision boundary."""
    japanize_matplotlib.japanize()
    X, y = make_moons(n_samples=n_samples, noise=noise, random_state=random_state)

    linear_clf = make_pipeline(StandardScaler(), SVC(kernel="linear", C=1.0))
    linear_clf.fit(X, y)

    rbf_clf = make_pipeline(StandardScaler(), SVC(kernel="rbf", C=5.0, gamma=0.5))
    rbf_clf.fit(X, y)

    linear_acc = float(accuracy_score(y, linear_clf.predict(X)))
    rbf_acc = float(accuracy_score(y, rbf_clf.predict(X)))

    grid_x, grid_y = np.meshgrid(
        np.linspace(X[:, 0].min() - 0.5, X[:, 0].max() + 0.5, 400),
        np.linspace(X[:, 1].min() - 0.5, X[:, 1].max() + 0.5, 400),
    )
    grid = np.c_[grid_x.ravel(), grid_y.ravel()]
    rbf_scores = rbf_clf.predict(grid).reshape(grid_x.shape)

    fig, ax = plt.subplots(figsize=(6, 5))
    ax.contourf(grid_x, grid_y, rbf_scores, alpha=0.2, cmap="coolwarm")
    ax.scatter(X[:, 0], X[:, 1], c=y, cmap="coolwarm", edgecolor="k", s=30)
    ax.set_title(title)
    ax.set_xlabel(xlabel)
    ax.set_ylabel(ylabel)
    fig.tight_layout()
    plt.show()

    return {"linear_accuracy": linear_acc, "rbf_accuracy": rbf_acc}

metrics = run_svm_demo(
    title="Decision boundary of RBF-SVM",
    xlabel="feature 1",
    ylabel="feature 2",
)
print(f"Linear kernel accuracy: {metrics['linear_accuracy']:.3f}")
print(f"RBF kernel accuracy: {metrics['rbf_accuracy']:.3f}")

Ο πυρήνας RBF αποτυπώνει πολύ καλύτερα το καμπύλο όριο σχήμα

Αναφορές #

  • Vapnik, V. (1998). Statistical Learning Theory. Wiley.
  • Smola, A. J., & Schölkopf, B. (2004). A Tutorial on Support Vector Regression. Statistics and Computing, 14(3), 199–222.