iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

SVM

Support Vector Machine finds the hyperplane that maximally separates classes. With the kernel trick (RBF, poly), SVMs handle non-linear boundaries — strong baselines on small/medium datasets.

Classifier + regressor + scaling

EXAMPLE
import numpy as np
from sklearn.datasets import load_wine, fetch_california_housing
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
from sklearn.svm import SVC, SVR, LinearSVC
from sklearn.metrics import classification_report, mean_absolute_error

# === Classification ===
data = load_wine()
X_train, X_test, y_train, y_test = train_test_split(
    data.data, data.target, test_size=0.2, stratify=data.target, random_state=42
)

# 1) ALWAYS scale before SVM — distances dominate
pipe = Pipeline([
    ('scaler', StandardScaler()),
    ('svm',    SVC(kernel='rbf', C=1.0, gamma='scale', probability=True, random_state=42)),
])
pipe.fit(X_train, y_train)
print(classification_report(y_test, pipe.predict(X_test), target_names=data.target_names))

# 2) Common kernels
# - linear  : fast, high-dim sparse data (text), interpretable
# - rbf     : default — smooth non-linear boundaries
# - poly    : polynomial features without explicit expansion
# - sigmoid : neural-net-like; rarely best

# 3) Hyperparameters
# C       : regularisation strength (1/lambda). Higher = fit train more.
# gamma   : RBF kernel width. Lower = smoother. 'scale' = 1/(n_features * X.var())
# degree  : for poly kernel
# class_weight : 'balanced' for imbalanced targets

param_grid = {
    'svm__C':     [0.1, 1, 10, 100],
    'svm__gamma': ['scale', 'auto', 0.01, 0.1, 1],
    'svm__kernel':['rbf', 'poly'],
}
grid = GridSearchCV(pipe, param_grid, cv=5, n_jobs=-1, scoring='f1_macro')
grid.fit(X_train, y_train)
print(grid.best_params_, grid.best_score_)

# 4) LinearSVC — faster, scales to MANY samples + features
linear = Pipeline([
    ('scaler', StandardScaler()),
    ('svm',    LinearSVC(C=1.0, max_iter=10_000, dual=False, random_state=42)),
])
linear.fit(X_train, y_train)
# Use LinearSVC instead of SVC(kernel='linear') for n > 10_000 samples — much faster.

# 5) Decision function + probability
probs = pipe.predict_proba(X_test)[:, 1]
scores = pipe.decision_function(X_test)        # raw margin (signed distance)

# 6) Regression — SVR
hx, hy = fetch_california_housing(return_X_y=True)
rx_tr, rx_te, ry_tr, ry_te = train_test_split(hx, hy, test_size=0.2, random_state=42)
reg = Pipeline([
    ('scaler', StandardScaler()),
    ('svr',    SVR(kernel='rbf', C=10, gamma='scale', epsilon=0.1)),
]).fit(rx_tr, ry_tr)
print('MAE:', mean_absolute_error(ry_te, reg.predict(rx_te)))

# 7) Imbalanced classification — class_weight
SVC(kernel='rbf', class_weight='balanced')
# Or pass {0: 1, 1: 10} to manually weight

# 8) Out-of-the-box pitfalls
# - Scaling: forgetting it = your SVM trains on whichever feature has the biggest variance
# - C too high: overfits training data; check with CV
# - gamma too high: every point becomes its own region (overfit)
# - SVC scales poorly past ~100k samples — use LinearSVC or SGDClassifier(loss='hinge')

# 9) When SVMs are the right pick
# - Small-to-medium tabular data (1k-100k rows)
# - High-dimensional sparse data (text, after TF-IDF) → LinearSVC
# - You need a strong non-linear baseline without tuning a neural network
# Otherwise reach for gradient boosting (LightGBM, XGBoost, HistGBDT)

# 10) Inspect the model
clf = grid.best_estimator_.named_steps['svm']
print('support vectors:', clf.n_support_)
print('support indices:', clf.support_[:10])
# Only support vectors define the boundary; the rest don't matter.

Why it matters

SVMs without feature scaling don’t work. Standardise first, then tune C and gamma via grid search — that’s 90% of the recipe.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
from sklearn.svm import SVC
clf = SVC(kernel='rbf', C=1.0, gamma='scale').fit(Xtr, ytr)
Try it Yourself »

Discussion

Loading…