API Reference / algorithms / anomaly /

one_class_svm.py

One-Class SVM for novelty detection and anomaly detection.

Classes

OneClassSVMDetector

class algorithms.anomaly.one_class_svm.OneClassSVMDetector(Classifier)

One-Class Support Vector Machine for novelty and anomaly detection.

The One-Class SVM learns a decision boundary that encompasses the bulk of the normal data in a high-dimensional feature space. It identifies anomalies as points lying outside this boundary. It is particularly effective for novelty detection, where the model is trained primarily on normal instances.
Constructor
__init__(
    self,
    kernel: str = 'rbf',
    nu: float = 0.1,
    gamma: float | str = 'auto',
    degree: int = 3,
    coef0: float = 0.0,
    tol: float = 0.001,
    max_iter: int = 1000,
)

Overview

The algorithm works by mapping the input data into a high-dimensional feature space (using a kernel) and finding the hyperplane that best separates the data from the origin with a maximum margin:

  1. Map data to high dimensions via the selected kernel (e.g., RBF)
  2. Solve an optimization problem to find a "frontier" encompassing the data
  3. New points are checked against this frontier
  4. Points falling outside the frontier are labeled as anomalies
The intuition: By separating the data from the origin in a high-dimensional feature space, we capture the "support" of the distribution.

Theory

The One-Class SVM solves the following optimization problem:

\min_{w, \rho, \xi} \frac{1}{2}\|w\|^2 - \rho + \frac{1}{\nu n}\sum_{i=1}^n \xi_i

Subject to:

w^T\phi(x_i) \geq \rho - \xi_i, \quad \xi_i \geq 0
where:
  • w: Normal vector to the separating hyperplane
  • \rho: Offset from the origin
  • \nu (nu): Controls the trade-off between keeping data inside the frontier and the "smoothness" of the boundary
  • \phi: Non-linear mapping to a higher-dimensional space (defined by the kernel)
  • \xi_i: Slack variables allowing for points to lie outside the boundary
Score interpretation:
  • Positive score → Normal point (inside the decision boundary)
  • Negative score → Anomaly (outside the decision boundary)

Parameters

kernel
str = "rbf"

Kernel function used to map data to higher dimensions:

  • "linear": Linear kernel
  • "rbf": Radial Basis Function (Gaussian)
  • "poly": Polynomial kernel
  • "sigmoid": Sigmoid kernel
nu
float = 0.1
Upper bound on the fraction of training errors and a lower bound on the fraction of support vectors. Must be in the range (0, 1]. Roughly corresponds to the expected contamination rate.
gamma
float or "auto" = "auto"

Kernel coefficient for RBF, polynomial, and sigmoid kernels:

  • "auto": Uses 1 / n_features
  • float: User-defined positive coefficient
degree
int = 3
Degree of the polynomial kernel. Ignored for other kernels.
coef0
float = 0.0
Independent term in the polynomial and sigmoid kernel functions.
tol
float = 1e-3
Stopping tolerance on the maximal KKT violation, the gap between the largest and smallest gradient over the points still free to move.
max_iter
int = 1000
Hard cap on SMO iterations, where one iteration updates a single pair of multipliers. Pass 0 or a negative value for max(10000, 100 * n_samples), which is enough to reach tol on typical data.

Attributes

support_vectors_
np.ndarray
Points from the training set that define the decision boundary.
dual_coef_
np.ndarray
Coefficients (Lagrange multipliers) associated with the support vectors.
offset_
float
The learned offset (:math:`\rho`) of the decision function.
n_support_
int
Total number of support vectors found. At the optimum this is at least :math:`\nu` of the training set.
support_
np.ndarray of shape (n_support,)
Indices of the support vectors in the training data.
n_iter_
int
SMO iterations actually run before reaching tol.
gamma_
float
Actual gamma value used during the computation.
n_features_in_
int
Number of features observed during fit().

Notes

Solver: the \nu-formulation dual is solved by Sequential Minimal Optimization over the maximal-violating pair, the same working-set rule LIBSVM uses:

