SVM sklearn python实现小示例

示例说明

本示例是一个简单的试验,甚至连数据集都不用额外准备,旨在加深对SVM和核函数的理解,并看看如何利用 scikit-learn 中的svm,
编译环境是 jupyter notebook, 可以通过安装 Anaconda,导入 scikit-learn 库可以很容易实现,github示例代码。本例中变没有用外部数据集,而是随机生成的点,大家在理解算法和 scikit-learn 熟练使用后,可以尝试导入有具体意义的数据集,看看SVM的效果。

概述

SVM_demo_with_sklearn.ipynb代码中主要分为两个部分

  • 线性 SVM 分类器
  • SVM 与核函数

Section 1: 线性 SVM 分类器

首先导入依赖包

%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
import seaborn; 
from sklearn.linear_model import LinearRegression
from scipy import stats
import pylab as pl
seaborn.set()

支持向量机是解决分类和回归问题非常强大的有监督学习算法。简单说来,linear的SVM做的事情就是在不同类别的“数据团”之间划上一条线,对线性可分集,总能找到使样本正确划分的分界面,而且有无穷多个,哪个是最优? 必须寻找一种最优的分界准则,SVM试图找到一条最健壮的线,什么叫做最健壮的线?其实就是离2类样本点最远的线。

from sklearn.datasets.samples_generator import make_blobs
X, y = make_blobs(n_samples=50, centers=2,
                  random_state=0, cluster_std=0.60)

xfit = np.linspace(-1, 3.5)
plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='spring')

# 其实随意给定3组参数,就可以画出3条不同的直线,但它们都可以把图上的2类样本点分隔开
for m, b, d in [(1, 0.65, 0.33), (0.5, 1.6, 0.55), (-0.2, 2.9, 0.2)]:
    yfit = m * xfit + b
    plt.plot(xfit, yfit, '-k')
    plt.fill_between(xfit, yfit - d, yfit + d, edgecolor='none', color='#AAAAAA', alpha=0.4)

plt.xlim(-1, 3.5);
from sklearn.svm import SVC
clf = SVC(kernel='linear')
clf.fit(X, y)

def plot_svc_decision_function(clf, ax=None):
    """Plot the decision function for a 2D SVC"""
    if ax is None:
        ax = plt.gca()
    x = np.linspace(plt.xlim()[0], plt.xlim()[1], 30)
    y = np.linspace(plt.ylim()[0], plt.ylim()[1], 30)
    Y, X = np.meshgrid(y, x)
    P = np.zeros_like(X)
    for i, xi in enumerate(x):
        for j, yj in enumerate(y):
            P[i, j] = clf.decision_function([xi, yj])
    # plot the margins
    ax.contour(X, Y, P, colors='k',
               levels=[-1, 0, 1], alpha=0.5,
               linestyles=['--', '-', '--'])

  • 分隔超平面:上述将数据集分割开来的直线叫做分隔超平面。
  • 超平面:如果数据集是N维的,那么就需要N-1维的某对象来对数据进行分割。该对象叫做超平面,也就是分类的决策边界。
  • 间隔:一个点到分割面的距离,称为点相对于分割面的距离。数据集中所有的点到分割面的最小间隔的2倍,称为分类器或数据集的间隔。
  • 最大间隔:SVM分类器是要找最大的数据集间隔。
  • 支持向量:离分割超平面最近的那些点

sklearn的SVM里面会有一个属性support_vectors_,标示“支持向量”,也就是样本点里离超平面最近的点,组成的。
咱们来画个图,把超平面和支持向量都画出来。

plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='spring')
plot_svc_decision_function(clf)
plt.scatter(clf.support_vectors_[:, 0], clf.support_vectors_[:, 1],
            s=200, facecolors='none');

可以用IPython的 interact 函数来看看样本点的分布,会怎么样影响超平面:

from IPython.html.widgets import interact

def plot_svm(N=100):
    X, y = make_blobs(n_samples=200, centers=2,
                      random_state=0, cluster_std=0.60)
    X = X[:N]
    y = y[:N]
    clf = SVC(kernel='linear')
    clf.fit(X, y)
    plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='spring')
    plt.xlim(-1, 4)
    plt.ylim(-1, 6)
    plot_svc_decision_function(clf, plt.gca())
    plt.scatter(clf.support_vectors_[:, 0], clf.support_vectors_[:, 1],
                s=200, facecolors='none')
    
interact(plot_svm, N=[10, 200], kernel='linear');

Section 2: SVM 与 核函数

对于非线性可切分的数据集,要做分割,就要借助于核函数了简单一点说呢,核函数可以看做对原始特征的一个映射函数,
不过SVM不会傻乎乎对原始样本点做映射,它有更巧妙的方式来保证这个过程的高效性。
下面有一个例子,你可以看到,线性的kernel(线性的SVM)对于这种非线性可切分的数据集,是无能为力的。

from sklearn.datasets.samples_generator import make_circles
X, y = make_circles(100, factor=.1, noise=.1)

clf = SVC(kernel='linear').fit(X, y)

plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='spring')
plot_svc_decision_function(clf);

然后强大的高斯核/radial basis function就可以大显身手了:

r = np.exp(-(X[:, 0] ** 2 + X[:, 1] ** 2))

from mpl_toolkits import mplot3d

def plot_3D(elev=30, azim=30):
    ax = plt.subplot(projection='3d')
    ax.scatter3D(X[:, 0], X[:, 1], r, c=y, s=50, cmap='spring')
    ax.view_init(elev=elev, azim=azim)
    ax.set_xlabel('x')
    ax.set_ylabel('y')
    ax.set_zlabel('r')

interact(plot_3D, elev=[-90, 90], azip=(-180, 180));

你在上面的图上也可以看到,原本在2维空间无法切分的2类点,映射到3维空间以后,可以由一个平面轻松地切开了。
而带rbf核的SVM就能帮你做到这一点:

clf = SVC(kernel='rbf')
clf.fit(X, y)

plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='spring')
plot_svc_decision_function(clf)
plt.scatter(clf.support_vectors_[:, 0], clf.support_vectors_[:, 1],
            s=200, facecolors='none');

关于SVM的总结:

  • 非线性映射是SVM方法的理论基础,SVM利用内积核函数代替向高维空间的非线性映射;
  • 对特征空间划分的最优超平面是SVM的目标,最大化分类边际的思想是SVM方法的核心;
  • 支持向量是SVM的训练结果,在SVM分类决策中起决定作用的是支持向量。因此,模型需要存储空间小,算法鲁棒性强;
  • 无任何前提假设,不涉及概率测度;
  • SVM算法对大规模训练样本难以实施
  • 用SVM解决多分类问题存在困难,经典的支持向量机算法只给出了二类分类的算法,而在数据挖掘的实际应用中,一般要解决多类的分类问题。可以通过多个二类支持向量机的组合来解决。主要有一对多组合模式、一对一组合模式和SVM决策树;再就是通过构造多个分类器的组合来解决。主要原理是克服SVM固有的缺点,结合其他算法的优势,解决多类问题的分类精度。如:与粗集理论结合,形成一种优势互补的多类问题的组合分类器。
  • SVM是O(n^3)的时间复杂度。在sklearn里,LinearSVC是可扩展的(也就是对海量数据也可以支持得不错), 对特别大的数据集SVC就略微有点尴尬了。不过对于特别大的数据集,你倒是可以试试采样一些样本出来,然后用rbf核的SVC来做做分类。

依赖的 packages

  • matplotlib
  • pylab
  • numpy
  • seaborn

others

  • 9
    点赞
  • 72
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值