Support Vector Machines and Support Vector Regression

Michael BrenndoerferOctober 26, 202650 min read

Learn how support vector machines and support vector regression work, from margins and hinge loss to kernels, dual coefficients, epsilon tubes, and scikit-learn implementation.

Machine Learning from ScratchAll chapters
Part 7 of 15Supervised Learning Beyond Linear Models
Chapter 56Support Vector Machines and Support Vector Regression
Reading the full chapter · 10 sections · 50 min10 sections · 50 min

All 10 sections · 50 min read

Support Vector Machines and Support Vector RegressionFull chapter · Sections in this chapter1 / 10 ↓
Reading tools Definitions, links & notes

Choose your expertise level to adjust how many terms are explained. Beginners see more tooltips, experts see fewer to maintain reading flow. Hover over underlined terms for instant definitions.

Article links

Make inline references clickable

Notes & comments

Support Vector Machines and Support Vector Regression

A classifier can fit every training label correctly and still fail to minimize the SVM objective. That happens in the toy example below: our fixed-step implementation agrees with the reference SVC on all training labels, while the reference fit has a lower value of the same hinge-loss objective. The scratch algorithm uses a fixed learning rate and a finite update budget without a convergence certificate. The Support Vector Machine (SVM) gives us an objective for assessing that optimization gap. For linearly separable data, its hard-margin form chooses the separating hyperplane with the widest buffer to the nearest training points. Its soft-margin form allows violations of that buffer in exchange for a penalty. We will derive both formulations and use the dual coefficients to identify which training points contribute to the fitted decision function.

The dual formulation gives a precise notion of sparsity. In a soft-margin SVM, training examples with zero dual coefficient do not contribute to the decision function. Only points on or inside the margin can have nonzero coefficients, although some such coefficients may also be zero. This differs from Lasso's sparsity in input-feature coefficients, and it can be useful computationally when the support set is small. A single formula, hinge loss plus an L2 penalty, connects the geometric story of maximum margins to regularized empirical risk minimization.

The same machinery extends to regression. Support Vector Regression (SVR) uses an ε\varepsilon-insensitive loss. Residuals with magnitude at most ε\varepsilon incur no data-fit loss, while excess residual magnitude is penalized linearly. Points strictly inside the tube have zero dual coefficients, which can produce a sparse model. Compared with squared loss, linear growth limits the influence of large response residuals, although it does not protect against every outlier or guarantee a small support set.

We work through margins, support vectors, the hinge loss, and the soft-margin Lagrangian, then connect valid kernels and ε-insensitive regression to executable examples. The margin and dual derivations spell out the Lagrangian steps.

Advantages

The maximum-margin principle gives SVMs a clean, geometric objective. With a valid positive-semidefinite kernel, the standard SVM objective is convex: every local minimum is global. Suitable solvers can approach a global optimum, but their stopping tolerances, update rules, and convergence conditions still matter. Support vectors identify the examples that contribute to the decision function, which can make the fit compact and useful to inspect. The support set can also contain most or all of the training data, and convexity alone does not make every fitted parameter unique.

The kernel trick extends the same dual optimization framework to nonlinear boundaries by replacing inner products with a valid kernel. A real-valued kernel must be symmetric and produce a positive-semidefinite Gram matrix for every finite collection of inputs; it then corresponds to inner products in a feature space. Support Vector Regression uses the same representation with an ε\varepsilon-insensitive loss. That loss ignores residuals within the tube and grows linearly outside it, reducing the influence of large response residuals relative to squared loss. Its support set need not be small, and whether it predicts better than OLS depends on the data and must be checked on validation data.

Disadvantages

Exact nonlinear kernel SVMs can become expensive as the training set grows. Materializing the full Gram matrix requires O(n2)O(n^2) storage, while decomposition solvers can compute entries on demand and keep a bounded cache. Training time depends on the kernel, feature dimension, data, cache, solver, and stopping tolerance; a single quadratic or cubic rate does not describe every SVM. Large linear problems can instead be fitted without a Gram matrix. Feature scales also affect the regularization and kernel geometry, so choose a meaningful scale for the inputs; standardization is a useful default when units differ, as discussed in Standardization.

SVM decision scores are not calibrated probabilities. In a binary model the score is f(x)f(\mathbf{x}); with a nonzero normal vector, divide by its feature-space norm to obtain signed distance to the hyperplane. Procedures such as Platt scaling or isotonic regression can estimate probabilities from scores, adding estimation work whose quality must be checked. Kernel settings and the penalty CC affect the fit, so compare relevant choices through hyperparameter search. With imbalanced classes, unweighted summed loss gives more total weight to the more numerous class; class weights or resampling within training folds can change that tradeoff.

Formula

We start with a question that is more subtle than it first appears: among all hyperplanes that separate two classes, which one should we trust? A hyperplane is specified by a normal vector w∈Rp\mathbf{w} \in \mathbb{R}^p and a bias b∈Rb \in \mathbb{R}, and the signed decision value is

f(x)=w⊤x+b.f(\mathbf{x}) = \mathbf{w}^\top \mathbf{x} + b.

where:

  • w\mathbf{w}: the normal vector of the hyperplane, which fixes its orientation
  • x\mathbf{x}: the input point being classified
  • bb: the bias term, which shifts the hyperplane away from the origin
  • f(x)f(\mathbf{x}): the signed decision value, positive on one side of the hyperplane and negative on the other

This tells us which side of the boundary a point lies on; away from a zero score, the predicted signed label is sign⁡(f(x))\operatorname{sign}(f(\mathbf{x})). For a nonzero normal vector, multiplying w\mathbf{w} and bb by a positive constant preserves both that prediction and the geometric boundary. Infinitely many boundaries may separate a dataset. In the separable hard-margin setting, the SVM selects the boundary with the widest empty buffer. Points with nonzero dual coefficients are called support vectors; in the hard-margin optimum they lie on the buffer's edge.

Margins, support vectors, and hinge loss

The perpendicular distance of a point x\mathbf{x} to the decision hyperplane f(x)=w⊤x+b=0f(\mathbf{x}) = \mathbf{w}^\top \mathbf{x} + b = 0 is

∣w⊤x+b∣∥w∥,\frac{|\mathbf{w}^\top \mathbf{x} + b|}{\|\mathbf{w}\|},

where:

  • w\mathbf{w}: the normal vector of the hyperplane
  • x\mathbf{x}: the query point whose distance we measure
  • bb: the bias term
  • ∥w∥=w⊤w\|\mathbf{w}\| = \sqrt{\mathbf{w}^\top \mathbf{w}}: the Euclidean length of the normal vector

This expression exposes an important scaling issue: multiplying w\mathbf{w} and bb by the same positive constant leaves the hyperplane and every perpendicular distance unchanged, because the numerator and denominator scale together. The unnormalized decision values f(x)f(\mathbf{x}) and functional margins yif(xi)y_i f(\mathbf{x}_i) do scale by that constant. The length ∥w∥\|\mathbf{w}\| therefore becomes a measure of margin width only after we fix the functional-margin scale. Here ∥w∥=w⊤w\|\mathbf{w}\| = \sqrt{\mathbf{w}^\top \mathbf{w}} is the Euclidean length of the normal vector; in the canonical hard-margin scale, the two margin hyperplanes have separation 2/∥w∥2/\|\mathbf{w}\|.

For a separating hyperplane, we can fix the scale so that the smallest functional margin is one. At the maximum-margin solution with both classes present, the bias centers the corridor between the nearest opposite-class projections, so the two supporting hyperplanes are f(x)=1f(\mathbf{x})=1 and f(x)=−1f(\mathbf{x})=-1. Their perpendicular separation is 2/∥w∥2/\|\mathbf{w}\|, with each one a distance 1/∥w∥1/\|\mathbf{w}\| from the decision hyperplane. Maximizing this width is equivalent to minimizing ∥w∥\|\mathbf{w}\|, or 12∥w∥2\tfrac12\|\mathbf{w}\|^2. The hard-margin problem therefore asks for the smallest weight norm subject to every training point lying on or beyond its class's margin hyperplane:

min⁡w, b  12∥w∥2s.t.  yi(w⊤xi+b)≥1,i=1,…,n.\begin{aligned} \min_{\mathbf{w},\, b} \;& \tfrac{1}{2}\|\mathbf{w}\|^2 \\ \text{s.t.} \;& y_i (\mathbf{w}^\top \mathbf{x}_i + b) \geq 1, \quad i = 1, \ldots, n. \end{aligned}

where:

  • 12∥w∥2\tfrac{1}{2}\|\mathbf{w}\|^2: the objective being minimized, equivalent to maximizing the margin 2/∥w∥2/\|\mathbf{w}\|
  • yi∈{−1,+1}y_i \in \{-1, +1\}: the label of the ii-th training example
  • xi\mathbf{x}_i: the ii-th training input
  • w⊤xi+b\mathbf{w}^\top \mathbf{x}_i + b: the signed decision value of the ii-th example
  • yi(w⊤xi+b)≥1y_i (\mathbf{w}^\top \mathbf{x}_i + b) \geq 1: the constraint that every point lies on or beyond its margin boundary

The quantity

mi=yi(w⊤xi+b)m_i = y_i(\mathbf{w}^\top \mathbf{x}_i + b)

