Chapter 17 Support Vector Machines
We assume you have loaded the following packages:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
Below we load more as we introduce more.
Support Vector Machines are many ways similar to logistic regression, but unlike the latter, they can capture complex patterns. However, they are not interpretable.
17.1 Yin-Yang Pattern
We demonstrate the behavior of SVM-s using a 2-D dataset where data points are in a yin-yang pattern. The dots can be created as
= 400 # number of dots
N = np.random.normal(size=N)
X1 = np.random.normal(size=N)
X2 = np.column_stack((X1, X2))
X = X1 - X2
d = X1 + X2 - 1.7*np.sin(1.2*d) +\
y =0.5, size=N) > 0 np.random.normal(scale
The data looks like this:
= plt.scatter(X1, X2, c=y,
_ = 20,
s ="black")
edgecolors= plt.show() _
The images shows yellow and blue dots that are in an imperfect yin-yang pattern with a fuzzy boundary between the classes.
17.2 SVM in sklearn
SVM classifier is implemented by SVC
in sklearn.svm
. It accepts
number of arguments, the most important of which are kernel
to
select different kernels, and the corresponding parameters for
different kernels, e.g. degree
for polynomial degree and gamma
for
the radial scale parameter. Besides that, SVC
behaves in a similar
fashion like other sklearn models, see Section
@(linear-regression-sklearn) for more information. We can
define the model as:
from sklearn.svm import SVC
## /usr/lib/python3/dist-packages/scipy/__init__.py:146: UserWarning: A NumPy version >=1.17.3 and <1.25.0 is required for this version of SciPy (detected version 1.26.1
## warnings.warn(f"A NumPy version >={np_minversion} and <{np_maxversion}"
= SVC(kernel="linear")
m = m.fit(X, y) _
SVC(kernel='linear')In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
SVC(kernel='linear')
# on training data m.score(X, y)
SVC(kernel='linear')In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
SVC(kernel='linear')
Next, let’s demonstrate the decision boundary using linear, polynomial, and radial kernels. We predict the values on a grid using the following function:
def DBPlot(m, X, y, nGrid = 100):
= X[:, 0].min() - 1, X[:, 0].max() + 1
x1_min, x1_max = X[:, 1].min() - 1, X[:, 1].max() + 1
x2_min, x2_max = np.meshgrid(np.linspace(x1_min, x1_max, nGrid),
xx1, xx2
np.linspace(x2_min, x2_max, nGrid))= np.column_stack((xx1.ravel(), xx2.ravel()))
XX = m.predict(XX).reshape(xx1.shape)
hatyy =(10,10))
plt.figure(figsize= plt.imshow(hatyy, extent=(x1_min, x1_max, x2_min, x2_max),
_ ="auto",
aspect='none', origin='lower',
interpolation=0.3)
alpha0], X[:,1], c=y, s=30, edgecolors='k')
plt.scatter(X[:,
plt.xlim(x1_min, x1_max)
plt.ylim(x2_min, x2_max) plt.show()
SVC(kernel='linear')In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
SVC(kernel='linear')
Linear kernel is very similar to logistic regression, and shows a similar linear decision boundary:
= SVC(kernel="linear") # linear kernel does not have important parameters m
SVC(kernel='linear')In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
SVC(kernel='linear')
= m.fit(X, y) _
SVC(kernel='linear')In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
SVC(kernel='linear')
DBPlot(m, X, y)
SVC(kernel='linear')In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
SVC(kernel='linear')
The result is not too bad–it captures the yellow and purple side of the points, but it clearly misses the purple “bay” and the yellow “peninsula”.
Next, let’s replicate this with a polynomial kernel of degree 2:
= SVC(kernel="poly", degree=2) m
SVC(kernel='linear')In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
SVC(kernel='linear')
= m.fit(X, y) _
SVC(degree=2, kernel='poly')In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
SVC(degree=2, kernel='poly')
DBPlot(m, X, y)
SVC(degree=2, kernel='poly')In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
SVC(degree=2, kernel='poly')
m.score(X, y)
SVC(degree=2, kernel='poly')In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
SVC(degree=2, kernel='poly')
As you can see, polynomial(2) kernel is able to represent a blue band on a yellow background. It id debateable whether this is any better than what linear kernel can do, but one can easily see that such a band would be a good representation for other kind of data.
Next, replicate the above with degree-3 kernel:
= SVC(kernel="poly", degree=3) m
SVC(degree=2, kernel='poly')In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
SVC(degree=2, kernel='poly')
= m.fit(X, y) _
SVC(kernel='poly')In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
SVC(kernel='poly')
DBPlot(m, X, y)
SVC(kernel='poly')In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
SVC(kernel='poly')
m.score(X, y)
SVC(kernel='poly')In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
SVC(kernel='poly')
And finally with a radial kernel:
= SVC(kernel="rbf", gamma=1) m
SVC(kernel='poly')In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
SVC(kernel='poly')
= m.fit(X, y) _
SVC(gamma=1)In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
SVC(gamma=1)
DBPlot(m, X, y)
SVC(gamma=1)In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
SVC(gamma=1)
m.score(X, y)
SVC(gamma=1)In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
SVC(gamma=1)
Radial kernel replicates the wavy boundary very well with (training) accuracy above 0.9.
17.3 Find the best model
Finally, let’s manipulate a few more parameters to devise the best model. We do just a quick and dirty job here, as our task is to demonstrate the basics of SVM-s:
from sklearn.model_selection import train_test_split
SVC(gamma=1)In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
SVC(gamma=1)
= train_test_split(X, y) Xt, Xv, yt, yv
SVC(gamma=1)In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
SVC(gamma=1)
for degree in [2,3,4]:
for coef0 in [-1, 0, 1]:
= SVC(kernel="poly", degree=degree, coef0=coef0)
m = m.fit(Xt, yt)
_ print(f"degree {degree}, coef0 {coef0},"
+ f" accuracy: {m.score(Xv, yv)}")
SVC(coef0=1, degree=4, kernel='poly')In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
SVC(coef0=1, degree=4, kernel='poly')
The best results are with ceof0 = 1
. Here is the corresponding plot
with polynomial degree 2:
= SVC(kernel="poly", degree=3, coef0=1) m
SVC(coef0=1, degree=4, kernel='poly')In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
SVC(coef0=1, degree=4, kernel='poly')
= m.fit(X, y) _
SVC(coef0=1, kernel='poly')In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
SVC(coef0=1, kernel='poly')
DBPlot(m, X, y)
SVC(coef0=1, kernel='poly')In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
SVC(coef0=1, kernel='poly')
You can see that it picks up the boundary very well.