← All tutorials

On this page

1 The maximum-margin classifier 2 The hinge loss and C 3 The margin and the hinge in four steps 4 How C sets the margin width 5 Kernels and SVM variants 6 SVMs in practice 7 References

Support Vector Machines (SVM)

Support vector machines find the boundary with the most room on both sides.

Many separating lineswhich one generalizes best?Maximum marginmargin width = 2/‖w‖Hinge and Ctrade margin width against violationsKernelssimilarity in a lifted feature spaceVariantsregression and anomaliesIn practicepipeline, tuning, settings, cost112556
Figure 1. Each box's marker is the number of the section that teaches it.

The linear SVM (Section 2) trains by gradient steps, one per batch of 32 points, about 141 per pass over the data, for 1,000 passes in the svm-pytorch notebook; the kernel SVC (Section 5) is fit once by a dedicated solver instead.

1 The maximum-margin classifier

An SVM picks, among the boundaries that separate the classes, the one farthest from the closest points. Two boundaries can both get every training point right; which do you trust on new data? The one with room to spare.

That boundary has the maximum margin, the most room on both sides before it touches a point, so a new point near the edge still lands on the right side.

support vector the margin margin boundary decision line 123
Figure 2. Only the three points the margin touches, 123, decide where it sits.

Those three points are the support vectors: moving any other point leaves the boundary in place.

The decision line is where the score w·x + b is zero, and the margin lines are where it hits +1 and −1:

The margin's width depends only on the length of the weights.
margin width = 2‖w‖
‖w‖ is the length of the weight vector w. Bigger weights make the score change faster, so the ±1 lines come sooner and the margin narrows; halve the weights and the margin doubles. Widening the margin is exactly shrinking the weights.

With no violations allowed, the widest margin is this problem:

The widest separator shrinks the weights and keeps every point on its own side.
min ½‖w‖2
min makes what follows as small as it can go: half the squared length of the weights. A smaller w means a wider margin, since the width is 2/‖w‖.
s.t. yi(w·xi + b) ≥ 1
The constraint after s.t., read "such that", requires every point's label yi (+1 or −1) times its score to reach at least 1, so each point sits on its own side, at least one unit past the line. xi is point i's features, the · is the dot product (multiply matching features, add them up), and b is the offset. The points that land exactly on 1 are the support vectors.

2 The hinge loss and C

Real data overlaps, so training allows violations and adds a cost for each. The SVM is a linear model trained with the hinge loss, which asks whether the model is right with room to spare. The label times the score is positive on the correct side, and past 1 the loss is zero.

wrong sideborderlineroom to spare01label × scorelosszero loss1
Figure 3. Wrong side and borderline points pay; past 1 1 the loss is zero.

The soft margin (Cortes and Vapnik, 1995) swaps the hard rule for that cost on each violation:

The hinge loss, and the objective that trades it against margin width.
fi = w·xi + b
Point i's raw score fi is the dot product of w and xi plus the offset b.
hingei = max(0, 1 − yi·fi)
The shortfall 1 − yi·fi, floored at zero by max: zero once a point is safely past its margin line, and growing the deeper it sits inside the margin or past the line.
J = ½‖w‖2 + C·mean(hinge)
J adds the margin cost to C times the average hinge, the cost for every point that is wrong or too close. The two parts pull against each other: the first wants small weights and a wide margin, the second wants no point inside it. Raise C and violations cost more than width, so the margin narrows; lower it and the model widens the margin and tolerates violations. Near C = 0 only width counts and every point sits inside the margin; a huge C approaches the hard margin above. scikit-learn's SVC puts its C on the summed hinge, so its default 1.0 equals C = n here, with n the number of points (Section 6).

C is not a learning rate: a large C puts little weight on keeping w small (weak regularization), a small C much weight. Swap the hinge for the log loss and this is logistic regression.

The svm-pytorch notebook in Machine-Learning-Concepts trains with PyTorch's SGD: one step per batch of 32 points, 1,000 passes over 4,500 training points (about 141,000 steps), learning rate 0.001. It writes the cost as the mean hinge plus 1e-4 times the squared weights, which is J divided by C with C = 5,000. The hinge has a kink, so the step uses the subgradient: a point short of the margin nudges the weights toward its label, and every other point is left alone.

The notebook's training loop in PyTorch, with X the points and labels y of −1 or +1.