is the functional margin of the ii-th example. In the canonical hard-margin optimum, support vectors have mi=1m_i=1, while points with mi>1m_i>1 lie beyond the corridor. In a soft-margin fit, mi<1m_i<1 indicates a margin violation, and support vectors can lie inside the margin or even be misclassified. The dual coefficient, rather than nearness alone, determines whether a point appears in the fitted decision function.

If the classes are linearly separable, the hard-margin constraints are feasible. If they are not, no hyperplane can keep the corridor empty, and insisting on the hard constraint makes the optimization problem infeasible. The SVM responds by turning the violation into a penalty. The hinge loss measures exactly how much a point fails the margin requirement:

Lhinge(mi)=max⁡(0, 1−mi).L_\text{hinge}(m_i) = \max\bigl(0,\, 1 - m_i\bigr).

where:

  • mi=yi(w⊤xi+b)m_i = y_i(\mathbf{w}^\top \mathbf{x}_i + b): the functional margin of the ii-th training example
  • 1−mi1 - m_i: the amount by which the functional margin falls short of 1

The maximum with zero clamps the loss at zero, so points with mi≥1m_i \geq 1 contribute no penalty and points that intrude into the margin or are misclassified incur a linear cost.

The hinge loss is zero once the functional margin reaches 1, and it grows linearly as points cross into the corridor or onto the wrong side. Penalizing these margin violations gives the soft-margin regularized empirical-risk objective:

min⁡w, b  12∥w∥2+C∑i=1nmax⁡ ⁣(0, 1−yi(w⊤xi+b)).\min_{\mathbf{w},\, b} \; \tfrac{1}{2}\|\mathbf{w}\|^2 + C \sum_{i=1}^n \max\!\bigl(0,\, 1 - y_i(\mathbf{w}^\top \mathbf{x}_i + b)\bigr).

where:

  • 12∥w∥2\tfrac{1}{2}\|\mathbf{w}\|^2: the margin term, which shrinks as the margin widens
  • CC: the penalty parameter controlling the exchange rate between margin width and training error
  • max⁡ ⁣(0, 1−yi(w⊤xi+b))\max\!\bigl(0,\, 1 - y_i(\mathbf{w}^\top \mathbf{x}_i + b)\bigr): the hinge loss of the ii-th example
  • ∑i=1n\sum_{i=1}^n: the sum over all training examples

The constant C>0C>0 sets the exchange rate between weight norm and training hinge loss. On a fixed dataset with the same kernel and penalty convention, increasing CC cannot increase the optimized total hinge loss, while the optimized squared weight norm cannot decrease. Either quantity can stay unchanged over a range of CC, and individual residuals or classification errors need not move monotonically. The hinge form needs no separate slack variables and can be optimized by subgradient methods. Because the loss has a kink at margin one, the following expressions give one valid subgradient of JJ:

∇wJ=w−C∑i∈Ayixi,∂J∂b=−C∑i∈Ayi,\nabla_{\mathbf{w}} J = \mathbf{w} - C \sum_{i \in \mathcal{A}} y_i \mathbf{x}_i, \qquad \frac{\partial J}{\partial b} = - C \sum_{i \in \mathcal{A}} y_i,

where:

  • J(w,b)=12∥w∥2+C∑i=1nmax⁡ ⁣(0,1−yi(w⊤xi+b))J(\mathbf{w}, b) = \tfrac{1}{2}\|\mathbf{w}\|^2 + C \sum_{i=1}^n \max\!\bigl(0, 1 - y_i(\mathbf{w}^\top \mathbf{x}_i + b)\bigr): the regularized hinge-loss objective being minimized
  • A={i:1−yi(w⊤xi+b)>0}\mathcal{A} = \{i : 1 - y_i(\mathbf{w}^\top \mathbf{x}_i + b) > 0\}: the set of points currently violating the margin, i.e. those with active hinge loss
  • CC: the exchange rate between margin width and training error

These expressions choose the zero hinge subgradient at points with mi=1m_i=1. At such a kink, any multiple −θiyixi-\theta_i y_i\mathbf{x}_i with θi∈[0,1]\theta_i\in[0,1] is allowed for the weight part of the hinge term, with the corresponding −θiyi-\theta_i y_i for the bias. Strict margin violators have the full hinge contribution, while points with mi>1m_i>1 have none. This current strict-violation set is not the dual support-vector set: an optimal point on the margin can have nonzero dual weight even though its hinge loss is zero.

Soft margins and regularization

The classical soft-margin formulation is the constrained version of the regularized empirical-risk objective above. Writing ξi=max⁡(0,1−yi(w⊤xi+b))\xi_i = \max\bigl(0, 1 - y_i(\mathbf{w}^\top \mathbf{x}_i + b)\bigr) as an explicit variable and minimizing 12∥w∥2+C∑iξi\tfrac{1}{2}\|\mathbf{w}\|^2 + C \sum_i \xi_i over w\mathbf{w}, bb, and ξ\xi subject to the relaxed margin constraints gives the same optimum as the hinge-loss problem. At the optimum, each slack records a functional-margin shortfall; a correctly classified point inside the margin can also have positive slack:

min⁡w, b, ξ  12∥w∥2+C∑i=1nξis.t.  yi(w⊤xi+b)≥1−ξi,ξi≥0.\begin{aligned} \min_{\mathbf{w},\, b,\, \xi} \;& \tfrac{1}{2}\|\mathbf{w}\|^2 + C \sum_{i=1}^n \xi_i \\ \text{s.t.} \;& y_i(\mathbf{w}^\top \mathbf{x}_i + b) \geq 1 - \xi_i, \quad \xi_i \geq 0. \end{aligned}

where:

  • ξi≥0\xi_i \geq 0: the slack for the ii-th example, measuring how far it violates the margin
  • 12∥w∥2\tfrac{1}{2}\|\mathbf{w}\|^2: the margin term
  • C∑i=1nξiC \sum_{i=1}^n \xi_i: the total violation penalty, scaled by CC
  • yi(w⊤xi+b)≥1−ξiy_i(\mathbf{w}^\top \mathbf{x}_i + b) \geq 1 - \xi_i: the relaxed margin constraint, allowing the ii-th example to fall short of the margin by at most ξi\xi_i

At any optimum, the slacks are pinned down by the KKT conditions:

ξi=max⁡(0,1−yi(w⊤xi+b)).\xi_i = \max\bigl(0, 1 - y_i(\mathbf{w}^\top \mathbf{x}_i + b)\bigr).

where:

  • ξi\xi_i: the optimal slack for the ii-th example
  • mi=yi(w⊤xi+b)m_i = y_i(\mathbf{w}^\top \mathbf{x}_i + b): the functional margin of the ii-th example
  • 1−mi1 - m_i: the amount by which the functional margin falls short of 1

This is why the slack formulation and the hinge-loss formulation describe the same learning problem even though they look different. In the constrained problem the slacks are auxiliary variables, but the KKT conditions pin each one to the value the hinge loss would assign it, so eliminating the slacks recovers the regularized empirical-risk objective exactly. The slack view is valuable because it reveals the constrained optimization structure and prepares us for the Lagrangian, which is where kernels enter.

Introduce multipliers αi≥0\alpha_i \geq 0 for the margin constraints and μi≥0\mu_i \geq 0 for the nonnegativity constraints. The Lagrangian is

L(w,b,ξ,α,μ)=12∥w∥2+C∑iξi−∑iαi ⁣[yi(w⊤xi+b)−1+ξi]−∑iμiξi.\mathcal{L}(\mathbf{w}, b, \xi, \alpha, \mu) = \tfrac{1}{2}\|\mathbf{w}\|^2 + C\sum_i \xi_i - \sum_i \alpha_i\!\left[y_i(\mathbf{w}^\top \mathbf{x}_i + b) - 1 + \xi_i\right] - \sum_i \mu_i \xi_i.

where:

  • w,b\mathbf{w}, b: the primal weight vector and bias
  • ξi≥0\xi_i \geq 0: the slack for the ii-th example, measuring how far it violates the margin
  • αi≥0\alpha_i \geq 0: the Lagrange multiplier for the ii-th margin constraint
  • μi≥0\mu_i \geq 0: the Lagrange multiplier for the nonnegativity constraint ξi≥0\xi_i \geq 0

Setting derivatives to zero gives three structural facts. First, ∂L/∂w=0\partial \mathcal{L} / \partial \mathbf{w} = 0 yields the weight as a linear combination of training points,

w=∑iαiyixi.\mathbf{w} = \sum_i \alpha_i y_i \mathbf{x}_i.

where:

  • αi≥0\alpha_i \geq 0: the Lagrange multiplier for the ii-th margin constraint
  • yi∈{−1,+1}y_i \in \{-1, +1\}: the label of the ii-th training example
  • xi\mathbf{x}_i: the ii-th training input
  • ∑i\sum_i: the sum over all training examples

This is the first sign that the solution may be sparse: any point with αi=0\alpha_i = 0 contributes nothing to the weight vector. Second, ∂L/∂b=0\partial \mathcal{L} / \partial b = 0 yields the balance condition

∑iαiyi=0.\sum_i \alpha_i y_i = 0.

where:

  • αi≥0\alpha_i \geq 0: the Lagrange multiplier for the ii-th margin constraint
  • yi∈{−1,+1}y_i \in \{-1, +1\}: the label of the ii-th training example
  • ∑i\sum_i: the sum over all training examples

