Support Vector Machines
Of every line that splits two classes, keep the one farthest from the nearest point on each side. A few border points decide everything, and there is no probability in the answer.
Why Does This Exist?
When two groups separate cleanly, thousands of boundaries get every training point right. Logistic regression draws one and stops once the error hits zero. The boundary you receive can pass a hair from a real point. Correct today, fragile tomorrow. A worn sensor or a shifted scale pushes new points across.
One term first. A hyperplane is the flat dividing surface a linear model draws: a line on a plane, a plane in 3D, the same idea higher up. Most linear models draw one and never ask where it sits. This one does. Of the many separating hyperplanes, take the one farthest from the nearest point on either side. The problem is convex, so there is exactly one answer and two runs agree.
This page covers that widest-street boundary, its margin math, and its loss. Nonlinear separation through feature maps belongs to the kernel trick.
Think of It Like This
Mowing the widest path between two hedges
Two tall hedges face each other and you must mow one straight path between them, the widest that fits, so a walker can pass without getting scratched. Nudge the center line left and the path narrows. Nudge it right and it narrows again. Exactly one line leaves the most room, running down the middle of the tightest gap.
Now notice which branches placed it: two or three tips poking out furthest. Trim a branch deep inside either hedge and nothing moves. Trim one brushing the path edge and the whole path shifts.
Where the picture stops: hedges sit still, data does not. If one poking branch was a fluke, your perfect path is wrong, which is why the soft version below lets a few branches cross the edge for a fee.
How It Actually Works
The margin and its width
Score a point as , where holds the features, holds one weight per feature, and shifts the surface. The boundary is the set where . Label the classes and and demand the right sign with room to spare:
The surfaces where the score equals and are the margin boundaries, dashed in the diagram. The gap between them measures , with the length of the weight vector, so widening the street means shortening . Work it: has length and margin , while has length and margin . Shorter weights, wider street.
This strict form is the hard margin, and it insists on perfect separation. One damaged point inside enemy territory makes every constraint unsatisfiable at once, and the optimizer returns nothing instead of something worse.
Soft margin and the C dial
The repair lets points break the rule and charges per break. Each point gets a slack measuring its shortfall, and the objective becomes . Read as the price of a violation, because everyone gets its direction backwards at first.
Large makes violations expensive, so the boundary contorts to satisfy nearly every point and the street narrows. Small makes violations cheap, so the optimizer buys a wide street and misclassifies some training points on purpose. Turning up regularizes less, the opposite of most dials.
Hinge loss and worked numbers
The per-point charge has a name. For score and label :
Read it as a rule about when the model stops caring. Score a point right and clear of the margin and the loss is exactly zero, not small. Inside the margin or on the wrong side, the cost climbs in a straight line. Three cases: gives ; gives ; gives .
That cutoff is the defining property. Points safely beyond the margin contribute nothing, so the answer rests on the handful inside or touching it: the support vectors, three in the diagram. Delete every other point and refit for an identical boundary. Compact, and only as trustworthy as those few rows. Note the output throughout is a signed distance to a surface, never a probability.
Code
Margin widths and hinge charges for the worked numbers, so you can check the direction of reasoning yourself.
import math
def margin_width(w): return 2.0 / math.sqrt(w[0] ** 2 + w[1] ** 2)
print(margin_width((1.0, 0.0))) # -> 2.0print(margin_width((2.0, 0.0))) # -> 1.0
def hinge(y, f): return max(0.0, 1 - y * f)
print(hinge(1, 0.5)) # -> 0.5print(hinge(1, 2.0)) # -> 0.0print(hinge(-1, 0.5)) # -> 1.5Longer weights mean a narrower street, and only points short of the margin pay anything.
Watch Out For
Turning C the wrong way when the model overfits
Symptom: the boundary hugs the data, validation slips, and someone reasons that is a regularization strength, raises it from 1 to 100, and watches validation slip further.
Fix: memorize the price reading instead. Fit at two values and compare margin width or support-vector count. Narrower street and fewer support vectors mean less regularization, every time. Log both numbers in the sweep so direction never relies on memory.
Reading the decision score as a probability
Symptom: scores get pushed through a squashing function, the rankings look right, accuracy looks healthy, and any decision that multiplies the number by a cost runs on fiction. Change and every pseudo probability moves, because the input was a distance in units of .
Fix: fit the mapping on held-out data instead of inventing it. Keep the raw distance for ranking and learn the probability map from a separate split before any cost math touches it.
The Quick Version
- Of all separating hyperplanes, this keeps the one farthest from the closest point on each side, and convexity gives a single answer.
- The street width is , so maximizing it means minimizing the weight vector length.
- Hard margin needs perfect separation. One outlier makes it infeasible, so the soft form buys violations at price .
- Large means pricey violations and a narrow street. Small means a wide street that tolerates errors.
- Hinge loss is exactly zero past the margin, so only nearby points shape the boundary. Those are the support vectors.
- The output is a signed distance, not a probability. Calibrate before multiplying by costs.