import torch
lr, lam = 0.001, 1e-4
epochs, batch = 1000, 32
w = torch.zeros(2)
b = torch.zeros(1)
w.requires_grad_()
b.requires_grad_()
SGD = torch.optim.SGD
opt = SGD([w, b], lr=lr)
for epoch in range(epochs):
    order = torch.randperm(len(X))
    for idx in order.split(batch):
        f = X[idx] @ w + b
        gap = 1 - y[idx] * f
        hinge = gap.clamp(min=0)
        fit = hinge.mean()
        l2 = w.dot(w) + b.dot(b)
        loss = fit + lam * l2
        opt.zero_grad()
        loss.backward()
        opt.step()
  1. 1Starts w and b at 0 and sets up SGD at the notebook's learning rate.
  2. 2Shuffles each pass and walks it in batches of 32, about 141 steps per pass.
  3. 3Scores f and hinge losses, lines 1 and 2 of the card in Section 2.
  4. 4Mean hinge plus λ times the squared weights, which is line 3 divided by C with λ = 1/(2C); the notebook also penalizes b.
  5. 5One subgradient step per batch.

3 The margin and the hinge in four steps

The widest separator, and what a point inside the margin costs.
min ½‖w‖2
Shrinking the weights widens the margin, whose width is 2/‖w‖.
s.t. yi(w·xi + b) ≥ 1
Every point on its own side, at least one unit past the line. The closest points sit exactly at 1: the support vectors.
hingei = max(0, 1 − yi·fi)
A point short of its margin line pays the shortfall; here y·f = 0.4, so the hinge is 0.6.
w the weights; smaller weights give a wider marginyi point i's label (+1 or −1)xi its featuresb the offsethingei point i's shortfall; fi its score

Figure 4. Four steps on a toy set: only the points the margin touches set the boundary.

4 How C sets the margin width

The same J, trained on 400 points in two overlapping clouds.

1

Figure 5. The margin and the support vectors for one value of C.

class +1 class −1 decision line margin lines support vector misclassified
036margin width5.870.560200400pointssupport vectors40046misclassified, 15 to 190.321101001000C (log scale)123
Figure 6. Raising C shrinks the margin 1 and the support vectors 2; mistakes 3 stay near 16.

5 Kernels and SVM variants

A kernel lets the same margin bend around curved data, and two variants reuse it for regression and anomalies.

5.1 The kernel trick

A lift adds a feature computed from the old ones, here the squared distance from the center.

flatliftedno straight cut worksa flat cut workslifted height = squared distance from center1123
Figure 7. Lifting puts the inner ring 1 low and the outer ring 2 high; one flat cut 3 splits them.

In practice no one computes the lift: a kernel scores each pair of points as if they had been lifted.

A kernel scores how similar two points are, standing in for the lift.
K(x, z) = φ(x)·φ(z)
φ (phi) is the lift, and K(x, z) is the dot product of two points x and z after it. The kernel computes that number straight from the original points, so the flat cut in the lifted space never needs the lifted coordinates.
The RBF kernel, and the polynomial kernel beside it.
K(x, z) = exp(−γ ‖x − z‖2)
K is a similarity score for a pair of points, x and z: e raised to minus γ times the squared distance between the pair, so nearby pairs score near 1 and far pairs fade toward 0. γ (gamma) sets how far each point's influence reaches: raise it and influence shrinks until the boundary bends around each single point; lower it and the boundary smooths toward a straight cut. scikit-learn's default, gamma = "scale", is 1 / (number of features × variance of the data).
K(x, z) = (γ x · z + c)d
The polynomial kernel scales the dot product by γ, adds a constant c and raises the sum to the power d. With c above 0 it counts every product of up to d features, so d = 2 can draw ellipses and parabolas; at c = 0 only products of exactly d features remain. A higher d bends more and overfits sooner; scikit-learn defaults to d = 3 (degree), c = 0 (coef0) and γ = "scale".

RBF (radial basis function) scores similarity to nearby points, like distance in k-nearest neighbors. The trained w is a weighted sum of the support vectors, so the score w·x is a sum of dot products, and the kernel replaces each one.

The weights are a sum over support vectors, so the score becomes a kernel sum.
w = Σi αi yi xi
The solver finds one weight αi (alpha) per training point, at most C. It is zero for every point safely past its margin, so only the support vectors add to w.
f(x) = Σi αi yi K(xi, x) + b
Each dot product xi·x becomes the kernel. Each support vector xi pushes toward its own class yi (+1 or −1) with weight αi, and the kernel K fades that push with distance at the rate gamma sets. The new point x takes the side whose pushes add up stronger; the boundary is where f(x) = 0 and the pushes exactly cancel.
1

Figure 8. Low gamma underfits, near 1 draws one ring, high gamma bends around each point.

class +1 class −1 called "inner" by the boundary

5.2 Choosing a kernel