Third, ∂L/∂ξi=0\partial \mathcal{L} / \partial \xi_i = 0 yields C−αi−μi=0C - \alpha_i - \mu_i = 0, so eliminating μi\mu_i gives the box constraint

0≤αi≤C.0 \leq \alpha_i \leq C.

Substituting the three equations back into L\mathcal{L} leaves only α\alpha behind:

max⁡α  ∑i=1nαi−12∑i,jαiαj yiyj xi⊤xjs.t.  0≤αi≤C,∑iαiyi=0.\begin{aligned} \max_{\alpha} \;& \sum_{i=1}^n \alpha_i - \tfrac{1}{2}\sum_{i,j} \alpha_i \alpha_j\, y_i y_j\, \mathbf{x}_i^\top \mathbf{x}_j \\ \text{s.t.} \;& 0 \leq \alpha_i \leq C, \quad \sum_i \alpha_i y_i = 0. \end{aligned}

where:

  • αi\alpha_i: the dual multiplier for the ii-th margin constraint, bounded in [0,C][0, C]
  • CC: the upper bound on each multiplier
  • xi⊤xj\mathbf{x}_i^\top \mathbf{x}_j: the pairwise inner product between training examples

The dual problem is a convex quadratic program: the objective is a concave quadratic in α\alpha that we maximize over the box and balance constraints, so the feasible region is convex and any local maximum is global. Apart from the box constraint 0≤αi≤C0 \leq \alpha_i \leq C and the balance condition ∑iαiyi=0\sum_i \alpha_i y_i = 0, its dependence on the training input vectors is only through pairwise inner products xi⊤xj\mathbf{x}_i^\top \mathbf{x}_j. The decision function becomes

f(x)=∑i=1nαiyi xi⊤x+b.f(\mathbf{x}) = \sum_{i=1}^n \alpha_i y_i\, \mathbf{x}_i^\top \mathbf{x} + b.

where:

  • x\mathbf{x}: the input point whose decision value we compute
  • αi\alpha_i: the dual multiplier of the ii-th training example
  • bb: the bias recovered from the KKT conditions
  • xi⊤x\mathbf{x}_i^\top \mathbf{x}: the inner product between the ii-th training point and the query point

The KKT complementarity conditions require αi=0\alpha_i=0 whenever yi(w⊤xi+b)>1y_i(\mathbf{w}^\top\mathbf{x}_i+b)>1. A point with 0<αi<C0<\alpha_i<C lies exactly on its margin hyperplane; a point with a strict violation has αi=C\alpha_i=C. At equality mi=1m_i=1, the multiplier can include either endpoint, so touching the margin does not by itself prove αi>0\alpha_i>0. The support vectors are precisely the points with positive dual coefficient in this representation. Only those terms remain in the decision sum, but the support set need not be a small fraction of the data.

There is also a useful connection to ordinary L2 regularization. If we divide the primal objective by nCnC and let

λ=1nC,\lambda = \frac{1}{nC},

the soft-margin objective becomes

λ2∥w∥2+1n∑i=1nξi.\frac{\lambda}{2}\|\mathbf{w}\|^2 + \frac{1}{n}\sum_{i=1}^n \xi_i.

Here the loss is averaged over the nn examples. Under this convention, C=1/(nλ)C = 1/(n\lambda): increasing CC reduces the relative strength of the L2 penalty. For a fixed training problem, the optimized total hinge loss cannot increase as CC grows, although the solution may stay unchanged over a range of values. If the loss is written as an unaveraged sum instead, the corresponding coefficient is λ=1/C\lambda = 1/C. Larger CC and larger Ridge-style λ\lambda therefore move regularization in opposite directions; always check the loss normalization before comparing libraries or codebases.

Kernel functions and nonlinear boundaries

The dual exposes a clean structural idea. Anywhere the algorithm touches an inner product xi⊤xj\mathbf{x}_i^\top \mathbf{x}_j, we can replace it with a symmetric function K(xi,xj)K(\mathbf{x}_i, \mathbf{x}_j) that corresponds to an inner product in some feature space φ\varphi, possibly infinite-dimensional:

K(xi,xj)=φ(xi)⊤φ(xj).K(\mathbf{x}_i, \mathbf{x}_j) = \varphi(\mathbf{x}_i)^\top \varphi(\mathbf{x}_j).

where:

  • KK: the kernel function, symmetric in its two arguments
  • xi,xj\mathbf{x}_i, \mathbf{x}_j: two input examples
  • φ\varphi: the feature map from input space into the (possibly infinite-dimensional) feature space

The dual problem and decision function replace each inner product by the kernel. The weight representation belongs to the feature space: wφ=∑iαiyiφ(xi)\mathbf{w}_\varphi=\sum_i\alpha_i y_i\varphi(\mathbf{x}_i). A nonlinear kernel need not provide a weight vector in the original input coordinates. The decision function is:

f(x)=∑iαiyiK(xi,x)+b.f(\mathbf{x}) = \sum_i \alpha_i y_i K(\mathbf{x}_i, \mathbf{x}) + b.

where:

  • αi\alpha_i: the dual multiplier of the ii-th training example
  • yiy_i: the label of the ii-th training example
  • K(xi,x)K(\mathbf{x}_i, \mathbf{x}): the kernel similarity between the ii-th training point and the query point
  • bb: the bias recovered from the KKT conditions

We can now fit nonlinear functions in the original input space without explicitly computing φ(x)\varphi(\mathbf{x}). This is the kernel trick. Three useful kernel examples are:

  • Linear kernel, K(z,z′)=z⊤z′K(\mathbf{z}, \mathbf{z}') = \mathbf{z}^\top \mathbf{z}', which recovers the linear soft-margin formulation.
  • Polynomial kernel, K(z,z′)=(z⊤z′+c)dK(\mathbf{z}, \mathbf{z}') = (\mathbf{z}^\top \mathbf{z}' + c)^d, with positive integer dd and c≥0c \geq 0. When c>0c > 0, its feature map contains scaled monomials of degrees zero through dd; when c=0c = 0 and d>0d > 0, it contains only degree-dd monomials.
  • Radial basis function (RBF) kernel, K(z,z′)=exp⁡(−γ∥z−z′∥2)K(\mathbf{z}, \mathbf{z}') = \exp(-\gamma\|\mathbf{z} - \mathbf{z}'\|^2), with γ>0\gamma > 0. Similarity falls to e−1e^{-1} at Euclidean separation 1/γ1/\sqrt{\gamma}, so this is its characteristic distance scale.

A real-valued kernel is valid when it is symmetric and its Gram matrix Kij=K(xi,xj)K_{ij}=K(\mathbf{x}_i,\mathbf{x}_j) is positive semidefinite for every finite input collection. This is the positive-type kernel condition that gives a Hilbert-space feature map. A PSD training matrix alone does not establish that condition on all inputs; Mercer's spectral expansion requires additional regularity assumptions. Logistic-style similarities σ(z⊤z′)\sigma(\mathbf{z}^\top\mathbf{z}') are not valid kernels in general and can make the dual nonconcave. The linear kernel, the polynomial kernel under the conditions above, and the RBF kernel with γ>0\gamma>0 are valid. Nonnegative weighted sums and pointwise products of valid kernels remain valid; the latter follows from the Schur product theorem applied to their Gram matrices.

Two controls govern the RBF kernel. A larger γ\gamma makes similarity more local, which can permit a more variable boundary when CC is large enough; it does not by itself force memorization. A smaller γ\gamma makes similarities vary more slowly. For fixed CC, taking γ\gamma all the way to zero makes the kernel approach the constant value one, so the fitted scores can flatten toward an intercept rather than recover a linear SVM. The penalty CC controls the cost of violations and interacts with this locality. Choose them jointly using validation, as covered in Hyperparameter Search and Nested Cross-Validation.

Epsilon-insensitive regression and practical limitations

Support Vector Regression extends everything above to a continuous target yi∈Ry_i \in \mathbb{R}. The idea is to build a tube of half-width ε>0\varepsilon > 0 along the fitted function and ignore residuals smaller than ε\varepsilon. The loss is symmetric and piecewise linear:

Lε(r)=max⁡(0,∣r∣−ε),L_\varepsilon(r) = \max\bigl(0, |r| - \varepsilon\bigr),

where:

  • rr: the residual yi−f(xi)y_i - f(\mathbf{x}_i) for a training example, i.e. the difference between the observed target and the predicted value
  • ε>0\varepsilon > 0: the half-width of the insensitive tube
  • ∣r∣−ε|r| - \varepsilon: the amount by which the residual exceeds the tube
  • max⁡(0,∣r∣−ε)\max\bigl(0, |r| - \varepsilon\bigr): the loss, zero inside the tube and linear outside

Points inside the tube incur zero loss; points outside incur a linear penalty. This is the regression analogue of the margin neighborhood: small errors are treated as noise and ignored, while large errors become support vectors that shape the fit.

In QP form we introduce two slacks per point, one for errors above the tube, ξi\xi_i, and one for errors below, ξi∗\xi_i^*:

