Contents

3.2. Support Vector Machines

Support vector machines (SVMs) are a set of supervised learning methods used for classification, regression and outliers detection.

The advantages of Support Vector Machines are:

  • Effective in high dimensional spaces.
  • Still effective in cases where number of dimensions is greater than the number of samples.
  • Uses a subset of training points in the decision function (called support vectors), so it is also memory efficient.
  • Versatile: different Kernel functions can be specified for the decision function. Common kernels are provided, but it is also possible to specify custom kernels.

The disadvantages of Support Vector Machines include:

  • If the number of features is much greater than the number of samples, the method is likely to give poor performances.
  • SVMs do not directly provide probability estimates, these are calculated using five-fold cross-validation, and thus performance can suffer.

3.2.1. Classification

SVC, NuSVC and LinearSVC are classes capable of performing multi-class classification on a dataset.

../_images/plot_iris1.png

SVC and NuSVC are similar methods, but accept slightly different sets of parameters and have different mathematical formulations (see section Mathematical formulation). On the other hand, LinearSVC is another implementation of Support Vector Classification for the case of a linear kernel. Note that LinearSVC does not accept keyword ‘kernel’, as this is assumed to be linear. It also lacks some of the members of SVC and NuSVC, like support_.

As other classifiers, SVC, NuSVC and LinearSVC take as input two arrays: an array X of size [n_samples, n_features] holding the training samples, and an array Y of integer values, size [n_samples], holding the class labels for the training samples:

>>> from scikits.learn import svm
>>> X = [[0, 0], [1, 1]]
>>> Y = [0, 1]
>>> clf = svm.SVC()
>>> clf.fit(X, Y)
SVC(kernel='rbf', C=1.0, probability=False, degree=3, coef0=0.0, eps=0.001,
  cache_size=100.0, shrinking=True, gamma=0.5)

After being fitted, the model can then be used to predict new values:

>>> clf.predict([[2., 2.]])
array([ 1.])

SVMs decision function depends on some subset of the training data, called the support vectors. Some properties of these support vectors can be found in members support_vectors_, support_ and n_support:

>>> # get support vectors
>>> clf.support_vectors_
array([[ 0.,  0.],
       [ 1.,  1.]])
>>> # get indices of support vectors
>>> clf.support_ 
array([0, 1]...)
>>> # get number of support vectors for each class
>>> clf.n_support_ 
array([1, 1]...)

3.2.1.1. Multi-class classification

SVC and NuSVC implement the “one-against-one” approach (Knerr et al., 1990) for multi- class classification. If n_class is the number of classes, then n_class * (n_class - 1)/2 classifiers are constructed and each one trains data from two classes.

>>> X = [[0], [1], [2], [3]]
>>> Y = [0, 1, 2, 3]
>>> clf = svm.SVC()
>>> clf.fit(X, Y)
SVC(kernel='rbf', C=1.0, probability=False, degree=3, coef0=0.0, eps=0.001,
  cache_size=100.0, shrinking=True, gamma=0.25)
>>> dec = clf.decision_function([[1]])
>>> dec.shape[1] # 4 classes: 4*3/2 = 6
6

On the other hand, LinearSVC implements “one-vs-the-rest” multi-class strategy, thus training n_class models. If there are only two classes, only one model is trained.

>>> lin_clf = svm.LinearSVC()
>>> lin_clf.fit(X, Y)
LinearSVC(loss='l2', C=1.0, intercept_scaling=1, fit_intercept=True,
     eps=0.0001, penalty='l2', multi_class=False, dual=True)
>>> dec = lin_clf.decision_function([[1]])
>>> dec.shape[1]
4

See Mathematical formulation for a complete description of the decision function.

3.2.2. Regression

The method of Support Vector Classification can be extended to solve regression problems. This method is called Support Vector Regression.

The model produced by support vector classification (as described above) depends only on a subset of the training data, because the cost function for building the model does not care about training points that lie beyond the margin. Analogously, the model produced by Support Vector Regression depends only on a subset of the training data, because the cost function for building the model ignores any training data close to the model prediction.

There are two flavors of Support Vector Regression: SVR and NuSVR.

As with classification classes, the fit method will take as argument vectors X, y, only that in this case y is expected to have floating point values instead of integer values.

>>> from scikits.learn import svm
>>> X = [[0, 0], [2, 2]]
>>> y = [0.5, 2.5]
>>> clf = svm.SVR()
>>> clf.fit(X, y)
SVR(kernel='rbf', C=1.0, probability=False, degree=3, shrinking=True,
  eps=0.001, p=0.1, cache_size=100.0, coef0=0.0, nu=0.5, gamma=0.5)
>>> clf.predict([[1, 1]])
array([ 1.5])

3.2.3. Density estimation, outliers detection

One-class SVM is used for outliers detection, that is, given a set of samples, it will detect the soft boundary of that set so as to classify new points as belonging to that set or not. The class that implements this is called OneClassSVM

In this case, as it is a type of unsupervised learning, the fit method will only take as input an array X, as there are no class labels.

../_images/plot_oneclass1.png

3.2.4. Support Vector machines for sparse data

There is support for sparse data given in any matrix in a format supported by scipy.sparse. Classes have the same name, just prefixed by the sparse namespace, and take the same arguments, with the exception of training and test data, which is expected to be in a matrix format defined in scipy.sparse.

For maximum efficiency, use the CSR matrix format as defined in scipy.sparse.csr_matrix.

Implemented classes are SVC, NuSVC, SVR, NuSVR, OneClassSVM, LinearSVC.

