什么是支持向量机?用于分类的支持向量机的完整介绍

2017年10月21日 由 yuxiangyu 发表 475576 0
支持向量机(SVM)是一个非常强大而多变的机器学习模型,能够执行线性或非线性的分类,回归,甚至异常值检测。它是机器学习中最流行的模型之一,任何对机器学习感兴趣的人都应该学习和使用它。SVM特别适用于复杂的中小型数据集分类。在这篇文章中,我们将探讨用于分类的SVM模型。

线性SVM


假设我们有两类数据,我们要使用SVM进行分类,如图所示:

支持向量机

这两个类别可以用直线(线性可分)轻松分离。左图显示了2个可能的线性分类器的决策边界。所有的SVM模型都是为了生成将数据进行很好分类的正确分割线(称为在更高维度中称为超平面)。在左图中,尽管红线也对数据进行了分类,但在新的数据实例中可能无法很好地执行。我们可以画出许多对这些数据进行分类的线,但是在所有这些线中,蓝线分隔数据最好。同样的蓝线显示在右图。这条线(超平面)不仅分离了两个类,还尽可能远离最接近的训练实例。你可以将SVM分类器视为在类之间拟合尽可能宽的街道(由右侧图上的平行虚线表示)。这被称最大间隔分类器。

这个最好的决策边界是由位于街道边缘的实例决定(或者称为“支持”)。这些实例称为支持向量。街道边缘的间距称为间隔(margin)。

支持向量机

软间隔分类器


如果我们严格要求我们的实例不得在“街道”上,并且修正街道的边缘,这就是所谓的硬间隔分类。而硬边缘分类有2个问题:

1)只有数据线性分离才有效。

2)对异常值太敏感。

支持向量机

在上面的数据分类图中,有一个蓝色的异常值。如果我们对该数据集应用硬间隔分类,我们将得到左边图所示的小间距的决策边界。为了避免这些问题,最好使用更弹性的模型。目的是在保持街道尽可能大和不允许实例过界之间找到一个良好的平衡(就是说会出现实例最终可能在街道中间甚至道路另一面的情况)。这称为软间隔分类。如果我们对该数据集应用软间隔分类,则我们将得到比硬间隔分类更大决策边界。如右图中所示。

非线性SVM


虽然线性SVM分类器能力不错,在许多情况下都工作的很好,但是许多数据集无法进行线性分离。处理非线性数据集的一个简单方法是添加更多的特征,比如多项式特征,有时这可以获得线性可分的数据集。通过生成多项式特征,我们将得到新的特征矩阵,它由具有小于或等于指定度的所有多项式组合的特征。下图是SVM使用多项式特征的示例。

支持向量机

核技巧


核(Kernel)是在一些特征空间中计算两个向量xx">和y点积的一种方法(特征空间可能有非常高的维度),所以核函数有时被称为“广义点积(generalized dot product)”。

假设我们有一个映射 φφ:RnRm">:Rnφ:RnRm">Rmφ:RnRm">向量Rn到特征空间Rm的映射。x和y的内积空间是φ(x)Tφ(y)。核是一个对应于这个点积k的函数,也就是k(x,y)=φ(x)Tφ(y)。核提供了在一些特征空间内计算点积的方法,你甚至可以不知道这个空间和φ是什么。

多项式核函数


添加多项式特征非常简单。但是低度多项式无法处理复杂的数据集,并且具有较高的多项式度它会产生大量的特征,让模型变得特别慢。在这种情况下,我们可以使用多项式核函数解决这个问题。多项式核函数公式如下:

支持向量机

d">d是多项式的度。

高斯核函数


高斯RBF(径向基函数)是SVM模型中使用的另一种流行的核函数。它的公式如下:
支持向量机

如果我们有如下的数据集,则高斯核函数非常有用。

支持向量机

超参数


在SVM模型中有2个重要的超参数。

C参数


