DEV Community

Devanshu Biswas
Devanshu Biswas

Posted on

One-Class SVM: Learn a Kernel Boundary Around Normal Data for Novelty Detection

Most anomaly detectors describe the normal data and flag whatever doesn't fit the description. The Elliptic Envelope fits one Gaussian ellipse; the Local Outlier Factor compares each point's local density to its neighbours'; the Isolation Forest counts how few random cuts isolate a point. The One-Class SVM does something different: it takes the max-margin idea from a regular SVM and turns it inward, learning a curved frontier that wraps the support of the data as tightly as it can — then calls anything outside a novelty. That boundary can be a ring, two islands, a crescent — shapes a single ellipse can't represent.

The decision function

With only "normal" examples and no anomalies to learn from, the model maps points through an RBF kernel K(x, y) = exp(−γ‖x − y‖²) — the kernel trick, so the infinite-dimensional feature map is never built — and produces a decision function of the form:

f(x) = Σᵢ αᵢ K(x, xᵢ) − ρ
Enter fullscreen mode Exit fullscreen mode

f(x) ≥ 0 is inside (normal), f(x) < 0 is outside (anomaly), and the boundary is the contour f = 0. The points that end up with αᵢ > 0 are the support vectors — the only ones that shape the frontier.

A didactic realization worth being honest about

The real one-class SVM (Schölkopf's formulation) finds a sparse set of weights αᵢ by solving a dual quadratic program with SMO: min ½ αᵀKα subject to Σα = 1 and the box 0 ≤ αᵢ ≤ 1/(νn). The demo behind this walkthrough does not run SMO. It keeps the identical decision-function form but takes the transparent SVDD / Parzen choice αᵢ = 1/n, so the raw score of each point is simply its RBF kernel density — high in the crowded core, low out on the fringe. This is a faithful didactic approximation, tuned so ν and γ behave exactly as the textbook says and every kernel contribution stays visible — not the exact sparse solve.

def rbf(a, b, g):
    dx, dy = a.x - b.x, a.y - b.y
    return math.exp(-g * (dx * dx + dy * dy))     # 1 when identical -> 0 when far

# SVDD / Parzen score of each point = its RBF kernel density
#   sᵢ = (1/n) Σⱼ K(xᵢ, xⱼ)      (uniform weight αⱼ = 1/n)
def density_scores(pts, gamma):
    return [sum(rbf(p, q, gamma) for q in pts) / len(pts) for p in pts]
Enter fullscreen mode Exit fullscreen mode

The ν-quantile offset, and the ν guarantee

Where you place ρ decides how many points fall outside. The beautiful property of ν is that it is both an upper bound on the fraction of outliers and a lower bound on the fraction of support vectors. The demo realizes that directly by setting ρ to the ν-quantile of the scores, so exactly ⌊ν·n⌋ points score below it and are flagged:

def choose_rho(scores, nu):
    s = sorted(scores)                             # ascending
    k_out = min(len(s) - 1, int(nu * len(s)))
    return s[k_out]                                # exactly k_out points below rho

def decision(x, pts, gamma, rho):                  # signed score at ANY point
    return sum(rbf(x, p, gamma) for p in pts) / len(pts) - rho
Enter fullscreen mode Exit fullscreen mode

Two knobs govern everything. ν sets the flagged fraction. γ is the RBF width: raise it and each point's influence decays fast, tightening the frontier and making it wigglier; lower it and the influence is broad, smoothing toward one round dome. The boundary itself is drawn by evaluating f on a grid and running marching squares on the f = 0 sign changes.

Where it sits

In practice you reach for scikit-learn, which wraps libsvm's SMO:

from sklearn.svm import OneClassSVM
oc = OneClassSVM(kernel="rbf", nu=0.1, gamma="scale")
oc.fit(X_train_normal)                 # trained on inliers only
labels = oc.predict(X_new)             # +1 inlier / -1 novelty
scores = oc.decision_function(X_new)   # signed distance to the boundary (f)
Enter fullscreen mode Exit fullscreen mode

Because it fits a boundary rather than a density or a distance, it wraps non-convex shapes the Elliptic Envelope cannot, and unlike the transductive LOF it is inductive — once fit, it scores brand-new points, which makes it a go-to for genuine novelty detection. The costs are the flip side of that power: two coupled knobs with no label to cross-validate against, real sensitivity to feature scaling and to contamination in the training set, and an O(n²)–O(n³) solve that keeps it a moderate-n tool.

Scatter your own data and watch the frontier breathe as you slide ν and γ: https://dev48v.infy.uk/ml/day58-one-class-svm.html

Top comments (0)