Support Vector Machines and Support Vector Regression
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 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
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 -insensitive loss. Residuals with magnitude at most 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 -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 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 ; 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 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 and a bias , and the signed decision value is
where:
- : the normal vector of the hyperplane, which fixes its orientation
- : the input point being classified
- : the bias term, which shifts the hyperplane away from the origin
- : 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 . For a nonzero normal vector, multiplying and 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 to the decision hyperplane is
where:
- : the normal vector of the hyperplane
- : the query point whose distance we measure
- : the bias term
- : the Euclidean length of the normal vector
This expression exposes an important scaling issue: multiplying and by the same positive constant leaves the hyperplane and every perpendicular distance unchanged, because the numerator and denominator scale together. The unnormalized decision values and functional margins do scale by that constant. The length therefore becomes a measure of margin width only after we fix the functional-margin scale. Here is the Euclidean length of the normal vector; in the canonical hard-margin scale, the two margin hyperplanes have separation .
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 and . Their perpendicular separation is , with each one a distance from the decision hyperplane. Maximizing this width is equivalent to minimizing , or . 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:
where:
- : the objective being minimized, equivalent to maximizing the margin
- : the label of the -th training example
- : the -th training input
- : the signed decision value of the -th example
- : the constraint that every point lies on or beyond its margin boundary
The quantity
is the functional margin of the -th example. In the canonical hard-margin optimum, support vectors have , while points with lie beyond the corridor. In a soft-margin fit, 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:
where:
- : the functional margin of the -th training example
- : the amount by which the functional margin falls short of 1
The maximum with zero clamps the loss at zero, so points with 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:
where:
- : the margin term, which shrinks as the margin widens
- : the penalty parameter controlling the exchange rate between margin width and training error
- : the hinge loss of the -th example
- : the sum over all training examples
The constant sets the exchange rate between weight norm and training hinge loss. On a fixed dataset with the same kernel and penalty convention, increasing cannot increase the optimized total hinge loss, while the optimized squared weight norm cannot decrease. Either quantity can stay unchanged over a range of , 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 :
where:
- : the regularized hinge-loss objective being minimized
- : the set of points currently violating the margin, i.e. those with active hinge loss
- : the exchange rate between margin width and training error
These expressions choose the zero hinge subgradient at points with . At such a kink, any multiple with is allowed for the weight part of the hinge term, with the corresponding for the bias. Strict margin violators have the full hinge contribution, while points with 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 as an explicit variable and minimizing over , , and 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:
where:
- : the slack for the -th example, measuring how far it violates the margin
- : the margin term
- : the total violation penalty, scaled by
- : the relaxed margin constraint, allowing the -th example to fall short of the margin by at most
At any optimum, the slacks are pinned down by the KKT conditions:
where:
- : the optimal slack for the -th example
- : the functional margin of the -th example
- : 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 for the margin constraints and for the nonnegativity constraints. The Lagrangian is
where:
- : the primal weight vector and bias
- : the slack for the -th example, measuring how far it violates the margin
- : the Lagrange multiplier for the -th margin constraint
- : the Lagrange multiplier for the nonnegativity constraint
Setting derivatives to zero gives three structural facts. First, yields the weight as a linear combination of training points,
where:
- : the Lagrange multiplier for the -th margin constraint
- : the label of the -th training example
- : the -th training input
- : the sum over all training examples
This is the first sign that the solution may be sparse: any point with contributes nothing to the weight vector. Second, yields the balance condition
where:
- : the Lagrange multiplier for the -th margin constraint
- : the label of the -th training example
- : the sum over all training examples
Third, yields , so eliminating gives the box constraint
Substituting the three equations back into leaves only behind:
where:
- : the dual multiplier for the -th margin constraint, bounded in
- : the upper bound on each multiplier
- : the pairwise inner product between training examples
The dual problem is a convex quadratic program: the objective is a concave quadratic in 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 and the balance condition , its dependence on the training input vectors is only through pairwise inner products . The decision function becomes
where:
- : the input point whose decision value we compute
- : the dual multiplier of the -th training example
- : the bias recovered from the KKT conditions
- : the inner product between the -th training point and the query point
The KKT complementarity conditions require whenever . A point with lies exactly on its margin hyperplane; a point with a strict violation has . At equality , the multiplier can include either endpoint, so touching the margin does not by itself prove . 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 and let
the soft-margin objective becomes
Here the loss is averaged over the examples. Under this convention, : increasing reduces the relative strength of the L2 penalty. For a fixed training problem, the optimized total hinge loss cannot increase as 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 . Larger and larger Ridge-style 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 , we can replace it with a symmetric function that corresponds to an inner product in some feature space , possibly infinite-dimensional:
where:
- : the kernel function, symmetric in its two arguments
- : two input examples
- : 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: . A nonlinear kernel need not provide a weight vector in the original input coordinates. The decision function is:
where:
- : the dual multiplier of the -th training example
- : the label of the -th training example
- : the kernel similarity between the -th training point and the query point
- : the bias recovered from the KKT conditions
We can now fit nonlinear functions in the original input space without explicitly computing . This is the kernel trick. Three useful kernel examples are:
- Linear kernel, , which recovers the linear soft-margin formulation.
- Polynomial kernel, , with positive integer and . When , its feature map contains scaled monomials of degrees zero through ; when and , it contains only degree- monomials.
- Radial basis function (RBF) kernel, , with . Similarity falls to at Euclidean separation , so this is its characteristic distance scale.
A real-valued kernel is valid when it is symmetric and its Gram matrix 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 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 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 makes similarity more local, which can permit a more variable boundary when is large enough; it does not by itself force memorization. A smaller makes similarities vary more slowly. For fixed , taking 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 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 . The idea is to build a tube of half-width along the fitted function and ignore residuals smaller than . The loss is symmetric and piecewise linear:
where:
- : the residual for a training example, i.e. the difference between the observed target and the predicted value
- : the half-width of the insensitive tube
- : the amount by which the residual exceeds the tube
- : 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, , and one for errors below, :
where:
- : the primal weight vector and bias
- : the slack for residuals above the tube ()
- : the slack for residuals below the tube ()
- : the penalty controlling how strongly residuals outside the tube are penalized
- : the half-width of the insensitive tube
The dual has two multiplier families . With , stationarity in the unpenalized bias gives , and stationarity in the weight gives . Its objective is
Here is the signed coefficient of training example , and the term penalizes the total multiplier mass in the dual maximization. An active tube constraint can still have zero multiplier. A PSD kernel makes this objective concave. The prediction is
where:
- : the dual multiplier for the constraint
- : the dual multiplier for the constraint
- : the kernel similarity between the -th training point and the query point
- : the bias recovered from the KKT conditions
Complementarity explains where nonzero coefficients can occur. For , a point strictly inside the tube has . A point on either edge may have a nonzero multiplier, while a point strictly outside has the corresponding multiplier at . Thus only points on or outside the tube can contribute, but their number need not be small. The tube half-width controls which residuals have zero loss, and 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 , the loss becomes absolute error, and the prediction still uses the net coefficient .
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 ; when , its signed geometric distance is in the model's feature space. Neither quantity is automatically a probability. Validate the relevant hyperparameters, including , kernel settings such as , and 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- 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 and . We map 0 to and 1 to when calculating functional margins.
PythonIn [3]Expand
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]Expand

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]Expand
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.0VisualizationOut [6]Expand

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 , where and . All three approach zero for very confident correct predictions, but the hinge loss transitions sharply at ; its flat region for 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]Expand
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]Expand

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]Expand
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]Expand