C参数决定SVM分类器的边距宽度。C的值越越大分类器越严格,因此边距宽度小。对于较大的C值,如果该超平面更好地将所有训练点归类正确,则该模型将选择较小边距的超平面。相反,C的非常小的值将导致模型寻找更大的边距分离超平面,即使这个超平面错误的分类了更多的点。如果C值非常小,你会得到错误分类的实例,即使你的训练数据是线性可分的。

γ">γ参数


γ">γ参数定义了每个训练实例的影响能力。γ">γ参数对scikit-learn中的线性核函数是无效的。

使用scikit-learn实现


在这部分中,我们将使用scikit-learn来实现SVM。

线性核函数


import numpy as np
import pandas as pd
from matplotlib import style
from sklearn.svm import SVC
import matplotlib.pyplot as plt
plt.rcParams['figure.figsize'] = (12, 6)
style.use('ggplot')

# Import Dataset
data = pd.read_csv('data.csv', header=None)
X = data.values[:, :2]
y = data.values[:, 2]

# A function to draw hyperplane and the margin of SVM classifier
def draw_svm(X, y, C=1.0):
# Plotting the Points
plt.scatter(X[:,0], X[:,1], c=y)

# The SVM Model with given C parameter
clf = SVC(kernel='linear', C=C)
clf_fit = clf.fit(X, y)

# Limit of the axes
ax = plt.gca()
xlim = ax.get_xlim()
ylim = ax.get_ylim()

# Creating the meshgrid
xx = np.linspace(xlim[0], xlim[1], 200)
yy = np.linspace(ylim[0], ylim[1], 200)
YY, XX = np.meshgrid(yy, xx)
xy = np.vstack([XX.ravel(), YY.ravel()]).T
Z = clf.decision_function(xy).reshape(XX.shape)

# Plotting the boundary
ax.contour(XX, YY, Z, colors='k', levels=[-1, 0, 1],
alpha=0.5, linestyles=['--', '-', '--'])
ax.scatter(clf.support_vectors_[:, 0],
clf.support_vectors_[:, 1],
s=100, linewidth=1, facecolors='none')
plt.show()
# Returns the classifier
return clf_fit

clf_arr = []
clf_arr.append(draw_svm(X, y, 0.0001))
clf_arr.append(draw_svm(X, y, 0.001))
clf_arr.append(draw_svm(X, y, 1))
clf_arr.append(draw_svm(X, y, 10))

for i, clf in enumerate(clf_arr):
# Accuracy Score
print(clf.score(X, y))
pred = clf.predict([(12, 32), (-250, 32), (120, 43)])
print(pred)

支持向量机

支持向量机

支持向量机
0.992907801418
[1 0 1]
0.992907801418
[1 0 1]
1.0
[1 0 1]
1.0
[1 0 1]

你能看到相同超平面具有不同边距宽度。这取决于C超参数。

多项式核函数


import numpy as np
import pandas as pd
from matplotlib import style
from sklearn.svm import SVC
import matplotlib.pyplot as plt
plt.rcParams['figure.figsize'] = (12, 6)
style.use('ggplot')

data = pd.read_csv('polydata2.csv', header=None)
X = data.values[:, :2]
y = data.values[:, 2]

def draw_svm(X, y, C=1.0):
plt.scatter(X[:,0], X[:,1], c=y)
clf = SVC(kernel='poly', C=C)
clf_fit = clf.fit(X, y)

ax = plt.gca()
xlim = ax.get_xlim()
ylim = ax.get_ylim()

xx = np.linspace(xlim[0], xlim[1], 200)
yy = np.linspace(ylim[0], ylim[1], 200)
YY, XX = np.meshgrid(yy, xx)
xy = np.vstack([XX.ravel(), YY.ravel()]).T
Z = clf.decision_function(xy).reshape(XX.shape)

ax.contour(XX, YY, Z, colors='k', levels=[-1, 0, 1],
alpha=0.5, linestyles=['--', '-', '--'])
ax.scatter(clf.support_vectors_[:, 0],
clf.support_vectors_[:, 1],
s=100, linewidth=1, facecolors='none')
plt.show()
return clf_fit

clf = draw_svm(X, y)
score = clf.score(X, y)
pred = clf.predict([(-130, 110), (-170, -160), (80, 90), (-280, 20)])
print(score)
print(pred)