min⁡w, b, ξ, ξ∗  12∥w∥2+C∑i=1n(ξi+ξi∗)s.t.  yi−(w⊤xi+b)≤ε+ξi,(w⊤xi+b)−yi≤ε+ξi∗,ξi, ξi∗≥0.\begin{aligned} \min_{\mathbf{w},\, b,\, \xi,\, \xi^*} \; & \tfrac{1}{2}\|\mathbf{w}\|^2 + C \sum_{i=1}^n (\xi_i + \xi_i^*) \\ \text{s.t.} \; & y_i - (\mathbf{w}^\top \mathbf{x}_i + b) \leq \varepsilon + \xi_i, \\ & (\mathbf{w}^\top \mathbf{x}_i + b) - y_i \leq \varepsilon + \xi_i^*, \\ & \xi_i,\, \xi_i^* \geq 0. \end{aligned}

where:

  • w,b\mathbf{w}, b: the primal weight vector and bias
  • ξi\xi_i: the slack for residuals above the tube (yi>f(xi)+εy_i > f(\mathbf{x}_i) + \varepsilon)
  • ξi∗\xi_i^*: the slack for residuals below the tube (yi<f(xi)−εy_i < f(\mathbf{x}_i) - \varepsilon)
  • CC: the penalty controlling how strongly residuals outside the tube are penalized
  • ε\varepsilon: the half-width of the insensitive tube

The dual has two multiplier families αi,αi∗∈[0,C]\alpha_i,\alpha_i^*\in[0,C]. With βi=αi−αi∗\beta_i=\alpha_i-\alpha_i^*, stationarity in the unpenalized bias gives ∑iβi=0\sum_i\beta_i=0, and stationarity in the weight gives w=∑iβiφ(xi)\mathbf{w}=\sum_i\beta_i\varphi(\mathbf{x}_i). Its objective is

max⁡α,α∗  ∑iyiβi−ε∑i(αi+αi∗)−12∑i,jβiβjK(xi,xj),∑iβi=0,0≤αi,αi∗≤C.\max_{\alpha,\alpha^*}\; \sum_i y_i\beta_i-\varepsilon\sum_i(\alpha_i+\alpha_i^*) -\frac12\sum_{i,j}\beta_i\beta_j K(\mathbf{x}_i,\mathbf{x}_j), \quad \sum_i\beta_i=0,\quad 0\le\alpha_i,\alpha_i^*\le C.

Here βi\beta_i is the signed coefficient of training example ii, and the ε\varepsilon term penalizes the total multiplier mass ∑i(αi+αi∗)\sum_i(\alpha_i+\alpha_i^*) in the dual maximization. An active tube constraint can still have zero multiplier. A PSD kernel makes this objective concave. The prediction is

f(x)=∑i=1n(αi−αi∗) K(xi,x)+b.f(\mathbf{x}) = \sum_{i=1}^n (\alpha_i - \alpha_i^*)\, K(\mathbf{x}_i, \mathbf{x}) + b.

where:

  • αi\alpha_i: the dual multiplier for the constraint yi−f(xi)≤ε+ξiy_i-f(\mathbf{x}_i)\le\varepsilon+\xi_i
  • αi∗\alpha_i^*: the dual multiplier for the constraint f(xi)−yi≤ε+ξi∗f(\mathbf{x}_i)-y_i\le\varepsilon+\xi_i^*
  • K(xi,x)K(\mathbf{x}_i, \mathbf{x}): the kernel similarity between the ii-th training point and the query point
  • bb: the bias recovered from the KKT conditions

Complementarity explains where nonzero coefficients can occur. For ε>0\varepsilon > 0, a point strictly inside the tube has αi=αi∗=0\alpha_i = \alpha_i^* = 0. A point on either edge may have a nonzero multiplier, while a point strictly outside has the corresponding multiplier at CC. Thus only points on or outside the tube can contribute, but their number need not be small. The tube half-width ε\varepsilon controls which residuals have zero loss, and CC controls the penalty beyond the tube. The linear growth of this loss limits sensitivity to large response residuals relative to squared error; it does not protect against every outlier or guarantee better generalization. At ε=0\varepsilon = 0, the loss becomes absolute error, and the prediction still uses the net coefficient αi−αi∗\alpha_i-\alpha_i^*.

The practical limits depend on the formulation. Exact nonlinear kernel SVMs can be expensive on large datasets, while dedicated linear solvers avoid the full kernel matrix. Choose input scales that reflect the problem and evaluate preprocessing within the training folds. A binary classification score is f(x)f(\mathbf{x}); when w≠0\mathbf{w}\ne0, its signed geometric distance is f(x)/∥w∥f(\mathbf{x})/\|\mathbf{w}\| in the model's feature space. Neither quantity is automatically a probability. Validate the relevant hyperparameters, including CC, kernel settings such as γ\gamma, and ε\varepsilon for SVR, alongside any probability calibration needed downstream.

Visualizing Support Vector Machines

The following cell generates a small two-dimensional toy dataset and fits a large-CC linear SVM, producing the decision-score field used by the margin figure below. A large penalty can recover a separating solution on this example; it is still a soft-margin SVC fit. The reference estimator uses labels 0 and 1; our signed mathematical labels are −1-1 and +1+1. We map 0 to −1-1 and 1 to +1+1 when calculating functional margins.

PythonIn [3]
CollapseExpand
rng = np.random.default_rng(7)
X_neg = rng.normal(loc=(-1.0, -1.0), scale=0.35, size=(20, 2))
X_pos = rng.normal(loc=(1.0, 1.0), scale=0.35, size=(20, 2))
X_toy = np.vstack([X_neg, X_pos])
y_toy = np.array([0] * 20 + [1] * 20)

svc_demo = SVC(kernel="linear", C=1e4).fit(X_toy, y_toy)

# Precompute the decision-score field for the margin figure
xx, yy = np.meshgrid(np.linspace(-2.5, 2.5, 400), np.linspace(-2.5, 2.5, 400))
scores = svc_demo.decision_function(np.c_[xx.ravel(), yy.ravel()]).reshape(
    xx.shape
)
VisualizationOut [4]
CollapseExpand
Two clusters with a linear SVM decision boundary and margin lines. The two solver support vectors lie on the margins up to numerical tolerance and are circled.
Large-C linear SVM on separated data. The solid line is the zero-score decision boundary, the dashed lines mark scores of minus one and plus one, and circled points are the reference solver's support vectors lying on the margins up to numerical tolerance.

The dual view gives a second way to read the fitted margin. In the large-C fit above, most training points have zero dual coefficient, while the support vectors carry positive coefficient magnitudes. The next cell records those coefficients and the functional margins used by the figure.

PythonIn [5]
CollapseExpand
y_signed_toy = np.where(y_toy == 1, 1.0, -1.0)
f_toy = svc_demo.decision_function(X_toy)
margins_toy = y_signed_toy * f_toy
alpha_full = np.zeros_like(margins_toy)
alpha_full[svc_demo.support_] = np.abs(svc_demo.dual_coef_.ravel())
support_mask = alpha_full > 0.0
VisualizationOut [6]
CollapseExpand
Dual coefficient magnitude versus margin; nonzero values cluster near margin one.
Absolute dual coefficients for the large-C linear SVM on the toy data, plotted against the training functional margin. Nonzero coefficients occur only for support vectors near margin one; the two support vectors have almost identical margins and coefficients, so their positive-coefficient markers overlap at this scale. Non-support points have margins above one and zero coefficients.

The hinge loss makes the margin behavior quantitative. The next figure compares the hinge, logistic, and zero-one losses as functions of the functional margin m=y f(x)m = y\,f(\mathbf{x}), where y∈{−1,+1}y \in \{-1, +1\} and f(x)=w⊤x+bf(\mathbf{x}) = \mathbf{w}^\top \mathbf{x} + b. All three approach zero for very confident correct predictions, but the hinge loss transitions sharply at m=1m = 1; its flat region for m>1m > 1 removes those points from the hinge subgradient. At an optimum, KKT complementarity also forces their dual coefficients to zero. The resulting support set can be sparse; its size depends on the data and fit.

For the plotted zero-one margin loss, a zero-margin tie counts as an error. The scratch prediction code later chooses class 0 at an exactly zero score; tie handling is a stated convention rather than a property shared by every classifier API.

The following cell computes the loss curves that the figure below renders.

PythonIn [7]
CollapseExpand
m_grid = np.linspace(-2.5, 2.5, 500)
hinge_vals = np.maximum(0.0, 1.0 - m_grid)
logistic_vals = np.log1p(np.exp(-m_grid))
zero_one_vals = (m_grid <= 0).astype(float)

The loss curves are computed in the preceding cell and only rendered here.

VisualizationOut [8]
CollapseExpand
Line plot of three loss curves: hinge loss decreases linearly to zero as the margin rises to one and stays zero above one; logistic loss decays smoothly; zero-one is a step.
Hinge, logistic, and zero-one losses as functions of the functional margin. Hinge loss decreases linearly toward zero at margin one and stays flat beyond it, logistic loss decays smoothly, and zero-one is a step function; a point strictly beyond margin one has zero dual coefficient at an optimum, which links the flat hinge region to the sparse support set.

The kernel trick changes nonlinear behavior substantially. The next figures compare linear and RBF SVMs on data with a curved decision boundary and independently seeded label flips at an 8% probability. Both models use C=3, so the penalty is held constant.