RBF is the default for low-dimensional curved data like the rings. The polynomial kernel bends the boundary into smooth curves, not RBF's tight local curves. When features outnumber points, as in text, linear usually wins: a straight cut in a huge space is already flexible.

Linearstraight cutPolynomialsmooth ovalRBFlocal curves123
Figure 9. The kernel sets the boundary's shape: a straight cut 1, a smooth oval 2, or local curves 3.

5.3 SVR and one-class SVM

Support vector regression draws a tube around the predictions and only adds a cost for points outside it. The one-class SVM draws the boundary around normal examples only, and anything outside is an anomaly.

In scikit-learn, SVR's tube half-width epsilon (default 0.1) sets how big a miss is free: wider ignores more, 0 counts every miss. OneClassSVM's nu (default 0.5) caps the share of training points it may call anomalies; it marks new points +1 or −1.

from sklearn.svm import SVC, SVR, OneClassSVM
clf = SVC(kernel="linear", C=1.0)
clf.fit(X, y)
reg = SVR(epsilon=0.1)  # rbf
reg.fit(X, y_reg)
det = OneClassSVM(nu=0.05)  # rbf
det.fit(X_normal)
flags = det.predict(X_new)  # ±1
  1. 1Classifier with a straight boundary.
  2. 2Regression that ignores errors under ε.
  3. 3Novelty detector trained on normal points only.

6 SVMs in practice

The standard recipe in scikit-learn.

from sklearn.datasets import make_moons
from sklearn.model_selection import train_test_split
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC

X, y = make_moons(1000, noise=0.2)
parts = train_test_split(X, y)
Xtr, Xte, ytr, yte = parts
svc = SVC(C=1.0, gamma="scale")
sc = StandardScaler()
model = make_pipeline(sc, svc)
model.fit(Xtr, ytr)
acc = model.score(Xte, yte)
n_sv = model[-1].n_support_
  1. 1Two noisy half-moons with a test split.
  2. 2Scaling, then an RBF SVM.
  3. 3Fits, scores and counts support vectors.
SettingWhere it entersRaise itLower itDefault
CPrice of the hinge term in JNarrow, strict marginWide, forgiving margin1.0 in SVC, on the summed hinge (n in J)
kernelThe similarity K in the decision sumLinear, polynomial or RBF decides the boundary's shape"rbf"
γ (gamma)Scales the squared distance in RBFBoundary bends around single pointsSmooth, nearly straight"scale", which is 1 / (features × variance)
n_components (Nystroem)Landmarks used to approximate KCloser to the exact kernel, more time and memoryFaster, coarser boundary100

SVC, built on libsvm, caches kernel values in 200 MB. Its kernel matrix holds K for every pair of points, so its documentation says fit time grows at least with the square of the samples and suggests LinearSVC or SGDClassifier past tens of thousands, possibly after Nystroem. Scale inside the pipeline, since unscaled features break the RBF distance. SVC handles many classes one pair at a time, and scikit-learn 1.9 deprecates probability=True in favor of CalibratedClassifierCV.

scikit-learn's C multiplies the summed hinge, while the J card's C multiplies the mean, so scikit-learn's C equals the page's C divided by n, and its default 1.0 is the page's C = n.

Tuning C and γ together by 5-fold cross-validation (train on four folds, test on the fifth).

import numpy as np
from sklearn.model_selection import GridSearchCV
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC
sc = StandardScaler()
svc = SVC(kernel="rbf")
model = make_pipeline(sc, svc)
Cs = np.logspace(-2, 3, 6)
gammas = np.logspace(-2, 2, 5)
grid = {}
grid["svc__C"] = Cs
grid["svc__gamma"] = gammas
gs = GridSearchCV(model, grid)
gs.fit(X, y)  # 5 folds by default
best = gs.best_params_
  1. 1Scales, then an RBF SVM.
  2. 2Candidate C and γ values, log spaced.
  3. 3Cross-validates every pair and keeps the best.

Nystroem builds features whose dot products approximate the RBF kernel; RBFSampler is the random alternative.

from sklearn.kernel_approximation import Nystroem
from sklearn.pipeline import make_pipeline
from sklearn.svm import LinearSVC
ny = Nystroem(n_components=300)
lin = LinearSVC(C=1.0)
clf = make_pipeline(ny, lin)
clf.fit(X, y)
  1. 1Approximates the RBF lift with 300 features, then a linear SVM.
  2. 2Fits in time linear in the number of points.

7 References

  1. Cortes, C., et al. (1995). Support-vector networks. Machine Learning.
  2. Boser, B. E., et al. (1992). A training algorithm for optimal margin classifiers. COLT.
  3. Platt, J. C. (1999). Fast training of support vector machines using sequential minimal optimization. In Advances in Kernel Methods.