\min_{\alpha} \; \frac{1}{2} \alpha^T K \alpha \quad \text{s.t.} \quad 0 \leq \alpha_i \leq \frac{1}{\nu n}, \;\; \sum_i \alpha_i = 1

\nu acts through the box bound alone, which is what makes it an upper bound on the fraction of training points left outside the boundary and a lower bound on the support vector fraction. The iteration starts from a feasible point and is fully deterministic, so repeated fits on the same data give the same model without needing a seed.

Complexity:

  • Training: O(n^2) per iteration bound by the kernel matrix, O(n^2) memory
  • Prediction: O(n_{sv} \cdot p) where n_{sv} is the number of support vectors
When to use One-Class SVM:
  • Novelty detection (training set contains only/mostly normal samples)
  • High-dimensional data where non-linear boundaries are required
  • Complex data distributions that can be captured with kernels
  • When precise control over the "frontier" shape is needed via hyper-parameters
Limitations:
  • High sensitivity to hyper-parameters (especially nu and gamma)
  • Poor scalability to very large datasets (cubic training time in worst case)
  • Not natively robust to outliers in the training set (unlike robust covariance)
  • Interpretation of results in high-dimensional kernel space is difficult

References

Scholkopf2001
Schölkopf, B., Platt, J.C., Shawe-Taylor, J., Smola, A.J., and Williamson, R.C. (2001). Estimating the support of a high-dimensional distribution. Neural Computation, 13(7), pp. 1443-1471. DOI: 10.1162/089976601750264965
Tax2004
Tax, D.M. and Duin, R.P. (2004). Support vector data description. Machine learning, 54(1), pp. 45-66. DOI: 10.1023/B:MACH.0000008084.60811.49

Basic usage for novelty detection:

python
>>> from tuiml.algorithms.anomaly import OneClassSVMDetector
>>> import numpy as np
>>> 
>>> # Generate normal training data
>>> X_train = np.random.randn(100, 2)
>>> 
>>> # Fit the model on normal data
>>> clf = OneClassSVMDetector(nu=0.1, kernel="rbf", gamma="auto")
>>> clf.fit(X_train)
>>> 
>>> # Predict on new data (one normal, one anomaly)
>>> X_test = np.array([[0, 0], [10, 10]])
>>> predictions = clf.predict(X_test)
>>> print(predictions)
[ 1 -1]
>>> 
>>> # Get decision function scores
>>> scores = clf.decision_function(X_test)
>>> print(scores.round(2))
[ 0.08 -0.09]

Methods

get_parameter_schema (cls) -> Dict[str, Dict[str, Any]]

Return JSON Schema for algorithm parameters.

get_capabilities (cls) -> List[str]

Return supported capabilities.

get_complexity (cls) -> str

Return complexity analysis.

get_references (cls) -> List[str]

Return academic citations.

fit (self, X: np.ndarray, _y: Optional[np.ndarray]=None) -> 'OneClassSVMDetector'

Fit the One-Class SVM model.

Parameters
X
np.ndarray of shape (n_samples, n_features)
Training data.
_y
np.ndarray or None = None
Ignored. Present for API consistency.
Returns
self
OneClassSVMDetector
Fitted estimator.
decision_function (self, X: np.ndarray) -> np.ndarray

Compute decision function values.

Parameters
X
np.ndarray of shape (n_samples, n_features)
Input samples.
Returns
scores
np.ndarray of shape (n_samples,)
Decision function values. Negative values indicate anomalies.
predict (self, X: np.ndarray) -> np.ndarray

Predict if samples are inliers or outliers.

Parameters
X
np.ndarray of shape (n_samples, n_features)
Input samples.
Returns
predictions
np.ndarray of shape (n_samples,)
-1 for anomalies (outliers), 1 for normal (inliers).
score_samples (self, X: np.ndarray) -> np.ndarray

Alias for decision_function for compatibility.

Parameters
X
np.ndarray of shape (n_samples, n_features)
Input samples.
Returns
scores
np.ndarray of shape (n_samples,)
Decision function values.