3.2.5. Complexity

Support Vector Machines are powerful tools, but their compute and storage requirements increase rapidly with the number of training vectors. The core of an SVM is a quadratic programming problem (QP), separating support vectors from the rest of the training data. The QP solver used by this libsvm-based implementation scales between O(n_{features} \times n_{samples}^2) and O(n_{features} \times n_{samples}^3) depending on how efficiently the libsvm cache is used in practice (dataset dependent). If the data is very sparse n_{features} should be replaced by the average number of non-zero features in a sample vector.

Also note that for the linear case, the algorithm used in LinearSVC by the liblinear implementation is much more efficient than its libsvm-based SVC counterpart and can scale almost linearly to millions of samples and/or features.

3.2.6. Tips on Practical Use

  • Support Vector Machine algorithms are not scale invariant, so it is highly recommended to scale your data. For example, scale each attribute on the input vector X to [0,1] or [-1,+1], or standardize it to have mean 0 and variance 1. Note that the same scaling must be applied to the test vector to obtain meaningful results. See The CookBook for some examples on scaling.
  • Parameter nu in NuSVC/OneClassSVM/NuSVR approximates the fraction of training errors and support vectors.
  • If data for classification are unbalanced (e.g. many positive and few negative), set class_weight=’auto’ and/or try different penalty parameters C.
  • Specify larger cache size (keyword cache) for huge problems.
  • The underlying LinearSVC implementation uses a random number generator to select features when fitting the model. It is thus not uncommon, to have slightly different results for the same input data. If that happens, try with a smaller eps parameter.

3.2.7. Kernel functions

The kernel function can be any of the following:

  • linear: <x_i, x_j'>.
  • polynomial: (\gamma <x, x'> + r)^d. d is specified by keyword degree.
  • rbf (exp(-\gamma |x-x'|^2), \gamma > 0). \gamma is specified by keyword gamma.
  • sigmoid (tanh(<x_i,x_j> + r)).

Different kernels are specified by keyword kernel at initialization:

>>> linear_svc = svm.SVC(kernel='linear')
>>> linear_svc.kernel
'linear'
>>> rbf_svc = svm.SVC(kernel='rbf')
>>> rbf_svc.kernel
'rbf'

3.2.7.1. Custom Kernels

You can define your own kernels by either giving the kernel as a python function or by precomputing the Gram matrix.

Classifiers with custom kernels behave the same way as any other classifiers, except that:

  • Field support_vectors_ is now empty, only indices of support vectors are stored in support_
  • A reference (and not a copy) of the first argument in the fit() method is stored for future reference. If that array changes between the use of fit() and predict() you will have unexpected results.

3.2.7.1.1. Using python functions as kernels

You can also use your own defined kernels by passing a function to the keyword kernel in the constructor.

Your kernel must take as arguments two matrices and return a third matrix.

The following code defines a linear kernel and creates a classifier instance that will use that kernel:

>>> import numpy as np
>>> from scikits.learn import svm
>>> def my_kernel(x, y):
...     return np.dot(x, y.T)
...
>>> clf = svm.SVC(kernel=my_kernel)

3.2.7.1.2. Using the Gram matrix

Set kernel=’precomputed’ and pass the Gram matrix instead of X in the fit method.

3.2.8. Mathematical formulation

A support vector machine constructs a hyper-plane or set of hyper-planes in a high or infinite dimensional space, which can be used for classification, regression or other tasks. Intuitively, a good separation is achieved by the hyper-plane that has the largest distance to the nearest training data points of any class (so-called functional margin), since in general the larger the margin the lower the generalization error of the classifier.

../_images/plot_separating_hyperplane1.png

3.2.8.1. SVC

Given training vectors x_i \in R^n, i=1,..., l, in two classes, and a vector y \in R^l such that y_i \in {1,
-1}, SVC solves the following primal problem:

\min_ {w, b, \zeta} \frac{1}{2} w^T w + C \sum_{i=1, l} \zeta_i



\textrm {subject to } & y_i (w^T \phi (x_i) + b) \geq 1 - \zeta_i,\\
& \zeta_i \geq 0, i=1, ..., l

Its dual is

\min_{\alpha} \frac{1}{2} \alpha^T Q \alpha - e^T \alpha


\textrm {subject to } & y^T \alpha = 0\\
& 0 \leq \alpha_i \leq C, i=1, ..., l

where e is the vector of all ones, C > 0 is the upper bound, Q is an l by l positive semidefinite matrix, Q_ij \equiv K(x_i,
x_j) and \phi (x_i)^T \phi (x) is the kernel. Here training vectors are mapped into a higher (maybe infinite) dimensional space by the function \phi

The decision function is:

sgn(\sum_{i=1}^l y_i \alpha_i K(x_i, x) + \rho)

This parameters can be accessed through the members dual_coef_ which holds the product y_i \alpha_i, support_vectors_ which holds the support vectors, and intercept_ which holds the independent term -\rho :

References:

3.2.8.2. NuSVC

We introduce a new parameter \nu which controls the number of support vectors and training errors. The parameter \nu \in (0,
1] is an upper bound on the fraction of training errors and a lower bound of the fraction of support vectors.

3.2.9. Frequently Asked Questions

  • Q: Can I get the indices of the support vectors instead of the support vectors ?

    A: The underlying C implementation does not provide this information.

3.2.10. Implementation details

Internally, we use libsvm and liblinear to handle all computations. These libraries are wrapped using C and Cython.

References:

For a description of the implementation and details of the algorithms used, please refer to