支持向量机分类实战

简介: 对于机器学习者来说,SVM是非常重要的监督式学习模型之一,本文通过几个小例子,通俗的介绍了SVM的基本思想和关键信息,值得尝试。(文中源码)

更多深度文章,请关注云计算频道:https://yq.aliyun.com/cloud


支持向量机(SVM)是一个非常强大和灵活的机器学习模型,能够执行线性或非线性的分类,回归,甚至异常值检测。它是机器学习中最受欢迎的有监督学习模式之一,任何对ML感兴趣的人都应该对其有所了解,并且能够掌握其使用方法。SVM特别适用于复杂但数据集属于中小型的分类。

SVM主要的思想可以概括为两点:

1, 它是针对线性可分情况进行分析,对于线性不可分的情况,通过使用非线性映射算法将低维输入空间线性不可分的样本转化为高维特征空间使其线性可分,从而使得高维特征空间采用线性算法对样本的非线性特征进行线性分析成为可能。

2, 它基于结构风险最小化理论之上在特征空间中构建最优超平面,使得学习器得到全局最优化,并且在整个样本空间的期望以某种概率满足一定上界。

在这篇文章中,我们将探讨如何用Python实现分类的SVM模型。

线性SVM

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

f6eed87ca07eed76817b5c4443e74a542572004e

这两个类数据可以用直线(线性分离)轻松分离。左图显示了2个可能的线性分类器的决策边界。SVM模型其实就是关于生成正确的分界线(在较高维度称为Hyperplane)。在左图中,我们可以看到数据分类非常好,尽管红线对数据进行了分类,但在新的数据实例中可能无法很好地执行。我们可以画出许多对这些数据进行分类的线,但是在所有这些线中,蓝线可以分隔最多的数据。如果将相同的蓝线显示在右图,这条线(超平面)不仅分离了两个类,而且还保持了最远的相近的训练实例的距离。我们称之为大间距分类器(Large Margin Classification)。

这个最好的决策边界是由位于分界线边缘的实例确定(或“支持”)的。这些实例称为支持向量两条线边缘之间的距离称为边距

61dd8b9cfd293ed43fd572f3952df25ac04de949

间距分类器(soft Margin Classification)

如果我们严格把我们所用的例子放在这两条虚线上(如下图),并且在正确的一边,这就是所谓的硬间距分类,硬间距分类有2个问题。

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

2)对异常值非常敏感。

e226a227e8e1d8ef8aa0dbbedc4901c0b43ccd2c

在上面的数据类中,有一个蓝色的异常值。如果我们对该数据集应用硬间距分类器,我们将获得左边图所示的小边距的决策边界。为了避免这些问题,最好使用更灵活的模型。目的是在保持两条线之间距离尽可能大的情况下找到一个良好的平衡,并限制边际违规(即,最终在两条线中间的距离甚至错误的一面的情况),这称为软间距分类器。如果我们对该数据集应用软间距分类,我们将获得比硬间距分类更大的确定边界,这在右图中显示。

非线性SVM

虽然线性SVM分类器是有效的,并且在许多情况下令人惊奇地工作,但是许多数据集是不能接近线性分离。处理非线性数据集的一个简单方法是添加更多的特征,例如多项式特征,有时这可以导致线性可分离的数据集。通过生成多项式特征,我们将具有一个新特征矩阵,该特征矩阵由具有小于或等于指定度数的特征的所有多项式组合组成。以下图像是使用多项式特征进行SVM的示例。

19c54b957addfab4ce50dad4cf3a71250fb4ecbd

核心技巧

内核是计算两个向量X,Y的点积的一种方法和在某些(可能非常高的维度)特征空间中,这就是为什么内核函数有时被称为“广义点积分”。假设我们有一个映射:φ:RnRm,这使我们的矢量在Rn到某些特征空间Rm。然后数量积X,Y在这个空间里面是 φ(x)(y)。一个内核是一个函数K相当于数量积:k(x,y)=φ(x)Tφ(y)。内核提供了一种方法来计算某些特征空间中的点积,甚至不知道这个空间是什么。

多项式内核

添加多项式特征非常简单。但是低度多项式不能处理复杂的数据集,并且具有较高的多项式度将会产生大量的特征,使得模型太慢。在这种情况下,我们可以使用多项式内核来避免这个问题。多项式内核具有以下格式:

411f80c9f7cdfd654513d6da75622fcba1d25576

这里的D是多项式的次数。

高斯RBF内核

高斯RBF(径向基函数)是SVM模型中使用的另一种流行的内核方法。高斯内核具有以下格式:

xy)= eγx - y |2γ0

如果我们有如下的数据集,则RBF内核非常有用。

cb8c85fd05bd1267eeee75fbae88bd7f1e4220c7

超参数

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

1.C参数

C参数决定SVM分类器的边距宽度,而且它的分类器严格,因此边缘宽度较小。对于值大的C,如果该超平面更好地将所有训练点归类正确,则该模型将选择较小余量的超平面。相反,C的非常小的值将导致模型寻找更大的边缘从而分离超平面。对于非常小的C值,你应该得到错误分类的例子,通常即使你的训练数据是线性分离的。