PythonIn [9]
CollapseExpand
X_wave = rng.normal(scale=0.9, size=(120, 2))
y_wave = (X_wave[:, 1] ** 2 + X_wave[:, 0] ** 2 > 1.2).astype(int)
noise_rng = np.random.default_rng(71)
flip_mask = noise_rng.random(y_wave.size) < 0.08
y_wave = np.where(flip_mask, 1 - y_wave, y_wave)
lin_svm = SVC(kernel="linear", C=3.0).fit(X_wave, y_wave)
rbf_svm = SVC(kernel="rbf", C=3.0, gamma=2.0).fit(X_wave, y_wave)
noise_count = int(flip_mask.sum())
linear_wave_accuracy = (lin_svm.predict(X_wave) == y_wave).mean()
rbf_wave_accuracy = (rbf_svm.predict(X_wave) == y_wave).mean()
linear_wave_support = lin_svm.support_.size
rbf_wave_support = rbf_svm.support_.size

# Precompute decision-score fields for the kernel comparison figure
xx_wave, yy_wave = np.meshgrid(np.linspace(-3, 3, 400), np.linspace(-3, 3, 400))
Z_lin = lin_svm.decision_function(
    np.c_[xx_wave.ravel(), yy_wave.ravel()]
).reshape(xx_wave.shape)
Z_rbf = rbf_svm.decision_function(
    np.c_[xx_wave.ravel(), yy_wave.ravel()]
).reshape(xx_wave.shape)
wave_limit = max(np.abs(Z_lin).max(), np.abs(Z_rbf).max())
wave_levels = np.linspace(-wave_limit, wave_limit, 21)
VisualizationsOut [10]
CollapseExpand
Nearly uniform negative linear-SVM score field with no zero-score boundary in the displayed rectangle. Both classes of noisy training points are shown.
Linear SVM score field on seeded noisy observations with C=3. The model predicts class 0 throughout the displayed rectangle, so a zero-score decision boundary does not appear; this illustrates the limited flexibility of a linear boundary for radial structure.
RBF SVM score field with a closed main boundary around the inner class and a small separate region near the lower left, on the same noisy points.
RBF SVM score field on the same seeded noisy observations with C=3. The nonlinear boundary follows the main radial structure and also forms a small separate region, showing how the kernel captures curved class geometry.
ConsoleOut [11]
CollapseExpand
flipped labels: 14/120 (0.117)
linear training accuracy: 0.583; support vectors: 104
RBF training accuracy:    0.875; support vectors: 69

The training diagnostics are computed on the same 120 observations with the same penalty C. They show how each hypothesis class fits this noisy example; they do not estimate performance on new data. The RBF fit has higher training accuracy here, and its plot shows a nonlinear boundary around the main radial structure. The linear model predicts one class across the displayed window. The support counts describe the fitted representations; they do not independently establish which model generalizes better. The independent seed for label flips leaves the earlier data generator's stream unchanged for the later SVR example.

The ε\varepsilon-insensitive loss is zero for ∣r∣≤ε|r| \leq \varepsilon and grows linearly outside that interval. The linear tails reduce the influence of large response residuals relative to squared loss, without guaranteeing resistance to high-leverage inputs. The following cell computes the three loss curves used in the figure below.

PythonIn [12]
CollapseExpand
r_grid = np.linspace(-3, 3, 500)
eps_demo = 0.5
eps_loss_vals = np.maximum(0.0, np.abs(r_grid) - eps_demo)
squared_loss_vals = r_grid**2
abs_loss_vals = np.abs(r_grid)
VisualizationOut [13]
CollapseExpand
Line plot of three regression loss curves: epsilon-insensitive is flat between minus epsilon and plus epsilon and linear outside; squared is quadratic; absolute is V-shaped.
Epsilon-insensitive, squared-error, and absolute-error losses. The epsilon-insensitive loss is flat between minus and plus epsilon and grows linearly outside the tube, whereas squared-error rises quadratically and absolute-error is V-shaped; the flat region makes SVR ignore small residuals while the linear tails limit the influence of large ones relative to squared loss.

An SVR fit shows the tube explicitly. The band of width 2ε2\varepsilon surrounds the model prediction, and training points inside it incur zero data-fit loss. The weight penalty remains part of the full objective. The following cell fits the SVR and computes the prediction curve used in the figure below.

PythonIn [14]
CollapseExpand
x_demo = np.sort(rng.uniform(-3.0, 3.0, 60))
y_demo = np.sin(x_demo) + 0.1 * rng.normal(size=x_demo.size)
X_demo = x_demo.reshape(-1, 1)

svr_demo = SVR(kernel="rbf", C=2.0, gamma=0.9, epsilon=0.2).fit(X_demo, y_demo)
x_grid = np.linspace(-3.0, 3.0, 400)
pred_grid = svr_demo.predict(x_grid.reshape(-1, 1))
VisualizationOut [15]
CollapseExpand
Scatter of noisy sine-wave data with a fitted SVR curve and shaded epsilon band around it. Support vectors on or outside the band up to solver tolerance are circled.
Support Vector Regression with an RBF kernel fit to noisy sine-wave data. The shaded band of half-width epsilon surrounds the prediction, points inside it incur zero loss, and circled support vectors lie on or outside the tube up to solver tolerance, showing how the tube controls which observations shape the fit.

Example

Two points suffice to work the margin calculation by hand. Let

x1=(1,1),  y1=+1,x2=(−1,−1),  y2=−1.\mathbf{x}_1 = (1, 1), \; y_1 = +1, \qquad \mathbf{x}_2 = (-1, -1), \; y_2 = -1.

where:

  • x1,x2∈R2\mathbf{x}_1, \mathbf{x}_2 \in \mathbb{R}^2: the two training inputs
  • y1,y2∈{−1,+1}y_1, y_2 \in \{-1, +1\}: their corresponding labels

The hard-margin problem for these two points is

min⁡w, b  12(w12+w22)s.t.  w1+w2+b≥1,w1+w2−b≥1.\begin{aligned} \min_{\mathbf{w},\, b} \;& \tfrac{1}{2}(w_1^2 + w_2^2) \\ \text{s.t.} \;& w_1 + w_2 + b \geq 1, \\ & w_1 + w_2 - b \geq 1. \end{aligned}

We can prove the symmetry rather than assume it. Let s=w1+w2s=w_1+w_2. The two constraints imply s≥1+∣b∣s\ge1+|b|, while w12+w22≥s2/2w_1^2+w_2^2\ge s^2/2, with equality only when w1=w2w_1=w_2. Hence the objective is at least (1+∣b∣)2/4≥1/4(1+|b|)^2/4\ge1/4. Equality is attained by b=0b=0 and w1=w2=1/2w_1=w_2=1/2, proving global optimality. At this solution both margin constraints are tight:

point 1:(+1)(w1+w2)=1,point 2:(−1)(−w1−w2)=1.\text{point 1:} \quad (+1)(w_1 + w_2) = 1, \qquad \text{point 2:} \quad (-1)(-w_1 - w_2) = 1.

Both equations reduce to w1+w2=1w_1 + w_2 = 1. Under the symmetry assumption w1=w2w_1 = w_2 we find w1=w2=0.5w_1 = w_2 = 0.5, so w=(0.5,0.5)\mathbf{w} = (0.5, 0.5) and ∥w∥=0.52+0.52=0.5≈0.707\|\mathbf{w}\| = \sqrt{0.5^2 + 0.5^2} = \sqrt{0.5} \approx 0.707. The margin width is

2∥w∥=20.5=20.707…≈2.828,\begin{aligned} \frac{2}{\|\mathbf{w}\|} &= \frac{2}{\sqrt{0.5}} \\ &= \frac{2}{0.707\ldots} \\ &\approx 2.828, \end{aligned}

and the decision boundary is the line x1+x2=0x_1 + x_2 = 0.

To connect this back to the dual, let α1,α2≥0\alpha_1, \alpha_2 \geq 0 be the multipliers. The KKT stationarity condition gives

w=∑iαiyixi=α1(1,1)+α2(−1)(−1,−1)=(α1+α2)(1,1).\mathbf{w} = \sum_i \alpha_i y_i \mathbf{x}_i = \alpha_1 (1, 1) + \alpha_2 (-1) (-1, -1) = (\alpha_1 + \alpha_2)(1, 1).

Since w=(0.5,0.5)\mathbf{w}=(0.5,0.5), stationarity requires α1+α2=0.5\alpha_1+\alpha_2=0.5. The balance condition gives α1=α2=0.25\alpha_1=\alpha_2=0.25. These hard-margin multipliers are feasible for the soft-margin box constraints when C≥0.25C\ge0.25, so the same zero-slack solution is optimal there. For 0<C<0.250<C<0.25, the dual optimum has α1=α2=C\alpha_1=\alpha_2=C and w=(2C,2C)\mathbf{w}=(2C,2C). Choosing b=0b=0 then gives both points functional margin 4C<14C<1. In fact every b∈[4C−1, 1−4C]b\in[4C-1,\,1-4C] is optimal in this regime, showing that the unpenalized bias need not be unique.

Returning to the hard-margin solution, which is also the soft-margin solution for C≥0.25C\geq0.25, we can check strong duality. Its primal objective is