ConsoleOut [11]Expand
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 -insensitive loss is zero for 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]Expand
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]Expand

An SVR fit shows the tube explicitly. The band of width 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]Expand
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]Expand

Example
Two points suffice to work the margin calculation by hand. Let
where:
- : the two training inputs
- : their corresponding labels
The hard-margin problem for these two points is
We can prove the symmetry rather than assume it. Let . The two constraints imply , while , with equality only when . Hence the objective is at least . Equality is attained by and , proving global optimality. At this solution both margin constraints are tight:
Both equations reduce to . Under the symmetry assumption we find , so and . The margin width is
and the decision boundary is the line .
To connect this back to the dual, let be the multipliers. The KKT stationarity condition gives
Since , stationarity requires . The balance condition gives . These hard-margin multipliers are feasible for the soft-margin box constraints when , so the same zero-slack solution is optimal there. For , the dual optimum has and . Choosing then gives both points functional margin . In fact every 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 , we can check strong duality. Its primal objective is
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
so the cross term carries a negative label product , and the negative inner product makes the product positive. Thus
and the dual objective equals
where:
- : the optimal dual multipliers from the stationarity condition
- : the labels and
- : the pairwise inner products, and
- : the value of the double sum computed above
The dual objective value matches the primal value , which is consistent with strong duality.
Now consider a slightly harder case that exercises the soft margin. Add a third point with . Keep the original candidate and ; rescaling it would change the functional margins used by the objective. For the third point,
Its smallest feasible slack at this candidate is therefore
The original two points still have zero slack, so this candidate has objective . 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 , the exact soft-margin optimum is the constant classifier
It predicts the negative class for all three points, pays hinge loss two for the positive point, and has objective . We can prove optimality using the dual multipliers
They satisfy the box constraints and , and they give
The dual objective is consequently , matching the primal value. A feasible primal value matching a feasible dual value establishes global optimality.
Here changes the objective value without changing the fitted classifier. The usual margin-versus-loss tradeoff does not promise that the boundary moves whenever changes. Since , this constant solution has no separating hyperplane with a finite margin width ; 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]Expand
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, bWe 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]Expand
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 , and the count of hinge-active examples. The count records strict margin violations, , at the current iterate. It includes misclassified points as well as correctly classified points too close to the boundary.
ConsoleOut [18]Expand
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 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]Expand
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_.sizeConsoleOut [20]Expand
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 , 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]Expand
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]Expand
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 , 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]Expand
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]Expand

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 -insensitive regressor, usingC, the selected kernel's settings, andepsilon. Theclass_weightparameter belongs toSVC; both estimators acceptsample_weightinfitto rescale individual violation penalties.decision_function(X): in the binary example, returns the score . Positive scores select the positive class. For a nonzero linear weight vector, divide by to obtain signed perpendicular distance. For multiclassSVC, training uses one-vs-one classifiers; the defaultdecision_function_shape="ovr"converts their outputs into one score per class. Scores are not calibrated probabilities.predict(X): returns class labels forSVCand continuous predictions forSVR.predict_proba(X): forSVC, enableprobability=Truebefore 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 frompredict(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 , ; largerCmeans 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 . Tune it jointly withC; taking it to zero at fixedCdoes 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. Atepsilon=0the loss is absolute error, rather than squared error.class_weight: changes the class-specific violation penalties inSVC. 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 . 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 through 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 lies at distance from the hyperplane when . This is twice the canonical one-sided margin distance . Signed geometric distance is . 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 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 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 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 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 . This finite penalty allows violations rather than preserving the hard constraint. Dividing by gives a mean-loss objective with penalty , where . Under that convention, larger 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 -insensitive loss that is zero for 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 .
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
Join the discussionAsk a question or share what you learned.
Keep exploring
Reference
Citation details
Cite or share this article.

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!