2.γ参数

这个γ参数定义了每个训练示例,γ参数对于scikit-learning中的线性内核是无效的。

应用scikit实现SVM

在这部分中,我们将使用scikit学习来实现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)

dad4f5630cfc2b327c05dcdb16d8ad39de143612

bf65c0e50d26b9561b2d09d1d272651264fc5eb8

b1ddb0850d5b364710ba8bc9d2c029136699f495

b1ddb0850d5b364710ba8bc9d2c029136699f495

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)
a15b75cb6c6f0613c4b662d7511344428abeb048

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))

b0431d107d1435d854b8099916a3663847c87ef5

e9b2078285e58e8e3c128c11112a4146a9c73405

6589600713871785dfabba68a46fdc028bf02f61

f9db3ea19e77aa84f508133fdaa051f2c7b23902

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))

cf8f68b18a55a800082e7aa7bc9a4a6fb51ee882

866ca2f925fbbffbb6f8a67506b5bafe3bc0e211

7407b9af56642dd6fc29fd82b77c83b6279b4134

7bc598b34ce58826872bd42296e651f1fb345b5b

0.965
0.97
0.985
0.995

γ参数对RBF SVM模型非常重要。在第一个例子中,γ低值导致非线性分类几乎接近线性分类。

如果你对此感兴趣,你可以查看此Github Repo代码示例和数据集。


本文由北邮@爱可可-爱生活 老师推荐,阿里云云栖社区组织翻译。

文章原标题《Support Vector Machines for Classification

作者:Mubaris NK 

译者:虎说八道,审校。

文章为简译,更为详细的内容,请查看原文


相关文章
|
2月前
|
机器学习/深度学习 资源调度 算法
R语言逻辑回归与分类模型的深度探索与应用
【8月更文挑战第31天】逻辑回归作为一种经典的分类算法,在R语言中通过`glm()`函数可以轻松实现。其简单、高效且易于解释的特点,使得它在处理二分类问题时具有广泛的应用价值。然而,值得注意的是,逻辑回归在处理非线性关系或复杂交互作用时可能表现不佳,此时可能需要考虑其他更复杂的分类模型。
|
2月前
|
机器学习/深度学习 算法
【机器学习】支持向量机SVM、逻辑回归LR、决策树DT的直观对比和理论对比,该如何选择(面试回答)?
文章对支持向量机(SVM)、逻辑回归(LR)和决策树(DT)进行了直观和理论上的对比,并提供了在选择这些算法时的考虑因素,包括模型复杂度、损失函数、数据量需求、对缺失值的敏感度等。
47 1
|
3月前
|
机器学习/深度学习 数据采集 数据可视化
Python实现支持向量机SVM分类模型线性SVM决策过程的可视化项目实战
Python实现支持向量机SVM分类模型线性SVM决策过程的可视化项目实战
Python实现支持向量机SVM分类模型线性SVM决策过程的可视化项目实战
|
5月前
|
机器学习/深度学习 算法 C++
选择适合的SVM模型进行分类任务
选择SVM模型时需考虑数据线性可分性、问题类型(二分类或多分类)、优化算法(凸优化优势)及性能指标(如准确率、召回率)。数据非线性可分时可使用核技巧。针对多分类,有OVO、OVA和DAG方法。同时,利用交叉验证评估模型泛化能力。
36 4
|
5月前
|
机器学习/深度学习 算法
机器学习第8天:SVM分类
机器学习第8天:SVM分类
|
5月前
|
机器学习/深度学习 人工智能 自然语言处理
PyTorch搭建图卷积神经网络(GCN)完成对论文分类及预测实战(附源码和数据集)
PyTorch搭建图卷积神经网络(GCN)完成对论文分类及预测实战(附源码和数据集)
317 1
|
5月前
|
机器学习/深度学习 数据采集 算法
支持向量机(SVM)在分类问题中的表现与优化方法
支持向量机(SVM)在分类问题中的表现与优化方法
309 1
|
机器学习/深度学习
【阿旭机器学习实战】【21】通过SVM分类与回归实战案例,对比支持向量机(SVM)3种SVM不同核函数
【阿旭机器学习实战】【21】通过SVM分类与回归实战案例,对比支持向量机(SVM)3种SVM不同核函数
【阿旭机器学习实战】【21】通过SVM分类与回归实战案例,对比支持向量机(SVM)3种SVM不同核函数
|
机器学习/深度学习 传感器 数据采集
【SVM分类】基于支持向量机的数据分类预测(libsvm)附matlab代码
【SVM分类】基于支持向量机的数据分类预测(libsvm)附matlab代码
|
机器学习/深度学习 存储 算法
机器学习算法(四): 基于支持向量机的分类预测(SVM)
机器学习算法(四): 基于支持向量机的分类预测(SVM)