12∥w∥2=12(0.52+0.52)=12(0.5)=0.25.\tfrac{1}{2}\|\mathbf{w}\|^2 = \tfrac{1}{2}\bigl(0.5^2 + 0.5^2\bigr) = \tfrac{1}{2}(0.5) = 0.25.

Because both points sit exactly on the margin, their slack values are zero and the hinge-loss sum vanishes, so the primal objective equals the margin term alone. This is the dual echo of the geometric statement that the two closest points fully determine the boundary.

We can verify the calculation with the dual objective. Note that

x1⊤x1=x2⊤x2=2,x1⊤x2=−2,\mathbf{x}_1^\top \mathbf{x}_1 = \mathbf{x}_2^\top \mathbf{x}_2 = 2, \qquad \mathbf{x}_1^\top \mathbf{x}_2 = -2,

so the cross term carries a negative label product y1y2=−1y_1 y_2 = -1, and the negative inner product x1⊤x2=−2\mathbf{x}_1^\top \mathbf{x}_2 = -2 makes the product positive. Thus

∑i,jαiαjyiyjxi⊤xj=α12y12x1⊤x1+2α1α2y1y2x1⊤x2+α22y22x2⊤x2=0.252⋅2+2⋅0.25⋅0.25⋅(1)(−1)(−2)+0.252⋅2=0.0625⋅2+0.125⋅2+0.0625⋅2=0.125+0.25+0.125=0.5.\begin{aligned} \sum_{i,j} \alpha_i \alpha_j y_i y_j \mathbf{x}_i^\top \mathbf{x}_j &= \alpha_1^2 y_1^2 \mathbf{x}_1^\top \mathbf{x}_1 + 2\alpha_1\alpha_2 y_1 y_2 \mathbf{x}_1^\top \mathbf{x}_2 + \alpha_2^2 y_2^2 \mathbf{x}_2^\top \mathbf{x}_2 \\ &= 0.25^2 \cdot 2 + 2 \cdot 0.25 \cdot 0.25 \cdot (1)(-1)(-2) + 0.25^2 \cdot 2 \\ &= 0.0625 \cdot 2 + 0.125 \cdot 2 + 0.0625 \cdot 2 \\ &= 0.125 + 0.25 + 0.125 = 0.5. \end{aligned}

and the dual objective equals

∑iαi−12∑i,jαiαjyiyjxi⊤xj=(0.25+0.25)−12(0.5)=0.5−0.25=0.25.\sum_i \alpha_i - \tfrac{1}{2} \sum_{i,j} \alpha_i \alpha_j y_i y_j \mathbf{x}_i^\top \mathbf{x}_j = (0.25 + 0.25) - \tfrac{1}{2}(0.5) = 0.5 - 0.25 = 0.25.

where:

  • αi\alpha_i: the optimal dual multipliers α1=α2=0.25\alpha_1 = \alpha_2 = 0.25 from the stationarity condition
  • yiy_i: the labels y1=+1y_1 = +1 and y2=−1y_2 = -1
  • xi⊤xj\mathbf{x}_i^\top \mathbf{x}_j: the pairwise inner products, x1⊤x1=x2⊤x2=2\mathbf{x}_1^\top \mathbf{x}_1 = \mathbf{x}_2^\top \mathbf{x}_2 = 2 and x1⊤x2=−2\mathbf{x}_1^\top \mathbf{x}_2 = -2
  • 0.50.5: the value of the double sum computed above

The dual objective value 0.250.25 matches the primal value 0.250.25, which is consistent with strong duality.

Now consider a slightly harder case that exercises the soft margin. Add a third point x3=(2,2)\mathbf{x}_3 = (2, 2) with y3=−1y_3 = -1. Keep the original candidate w=(0.5,0.5)\mathbf{w} = (0.5, 0.5) and b=0b = 0; rescaling it would change the functional margins used by the objective. For the third point,

y3f(x3)=(−1)(0.5⋅2+0.5⋅2)=−2.y_3 f(\mathbf{x}_3) = (-1)\bigl(0.5\cdot 2+0.5\cdot 2\bigr) = -2.

Its smallest feasible slack at this candidate is therefore

ξ3=max⁡(0,1−y3f(x3))=3.\xi_3=\max(0,1-y_3 f(\mathbf{x}_3))=3.

The original two points still have zero slack, so this candidate has objective 14+3C\tfrac14+3C. This is a feasible value, not proof that the candidate is optimal.

In fact, this dataset has a useful structure: the positive point lies between two negative points on the same line. For every C>0C>0, the exact soft-margin optimum is the constant classifier

w=(0,0),b=−1,(ξ1,ξ2,ξ3)=(2,0,0).\mathbf{w}=(0,0),\qquad b=-1,\qquad (\xi_1,\xi_2,\xi_3)=(2,0,0).

It predicts the negative class for all three points, pays hinge loss two for the positive point, and has objective 2C2C. We can prove optimality using the dual multipliers

(α1,α2,α3)=(C,C3,2C3).(\alpha_1,\alpha_2,\alpha_3) =\left(C,\frac C3,\frac{2C}{3}\right).

They satisfy the box constraints and α1−α2−α3=0\alpha_1-\alpha_2-\alpha_3=0, and they give

∑iαiyixi=(C+C3−4C3)(1,1)=(0,0).\sum_i\alpha_i y_i\mathbf{x}_i =\left(C+\frac C3-\frac{4C}{3}\right)(1,1) =(0,0).

The dual objective is consequently ∑iαi−12∥w∥2=2C\sum_i\alpha_i-\tfrac12\|\mathbf{w}\|^2=2C, matching the primal value. A feasible primal value matching a feasible dual value establishes global optimality.

Here CC changes the objective value without changing the fitted classifier. The usual margin-versus-loss tradeoff does not promise that the boundary moves whenever CC changes. Since w=0\mathbf{w}=0, this constant solution has no separating hyperplane with a finite margin width 2/∥w∥2/\|\mathbf{w}\|; the soft-margin objective is still well defined.

Implementation in Scikit-learn

We build the linear hinge-loss classifier from primitives first, then compare it with scikit-learn's SVC on the same data. Working from first principles helps us see where the subgradient comes from and how sensitive the solution is to feature scaling. We standardize the numerical inputs here so that both optimizers use the same feature representation.

PythonIn [16]
CollapseExpand
def hinge_objective(X, y_signed, w, b, C):
    margins = y_signed * (X @ w + b)
    return 0.5 * (w @ w) + C * np.maximum(0.0, 1.0 - margins).sum()


def hinge_subgradient(X, y_signed, w, b, C):
    margins = y_signed * (X @ w + b)
    active = (1.0 - margins) > 0
    dw = w - C * (X[active].T @ y_signed[active])
    db = -C * y_signed[active].sum()
    return dw, db


def train_linear_svm(X, y_signed, C=1.0, lr=0.05, n_iter=3000):
    w = np.zeros(X.shape[1])
    b = 0.0
    for _ in range(n_iter):
        dw, db = hinge_subgradient(X, y_signed, w, b, C)
        w = w - lr * dw
        b = b - lr * db
    return w, b

We reuse the toy two-dimensional dataset from the visualization section. The full toy set acts as training data here; this example has no held-out performance estimate. We compute the means and standard deviations from those training inputs only, then supply the same standardized features to both optimizers. Scaling changes the geometry of the weight penalty and kernel distances. A feature with large numerical units can contribute heavily to a distance calculation, but that does not imply that an SVM must ignore every smaller-scale feature.

PythonIn [17]
CollapseExpand
mu = X_toy.mean(axis=0)
sd = X_toy.std(axis=0)
X_std = (X_toy - mu) / sd
y_signed = np.where(y_toy == 1, 1.0, -1.0)

w_scratch, b_scratch = train_linear_svm(
    X_std, y_signed, C=2.0, lr=0.05, n_iter=3000
)
train_scores = X_std @ w_scratch + b_scratch
train_pred = (train_scores > 0).astype(int)
margins_scratch = y_signed * (X_std @ w_scratch + b_scratch)
n_active = int(((1.0 - margins_scratch) > 0).sum())
train_accuracy_scratch = (train_pred == y_toy).mean()

This fixed-step subgradient run uses a budget of 3,000 updates; that budget does not certify convergence to the optimum. We print the training accuracy, the weight norm ∥w∥\|\mathbf{w}\|, and the count of hinge-active examples. The count records strict margin violations, mi<1m_i<1, at the current iterate. It includes misclassified points as well as correctly classified points too close to the boundary.

ConsoleOut [18]
CollapseExpand
scratch training accuracy: 1.000
scratch ||w||:              1.228
hinge-active examples:      0/40
hinge-active fraction:      0.000

Now compare with the reference SVC, using the same CC and standardized inputs. Its printed margin width is measured in the standardized feature coordinates supplied to this fit. The reference solver works with the dual quadratic program, while our scratch implementation descends on the primal hinge objective. They target the same normalized hinge objective, but matching training labels alone does not establish that their parameter estimates or objective values agree.