支持向量机
1.0
[0 1 0 1]

高斯核函数


import numpy as np
import pandas as pd
from matplotlib import style
from sklearn.svm import SVC
from sklearn.datasets import make_classification, make_blobs, make_moons
import matplotlib.pyplot as plt
plt.rcParams['figure.figsize'] = (12, 6)
style.use('ggplot')

X, y = make_moons(n_samples=200)

# Auto gamma equals 1/n_features
def draw_svm(X, y, C=1.0, gamma='auto'):
plt.scatter(X[:,0], X[:,1], c=y)
clf = SVC(kernel='rbf', C=C, gamma=gamma)
clf_fit = clf.fit(X, y)

ax = plt.gca()
xlim = ax.get_xlim()
ylim = ax.get_ylim()

xx = np.linspace(xlim[0], xlim[1], 200)
yy = np.linspace(ylim[0], ylim[1], 200)
YY, XX = np.meshgrid(yy, xx)
xy = np.vstack([XX.ravel(), YY.ravel()]).T
Z = clf.decision_function(xy).reshape(XX.shape)

ax.contour(XX, YY, Z, colors='k', levels=[-1, 0, 1],
alpha=0.5, linestyles=['--', '-', '--'])
ax.scatter(clf.support_vectors_[:, 0],
clf.support_vectors_[:, 1],
s=100, linewidth=1, facecolors='none')
plt.show()
return clf_fit

clf_arr = []
clf_arr.append(draw_svm(X, y, 0.01))
clf_arr.append(draw_svm(X, y, 0.1))
clf_arr.append(draw_svm(X, y, 1))
clf_arr.append(draw_svm(X, y, 10))

for i, clf in enumerate(clf_arr):
print(clf.score(X, y))

支持向量机

支持向量机

支持向量机

支持向量机
0.83
0.9
1.0
1.0

import numpy as np
import pandas as pd
from matplotlib import style
from sklearn.svm import SVC
from sklearn.datasets import make_gaussian_quantiles
import matplotlib.pyplot as plt
plt.rcParams['figure.figsize'] = (12, 6)
style.use('ggplot')

X, y = make_gaussian_quantiles(n_samples=200, n_features=2, n_classes=2, cov=3)

# Auto gamma equals 1/n_features
def draw_svm(X, y, C=1.0, gamma='auto'):
plt.scatter(X[:,0], X[:,1], c=y)
clf = SVC(kernel='rbf', C=C, gamma=gamma)
clf_fit = clf.fit(X, y)

ax = plt.gca()
xlim = ax.get_xlim()
ylim = ax.get_ylim()

xx = np.linspace(xlim[0], xlim[1], 200)
yy = np.linspace(ylim[0], ylim[1], 200)
YY, XX = np.meshgrid(yy, xx)
xy = np.vstack([XX.ravel(), YY.ravel()]).T
Z = clf.decision_function(xy).reshape(XX.shape)

ax.contour(XX, YY, Z, colors='k', levels=[-1, 0, 1],
alpha=0.5, linestyles=['--', '-', '--'])
ax.scatter(clf.support_vectors_[:, 0],
clf.support_vectors_[:, 1],
s=100, linewidth=1, facecolors='none')
plt.show()
return clf_fit

clf_arr = []
clf_arr.append(draw_svm(X, y, 0.1))
clf_arr.append(draw_svm(X, y, 1))
clf_arr.append(draw_svm(X, y, 10))
clf_arr.append(draw_svm(X, y, 100))

for i, clf in enumerate(clf_arr):
print(clf.score(X, y))

支持向量机

支持向量机

支持向量机

支持向量机
0.965
0.97
0.985
0.995

γ">γ参数对RBF SVM模型非常重要。在第一个例子中,低的γ">γ值导致了出现接近线性分类。

你可以在下面的链接中查看代码示例和数据集。

https://github.com/mubaris/studious-eureka
欢迎关注ATYUN官方公众号
商务合作及内容投稿请联系邮箱:bd@atyun.com
评论 登录
写评论取消
回复取消