The Dual Support Vector Machine
Everything so far has been written in terms of , which lives in . That is the primal SVM, and its size grows with the number of features. Section 12.3 rewrites the same problem in terms of one multiplier per example — and in doing so produces the form that Section 12.4 can kernelise.
The Lagrangian and its three derivatives
Section titled “The Lagrangian and its three derivatives”Attach to the margin constraint 12.26b and to the non-negativity constraint 12.26c:
Differentiating in the three primal variables:
Setting the first to zero gives the result the rest of the chapter rests on:
the representer theorem — the optimal weight vector is a linear combination of the training examples. Setting the second to zero adds , which makes it an affine combination. Setting the third to zero and using gives .
Substituting back eliminates , and entirely (Equations 12.39, 12.40) and leaves
The examples appear only through . That is the whole point of the exercise, and page 1208 collects the winnings.
The running example, exactly
Section titled “The running example, exactly”The eight-point dataset has a dual solution that can be written down by hand. With and support vectors , and , Equation 12.38 and the constraint give and .
import numpy as np
from scipy.optimize import minimize
X = np.array([[3.0, 1.0], [3.0, -1.0], [6.0, 1.0], [6.0, -1.0],
[1.0, 0.0], [0.0, 1.0], [0.0, -1.0], [-1.0, 0.0]])
Y = np.array([ 1.0, 1.0, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0])
BIG = 1e6 # stands in for the hard margin
def dual(XX, YY, C, tries=25):
H = (YY[:, None] * YY[None, :]) * (XX @ XX.T) # Y K Y
out, bv = None, np.inf
for s in range(tries):
rg = np.random.default_rng(s)
a0 = np.clip(np.abs(rg.normal(0.3, 0.3, len(XX))), 0, C)
r = minimize(lambda a: 0.5 * a @ H @ a - a.sum(), a0,
jac=lambda a: H @ a - 1.0,
bounds=[(0.0, C)] * len(XX),
constraints=[{"type": "eq", "fun": lambda a: YY @ a,
"jac": lambda a: YY}],
method="SLSQP", options={"maxiter": 30000, "ftol": 1e-14})
if r.success and r.fun < bv - 1e-13:
bv, out = r.fun, np.clip(r.x, 0.0, C)
return out
a = dual(X, Y, BIG)
w = a * Y @ X # Equation 12.38
print(f"alpha : {np.round(a, 8)}")
print(f"w = sum a y x : {np.round(w, 8)}")
print(f"sum y_n alpha_n : {Y @ a:.3e}")
print(f"support vectors : {list(np.where(a > 1e-9)[0])}")alpha : [0.25 0.25 0. 0. 0.5 0. 0. 0. ]
w = sum a y x : [1. 0.]
sum y_n alpha_n : -5.306e-16
support vectors : [0, 1, 4]The largest deviation from the exact is , and recovers the primal answer to .
Sparsity is the point
Section titled “Sparsity is the point”The book’s remark is short: “The examples , for which the corresponding parameters , do not contribute to the solution at all. The other examples, where , are called support vectors.”
Measured from both directions:
sv = a > 1e-9
a2 = dual(X[sv], Y[sv], BIG) # keep ONLY the support vectors
print(f"refit on {int(sv.sum())} points : alpha = {np.round(a2, 8)}")
print(f" w = {np.round(a2 * Y[sv] @ X[sv], 8)}, gap "
f"{np.linalg.norm(a2 * Y[sv] @ X[sv] - w):.3e}")
rg = np.random.default_rng(7) # now ADD 500 easy examples
XL = np.vstack([X, rg.uniform([20, -5], [40, 5], (250, 2)),
rg.uniform([-40, -5], [-20, 5], (250, 2))])
YL = np.r_[Y, np.ones(250), -np.ones(250)]
aL = dual(XL, YL, BIG, tries=6)
print(f"N = {len(XL)} : support vectors {int((aL > 1e-9).sum())}, "
f"w gap {np.linalg.norm(aL * YL @ XL - w):.3e}")
print(f" alpha mass on the 500 extras : {aL[8:].sum():.3e}")refit on 3 points : alpha = [0.25 0.25 0.5 ]
w = [ 1. -0.], gap 1.950e-08
N = 508 : support vectors 3, w gap 6.238e-09
alpha mass on the 500 extras : 8.289e-12Five of eight examples can be deleted without changing the answer, and five hundred more can be added without changing it either. The five hundred extras collectively carry of dual mass. This is the same property page 1205 measured from the primal side: a point beyond its margin has zero hinge loss, and here it has zero multiplier.
Recovering b, and a wrinkle in the remark
Section titled “Recovering b, and a wrinkle in the remark”The dual returns , and Equation 12.38 returns — but was eliminated. For an example on the margin, , so
from example 0 : b = -1.999999981275
from example 1 : b = -1.999999949778
from example 4 : b = -1.999999988509
the primal's b*: -2.0The book adds: “In principle, there may be no examples that lie exactly on the margin. In this case, we should compute for all support vectors and take the median value to be the value of .”
That rule as written discards the sign. Taking the median of an absolute value returns a non-negative number, and here is :
| from Equation 12.42 | the median-of-absolute rule | |
|---|---|---|
The magnitudes agree to or better, so the intent is clear and the fix is to drop the absolute value — take the median of itself.
The margin note is a one-way implication
Section titled “The margin note is a one-way implication”The book’s side note reads:
It turns out that examples that lie exactly on the margin are examples whose dual parameters lie strictly inside the box constraints, .
The KKT conditions give three implications:
| condition | consequence |
|---|---|
| — at or beyond the margin | |
| — exactly on the margin | |
| — at or inside the margin |
The middle row is the note’s claim read left to right, and it is correct. The note is phrased the other way round — examples on the margin are examples with — and that direction is false, because the third row also permits exactly.
C = 0.5 (b from the primal: -1.000000)
n x_n y alpha y f(x) position
0 [3. 1.] +1 0.500000 -0.000000 inside / wrong side
2 [6. 1.] +1 0.009204 1.000000 ON the margin
3 [6. -1.] +1 0.004685 1.000000 ON the margin
7 [-1. 0.] -1 0.000000 1.333333 beyond the margin
on the margin : alpha in [0.004685, 0.009204] -- strictly inside
C = 2.0 (b from the primal: -2.000000)
n x_n y alpha y f(x) position
0 [3. 1.] +1 2.000000 1.000000 ON the margin
1 [3. -1.] +1 2.000000 1.000000 ON the margin
4 [1. 0.] -1 2.000000 1.000000 ON the margin
8 [4.5 0.] -1 2.000000 -2.500000 inside / wrong side
on the margin : alpha in [2.000000, 2.000000] -- AT the boundAt , three examples sit exactly on the margin with — at the box bound, not strictly inside it. This is not a solver artefact: the optimum is unique there. Writing , , , the constraints force and , and the dual objective is with . Maximising that pushes to its bound , giving — all three at the bound, and , matching the measured dual value of .
-
pch.quizShowAnswer
C — That sum of y_n alpha_n is zero, which makes it an affine combination rather than merely a linear one
-
pch.quizShowAnswer
B — Because a point beyond its margin has zero hinge loss in the primal and zero multiplier in the dual — it contributes nothing to Equation 12.38
-
pch.quizShowAnswer
C — The absolute value discards the sign, so the rule returns a non-negative number — on this data b* is -2 and the rule returns +2
-
pch.quizShowAnswer
B — The note's implication holds in one direction only: 0 < alpha < C implies on the margin, but an on-margin example may also have alpha = C. The note is phrased as the converse
Exercises
Section titled “Exercises”Exercise 1 – Solve the dual and recover w
Section titled “Exercise 1 – Solve the dual and recover w”Exercise 2 – Delete everything that is not a support vector
Section titled “Exercise 2 – Delete everything that is not a support vector”Exercise 3 – Test the margin note in both directions
Section titled “Exercise 3 – Test the margin note in both directions”Recall card
Section titled “Recall card”- The primal SVM’s size grows with the number of features; the dual’s grows with the number of examples. Section 12.3 rewrites the same problem in terms of one multiplier per example.
- Equation 12.38 is the representer theorem: the optimal weight vector is a linear combination of the training examples, and the constraint from the derivative in b makes it an affine one.
- In the dual the examples appear only through their inner products. That is what makes Section 12.4’s kernel substitution a one-line change.
- On the running example the dual is exact: the multipliers are a quarter, a quarter and a half, and they recover w = (1, 0) to 2e-08.
- An identity the book does not state: the total dual mass equals the squared norm of w, which is the inverse squared margin. Verified to 4.8e-08 across 200 random datasets. A wide margin means small multipliers.
- Sparsity is the point. Five of the eight examples can be deleted without changing the answer, and 500 easy ones can be added without changing it either — they carry 8.3e-12 of dual mass between them.
- That is the dual’s version of page 1205’s finding: a point beyond its margin has zero hinge loss and zero multiplier.
- Recovering b needs an example on the margin, and the book’s fallback rule takes a median of absolute values — which discards the sign and returns plus two where the answer is minus two.
- Strong duality holds to machine precision, because the primal is convex with affine constraints. That is what makes solving the dual instead of the primal legitimate rather than merely convenient.
- The book’s margin note about the box constraints runs only one way. Strictly inside the box implies exactly on the margin; the converse is false, and at C = 2 three on-margin examples sit at the bound.
- That case is a unique optimum, not solver noise — the constraints force a single feasible family and the objective pushes the multipliers to the bound.
Next: The Convex Hull View — §12.3.2, the same dual reached by a completely different geometric argument.
pch.coffeeTagline
pch.coffeeCtapch.feedbackHeading
pch.feedbackSubheading