PythonIn [19]
CollapseExpand
svc_ref = SVC(kernel="linear", C=2.0).fit(X_std, y_toy)
svc_pred = svc_ref.predict(X_std)
svc_margin = 2.0 / np.linalg.norm(svc_ref.coef_.ravel())
scratch_objective = hinge_objective(
    X_std, y_signed, w_scratch, b_scratch, C=2.0
)
reference_objective = hinge_objective(
    X_std, y_signed, svc_ref.coef_.ravel(), svc_ref.intercept_[0], C=2.0
)
objective_gap = scratch_objective - reference_objective
reference_support_count = svc_ref.support_.size
ConsoleOut [20]
CollapseExpand
sklearn training accuracy: 1.000
sklearn ||w||:             1.142
sklearn margin width:      1.752
agreement (scratch, sklearn): 1.000
sklearn support vectors:   2/40
sklearn support fraction:  0.050
scratch hinge objective:   0.754472
reference hinge objective: 0.651577
objective gap:             0.102895

The printed label agreement and objective gap answer different questions. Matching labels on this easy training set can coexist with a noticeable objective gap, because a fixed step size can keep the scratch iterate moving around the nonsmooth optimum. The scratch objective uses 12∥w∥2+C∑iξi\tfrac{1}{2}\|\mathbf{w}\|^2 + C\sum_i \xi_i, matching the reference SVC normalization. The scratch hinge-active fraction counts strict margin violations at its current iterate; it is not the dual support-vector fraction. The reference support count comes separately from svc_ref.support_.

The SVR side follows the same pattern. We reuse the noisy sine dataset from the visualization and inspect epsilon-insensitive loss and tube occupancy alongside the reference support-vector set. Points strictly inside the tube have zero epsilon-insensitive loss and zero dual coefficients. Points on the tube edges can have nonzero coefficients, as can points outside; the support set is not limited to strict outside points.

PythonIn [21]
CollapseExpand
def epsilon_insensitive_loss(residuals, epsilon):
    return np.maximum(0.0, np.abs(residuals) - epsilon)


svr_epsilon = 0.2
svr_ref = SVR(kernel="rbf", C=2.0, gamma=0.9, epsilon=svr_epsilon).fit(
    X_demo, y_demo
)
in_sample_pred = svr_ref.predict(X_demo)
res = y_demo - in_sample_pred
inside_tube = np.abs(res) <= svr_epsilon
inside_count = int(inside_tube.sum())
inside_fraction = inside_tube.mean()
mean_epsilon_loss = epsilon_insensitive_loss(res, svr_epsilon).mean()
mean_squared_residual = (res**2).mean()
ConsoleOut [22]
CollapseExpand
SVR support-vector count:  8/60
mean epsilon-insensitive loss: 0.0000
mean squared residual:         0.0114
points with |residual| <= epsilon: 55/60 (0.917)

The printed tube occupancy directly counts residuals with ∣r∣≤ε|r| \leq \varepsilon, using the fitted predictions. The mean epsilon-insensitive loss and mean squared residual summarize different loss functions and scale differently when target units change; their relative magnitudes do not reveal how many observations lie inside the tube. The reference support set can include points on the tube boundary, and finite solver tolerance can put their computed residuals slightly inside or outside it. These in-sample diagnostics describe the fit; they do not establish that the model generalizes or that a particular tube width is optimal.

The tube width is a tuning choice, not a fixed property of the data. Refitting SVR on the same sine training set over a small epsilon grid shows how the support fraction and the fraction of in-sample residuals inside the tube vary. Here the support fraction decreases across the grid, while the measured inside-tube fraction rises overall and is unchanged between epsilon 0.2 and 0.4. These counts use the fitted residuals and the exact comparison shown in the code, so solver tolerance can affect points near the tube edges. This is a training-set diagnostic, not a validation comparison.

PythonIn [23]
CollapseExpand
epsilon_grid = np.array([0.05, 0.10, 0.20, 0.40, 0.80])
support_fraction = []
inside_fraction = []
for eps_val in epsilon_grid:
    svr_scan = SVR(kernel="rbf", C=2.0, gamma=0.9, epsilon=float(eps_val)).fit(
        X_demo, y_demo
    )
    pred_scan = svr_scan.predict(X_demo)
    support_fraction.append(len(svr_scan.support_) / len(y_demo))
    inside_fraction.append(np.mean(np.abs(y_demo - pred_scan) <= eps_val))
support_fraction = np.array(support_fraction)
inside_fraction = np.array(inside_fraction)
VisualizationOut [24]
CollapseExpand
Support-vector fraction decreases across five epsilon fits; the inside-tube fraction rises overall and is equal at epsilon 0.2 and 0.4.
Support-vector fraction and in-sample inside-tube fraction for RBF SVR as the epsilon tube half-width varies on a fixed training set. On this seeded grid, the support fraction decreases and the measured inside-tube fraction rises overall, with equal inside fractions at epsilon 0.2 and 0.4. Each point uses a refitted model at the same C and gamma; these observed trends are not a universal monotonicity guarantee.

The implementation uses C, kernel, gamma, and epsilon directly; these are summarized jointly with the reference-library controls in the Key Methods and Key Parameters sections that follow.

Key Methods

These methods support fitting, prediction, and inspection of the decision scores.

  • SVC(...).fit(X, y): trains a soft-margin classifier. The linear-kernel version can be compared with dedicated linear solvers for larger datasets.
  • SVR(...).fit(X, y): trains an ε\varepsilon-insensitive regressor, using C, the selected kernel's settings, and epsilon. The class_weight parameter belongs to SVC; both estimators accept sample_weight in fit to rescale individual violation penalties.
  • decision_function(X): in the binary example, returns the score f(x)f(\mathbf{x}). Positive scores select the positive class. For a nonzero linear weight vector, divide by ∥w∥\|\mathbf{w}\| to obtain signed perpendicular distance. For multiclass SVC, training uses one-vs-one classifiers; the default decision_function_shape="ovr" converts their outputs into one score per class. Scores are not calibrated probabilities.
  • predict(X): returns class labels for SVC and continuous predictions for SVR.
  • predict_proba(X): for SVC, enable probability=True before fitting. libsvm estimates probabilities using additional internal five-fold cross-validation and Platt scaling for the binary models. This slows fitting, and the most probable class can differ from predict(X). Assess probability calibration on held-out data.

Key Parameters

Below are some of the main parameters that affect how SVMs work and perform, using SVC and SVR in scikit-learn.

  • C: controls the penalty for margin or tube violations. Under the mean-loss convention λ∥w∥2/2+∑iLi/n\lambda\|\mathbf{w}\|^2/2+\sum_iL_i/n, C=1/(nλ)C=1/(n\lambda); larger C means weaker relative regularization.
  • kernel: chooses the feature-space inner product. A linear kernel keeps a linear boundary in the supplied features; polynomial and RBF kernels can produce nonlinear boundaries.
  • gamma: controls RBF locality, with characteristic distance 1/γ1/\sqrt{\gamma}. Tune it jointly with C; taking it to zero at fixed C does not generally recover a linear SVM.
  • epsilon: sets the SVR tube's half-width in target units. A wider tube ignores more residual values for a fixed fitted function and can encourage a sparser fit. At epsilon=0 the loss is absolute error, rather than squared error.
  • class_weight: changes the class-specific violation penalties in SVC. Choose weights using class frequencies, error costs, and validation; weighting and resampling are options whose suitability depends on the task.

Practical Implications

This section covers when to use SVMs, recommended practices, common pitfalls, and computational and deployment considerations.

When to Use SVMs

SVMs are useful candidates for moderate-sized nonlinear problems and for high-dimensional applications such as sparse text classification or bioinformatics. A kernel is especially attractive when it expresses a meaningful similarity that would be awkward to construct as explicit features. Dedicated linear SVM solvers can also handle much larger sparse datasets. The convex objective gives every exact optimum the same objective value, but bias terms or dual coefficients can be nonunique, and finite solver tolerances can produce different fitted scores. Compare models using validation and record the loss, normalization, preprocessing, and solver settings when reproducing a result.

For tabular data with mixed numerical and categorical inputs, compare the SVM with tree ensembles or gradient boosting using suitable preprocessing and validation. Runtime differences depend on sample size, representation, and tuning budget. A nonlinear kernel sum does not automatically provide a decomposition into per-feature contributions, whereas a linear SVM has the additive score ∑jwjxj+b\sum_j w_jx_j+b. If probabilities are required, include calibration and its validation in the comparison.

Best Practices

Use C=1 and gamma="scale" as a baseline for an RBF classifier, then compare relevant kernels and parameter ranges with cross-validation, following Hyperparameter Search and Nested Cross-Validation. A logarithmic range such as 10−310^{-3} through 10310^3 is a starting search range, not a universal one. For large linear problems, consider LinearSVC or SGDClassifier(loss="hinge"), which avoid the kernel Gram matrix. Compare their validation results rather than expecting identical boundaries. SVC(kernel="linear") uses hinge loss with an unpenalized intercept. LinearSVC defaults to squared hinge loss and penalizes the intercept. SGDClassifier(loss="hinge") also leaves its intercept unpenalized, while using a mean-loss objective with alpha regularization. LinearSVC and SGDClassifier use different solvers and stopping rules from SVC.

Set random_state where the chosen solver or calibration procedure uses randomness. For imbalanced classes, compare class weights or resampling performed only within the training fold; oversampling before splitting can place copies of the same example in training and validation. When probabilities are required, compare SVC(probability=True) with an explicit procedure such as CalibratedClassifierCV using held-out probability metrics and calibration plots. An explicit wrapper can make the calibration protocol easier to control, but it is not guaranteed to improve probability estimates.

Data Requirements and Preprocessing

Feature scales affect the SVM's geometry and regularization. Changing the units of one input changes its contribution to an RBF distance and the penalty associated with an equivalent linear coefficient. This can distort a fit when the units are arbitrary, although a high-variance feature does not automatically make the model ignore every other feature. Standardization is a useful default for many numerical datasets; other representations, such as normalized sparse text features or a domain-specific kernel, may call for a different choice. For sparse inputs, StandardScaler(with_mean=False) scales features without centering; its default centering raises an error on sparse matrices. Fit any learned scaling statistics on the training fold only, and reuse them on validation and test inputs. Estimating them from held-out data would leak information into the fitted procedure.

Handle missing values using preprocessing supported by the chosen estimator. Fit the imputer, scaler, and SVM together within each training fold so that prediction uses the training statistics. For a custom kernel, symmetry and positive semidefiniteness must hold on every finite input collection. Negative training-Gram eigenvalues beyond numerical error reveal a failure of that matrix's PSD condition; nonnegative eigenvalues on one dataset do not prove global kernel validity. An invalid kernel can make the dual nonconcave, depending on its behavior on the feasible directions.

Common Pitfalls

Do not interpret SVM decision scores as probabilities. In the canonical binary formulation, a point with score ±2\pm2 lies at distance 2/∥w∥2/\|\mathbf{w}\| from the hyperplane when w≠0\mathbf{w}\ne\mathbf{0}. This is twice the canonical one-sided margin distance 1/∥w∥1/\|\mathbf{w}\|. Signed geometric distance is f(x)/∥w∥f(\mathbf{x})/\|\mathbf{w}\|. It does not imply odds or a fixed probability. A second issue is using an arbitrary similarity function as a kernel. The function must be symmetric and produce a positive-semidefinite Gram matrix on every finite input set. Logistic-style similarities σ(z⊤z′)\sigma(\mathbf{z}^\top\mathbf{z}') do not satisfy this requirement in general and can destroy the dual's concavity. Checking one training matrix can reveal a failure, but cannot prove that a function is a valid kernel on all inputs.

Oversampling before splitting can leak copies of observations across the training-validation boundary. Perform any resampling within training folds. Likewise, fit learned preprocessing within each training fold: changing measurement units can alter the regularization and kernel geometry, while sensible pre-existing scales may already suit the task. Defaults such as C=1 are baselines whose validation performance must be checked. Compare alternatives with comparable tuning budgets and use an untouched test set for the final performance estimate.

Computational Considerations

A full kernel Gram matrix contains n2n^2 entries, so explicitly storing it requires quadratic memory. Decomposition solvers such as libsvm can compute kernel entries as needed and retain a cache instead. Exact nonlinear kernel fitting can still become expensive as nn grows: feature dimension, kernel-evaluation cost, cache reuse, data geometry, and solver tolerance all affect runtime. Dense quadratic-programming steps can involve cubic-cost linear algebra, but that is not a universal bound on total SVM training time. Measure fitting time and memory for the intended data size; dedicated linear solvers are often preferable when a linear boundary is adequate.

For larger linear problems, consider LinearSVC or SGDClassifier(loss="hinge"), which avoid materializing the kernel matrix. Linear passes through a fixed feature representation can scale with the number of nonzero input entries; total training time also depends on convergence. For a nonlinear approximation, RBFSampler constructs random Fourier features for the RBF kernel, while Nystroem constructs a feature map using a subset of training points as landmarks. Fit a linear model on the transformed inputs and validate the approximation dimension as well as the model settings. For libsvm models, cache_size controls the kernel cache in megabytes, with a default of 200 MB in scikit-learn 1.8; it does not cap all training memory.

Performance and Deployment Considerations

Use cross-validation on the training data to select the model and evaluate the selected procedure on an untouched test split when one is available. Choose accuracy, F1, ROC AUC, or another metric to match class balance and the cost of errors. For a kernel model, the support-vector count helps estimate storage and prediction cost. A fraction near one indicates a dense support representation; it does not by itself identify a poor kernel or an excessive penalty. Inspect validation performance alongside the count. For regression, validation RMSE and MAE measure prediction error, while the support count describes the representation's sparsity.

Persist the complete prediction procedure: preprocessing, kernel choice and parameters, fitted coefficients and bias, support inputs for a nonlinear kernel expansion, and the class-label mapping for classification. A nonlinear kernel model typically evaluates a sum over its support vectors, so prediction cost grows with their number and the cost of each kernel evaluation. A linear model can instead store the combined vector w\mathbf{w} and predict without visiting the support set. Monitor input and score distributions and assess whether changes warrant retraining; batch SVC and SVR fits do not update themselves. If the downstream system uses calibrated probabilities, persist the fitted calibration procedure as well and reassess calibration on fresh data.

Summary

Support Vector Machines connect a geometric margin objective to convex optimization. For separable data, the hard-margin problem requires every functional margin to be at least one. The soft-margin problem relaxes that requirement using slack penalties. Eliminating those slacks gives the hinge-loss objective 12∥w∥2+C∑imax⁡(0,1−yif(xi))\tfrac12\|\mathbf{w}\|^2+C\sum_i\max(0,1-y_i f(\mathbf{x}_i)). This finite penalty allows violations rather than preserving the hard constraint. Dividing by nCnC gives a mean-loss objective with penalty λ∥w∥2/2\lambda\|\mathbf{w}\|^2/2, where λ=1/(nC)\lambda=1/(nC). Under that convention, larger CC means weaker relative regularization.

The Lagrangian view exposes a dual problem that depends on pairwise inner products. Replacing them by a valid PSD kernel gives a feature-space inner product and preserves concavity of the dual objective. Linear, appropriately parameterized polynomial, and RBF kernels are examples. Arbitrary similarities need not be valid, and checking one Gram matrix is not a proof for every possible input set. KKT complementarity sets the multiplier to zero for a point strictly beyond its margin hyperplane; the remaining support-vector terms determine the decision sum, although the support set may include all training examples.

Support Vector Regression uses an ε\varepsilon-insensitive loss that is zero for ∣r∣≤ε|r|\le\varepsilon and linear beyond the tube. Support vectors may lie on the tube edges as well as outside it, and their number is data dependent. This loss limits the influence of large response residuals relative to squared loss; it does not ensure robustness to high-leverage inputs or improved validation error. Choose suitable preprocessing, validate the relevant penalty and kernel settings, account for class imbalance when it matters, and assess calibration when probabilities are required. The examples also show a limit of the geometric intuition: a soft-margin optimum can be a constant classifier with w=0\mathbf{w}=0.

Quiz

Ready to test your understanding? Take this quick quiz to reinforce what you've learned about support vector machines and support vector regression.

Support Vector Machines and Support Vector Regression Quiz

Question 1 of 80 of 8 completed
In the canonical hard-margin SVM scale, what is the optimization objective?
Join the discussionAsk a question or share what you learned.

Comments

Add to the conversation

A question, a correction, or an example from your own work.

No comments yet. Be the first to share your thoughts!

A different angle
All writing
Machine Learning

Linear and Quadratic Discriminant Analysis

Build LDA and QDA classifiers from Gaussian class models and Bayes' rule, with covariance estimation, shrinkage, and NumPy implementations.

59 min read
Machine Learning

Naive Bayes

Learn how naive Bayes classifiers work: Bayes decision rule, Gaussian and multinomial event models, smoothing, log-sum-exp, and NumPy implementation.

64 min read
Machine Learning

k-Nearest Neighbors

Build kNN from scratch, covering distance metrics, majority voting, local averaging, feature scaling, distance weighting, and the curse of dimensionality.

56 min read

About the author

Reference

Citation details

Cite or share this article.

BIBTEXAcademic
@misc{brenndoerfer2026supportvector, author = {Michael Brenndoerfer}, title = {Support Vector Machines and Support Vector Regression}, year = {2026}, url = {https://mbrenndoerfer.com/writing/support-vector-machines-from-scratch}, organization = {mbrenndoerfer.com}, note = {Accessed: 2026-10-28} }
APAAcademic
Michael Brenndoerfer (2026). Support Vector Machines and Support Vector Regression. Retrieved from https://mbrenndoerfer.com/writing/support-vector-machines-from-scratch
MLAAcademic
Michael Brenndoerfer. "Support Vector Machines and Support Vector Regression." 2026. Web. October 28, 2026. <https://mbrenndoerfer.com/writing/support-vector-machines-from-scratch>.
CHICAGOAcademic
Michael Brenndoerfer. "Support Vector Machines and Support Vector Regression." Accessed October 28, 2026. https://mbrenndoerfer.com/writing/support-vector-machines-from-scratch.
HARVARDAcademic
Michael Brenndoerfer (2026) 'Support Vector Machines and Support Vector Regression'. Available at: https://mbrenndoerfer.com/writing/support-vector-machines-from-scratch (Accessed: October 28, 2026).
SimpleBasic
Michael Brenndoerfer (2026). Support Vector Machines and Support Vector Regression. https://mbrenndoerfer.com/writing/support-vector-machines-from-scratch
Newsletter

Stay up to date

Get new articles, book updates, and notes on AI and technology.

Unsubscribe at any time. Privacy policy