【大数据专业】【超详细】支持向量机SVM——专治线性不可分

学习目标:

本篇博客包括以下三个基本内容:

1、支持向量机的核函数

2、不同核函数的SVM对比

3、支持向量机的gamma参数调节

(本次实验在Jupyter Notebook中运行)

基本原理:

  • 支持向量机(support vector machines, SVM)是一种二分类模型,它的基本模型是定义在特征空间上的间隔最大的线性分类器,间隔最大使它有别于感知机。
  • SVM还包括核技巧,这使它成为实质上的非线性分类器。
  • SVM的的学习策略就是间隔最大化,可形式化为一个求解凸二次规划的问题,也等价于正则化的合页损失函数的最小化问题。
  • SVM的的学习算法就是求解凸二次规划的最优化算法。

一、支持向量机SVM的核函数:

【结尾会附赠全部代码】

1、导入numpy以及画图工具

import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

2、导入支持向量机分类库

from sklearn.svm import SVC

3、导入数据集生成工具

from sklearn.datasets import make_blobs

4、生成100个具有两个特征的两分类点并展示出来

X,y = make_blobs(n_samples = 100,
                 n_features = 2,
                 centers = 2,
                 random_state = 6)
plt.scatter(X[:,0],X[:,1],c = y,s = 30,cmap = plt.cm.Paired)

显示为:
在这里插入图片描述
5、拆分训练集与测试集

from sklearn.model_selection import train_test_split
X_train,X_test,y_train,y_test = train_test_split(X,y,test_size = 0.3,random_state = 6)

6、创建一个线性内核的支持向量机模型

clf  = SVC(kernel = 'linear',C = 1000)

7、模型训练

clf.fit(X_train,y_train)

结果为:

SVC(C=1000, kernel='linear')

8、查看模型准确率

clf.score(X_test,y_test)

结果为:

1.0

9、查看支持向量个数(每类分别有多少个)

clf.n_support_

结果为:

array([2, 1])

10、查看支持向量的坐标

clf.support_vectors_

结果为:

array([[ 5.73005848, -4.19481136],
       [ 7.80996597, -4.80944368],
       [ 6.49868019, -7.13530714]])

11、绘制一个线性内核的SVM分类器(下面代码必须同时运行)

#结果可视化
plt.scatter(X_train[:,0],X_train[:,1],s = 120,c = y_train,cmap = plt.cm.spring,edgecolors = "k")
#建立图像坐标
ax = plt.gca()
xlim = ax.get_xlim()
ylim = ax.get_ylim()
#生成两个等差数列
xx = np.linspace(xlim[0],xlim[1],30)
yy = np.linspace(ylim[0],ylim[1],30)
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()

结果为:
在这里插入图片描述
结果分析:
从上面图,可以清晰地看到,在分类器两侧分别有两条虚线,那些正好压在虚线上的数据点,就是支持向量。而该实验使用的这种方法称为“最大边界间隔超平面"(Maximum Margin Separating Hyerplane)。指的是说中间这条实线(在高维数据中是一个超平面),和所有支持向量之间的距离,都是最大的。

如果将SVM的内核换成RBF,会发生什么变化呢?
【创建一个RBF内核的支持向量机模型】

clf = SVC(kernel = 'rbf',C = 1)
clf.fit(X_train,y_train)
#结果可视化
plt.scatter(X_train[:,0],X_train[:,1],s = 120,c = y_train,cmap = plt.cm.spring,edgecolors = "k")
#建立图像坐标
ax = plt.gca()
xlim = ax.get_xlim()
ylim = ax.get_ylim()
#生成两个等差数列
xx = np.linspace(xlim[0],xlim[1],30)
yy = np.linspace(ylim[0],ylim[1],30)
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()

结果为:在这里插入图片描述
通过调节参数C的大小来观察变化

  • C=0.1
    在这里插入图片描述

  • C = 10

在这里插入图片描述

  • C=1000
    在这里插入图片描述
    **当以RBF作为内核时,数据点之间的距离用下面的公式计算:
    在这里插入图片描述
    公式中的x1和x2代表两个不同的数据点,而||x1-x2||代表两个点之间的欧几里得距离。y(gamma)是用来控制RBF内核宽度的参数,也就是图中实线距离两条虚线的距离。

全部代码为:

import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
#导入支持向量机分类库
from sklearn.svm import SVC
#生成100个具有两个特征的两分类点
from sklearn.datasets import make_blobs
X,y = make_blobs(n_samples = 100,
                 n_features = 2,
                 centers = 2,
                 random_state = 6)
plt.scatter(X[:,0],X[:,1],c = y,s = 30,cmap = plt.cm.Paired)
#拆分训练集和测试集
from sklearn.model_selection import train_test_split
X_train,X_test,y_train,y_test = train_test_split(X,y,test_size = 0.3,random_state = 6)
#导入支持向量机分类库
from sklearn.svm import SVC
#实例化#创建一个线性内核的支持向量机模型
clf  = SVC(kernel = 'linear',C = 1000)
#模型训练
clf.fit(X_train,y_train)
#查看模型准确率
clf.score(X_test,y_test)
#查看支持向量个数(每类分别有多少个)
clf.n_support_
#查看支持向量的坐标
clf.support_vectors_
#(必须放在一块运行)
#结果可视化
plt.scatter(X_train[:,0],X_train[:,1],s = 120,c = y_train,cmap = plt.cm.spring,edgecolors = "k")
#建立图像坐标
ax = plt.gca()
xlim = ax.get_xlim()
ylim = ax.get_ylim()
#生成两个等差数列
xx = np.linspace(xlim[0],xlim[1],30)
yy = np.linspace(ylim[0],ylim[1],30)
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()

二、不同核函数的SVM对比:

1、导入红酒数据集

from sklearn.datasets import load_wine

2、定义一个函数用来画图

def make_meshgrid(x,y,h = 0.02):
    x_min,x_max = x.min() - 1, x.max() + 1
    y_min,y_max = y.min() - 1, y.max() + 1
    xx,yy = np.meshgrid(np.arange(x_min,x_max,h),
                        np.arange(y_min,y_max,h))
    return xx,yy

3、定义一个绘制等高线的函数

def plot_contours(ax,clf,xx,yy,**params):
    Z = clf.predict(np.c_[xx.ravel(),yy.ravel()])
    Z = Z.reshape(xx.shape)
    out = ax.contourf(xx,yy,Z,**params)
    return out

4、实例化红酒数据集

wine = load_wine()

5、选取数据集的前两个特征

X = wine.data[:, :2]
y = wine.target

6、导入支持向量机SVM模型

from sklearn import svm

7、正则化

C = 1.0#SVM的正则化参数
models = (svm.SVC(kernel = 'linear',C = C),
          svm.LinearSVC(C=C),
          svm.SVC(kernel = 'rbf',gamma = 0.7,C = C),
          svm.SVC(kernel = 'poly',degree = 3,C = C))
models = (clf.fit(X,y) for clf in models)

8、绘制不同核函数的支持向量机模型
(下面代码同时运行)

#设定图题
titles = ('SVC with linear kernel',
         'LinearSVC (linear kernel)',
         'SVC with RBF kernel',
         'SVC with polynomial (degree 3) kernel')
#设定一个子图形的个数和排列方式
fig,sub = plt.subplots(2,2)
plt.subplots_adjust(wspace = 0.4,hspace = 0.4)
#使用前面定义的函数进行画图
X0,X1 = X[:,0],X[:,1]
xx,yy = make_meshgrid(X0, X1)

for clf, title, ax in zip(models,titles,sub.flatten()):
    plot_contours(ax,clf,xx,yy,
                  cmap = plt.cm.plasma,alpha = 0.8)
    ax.scatter(X0,X1,c = y,cmap = plt.cm.plasma,s = 20,edgecolors = 'k')
    ax.set_xlim(xx.min(),xx.max())
    ax.set_ylim(yy.min(),yy.max())
    ax.set_xlabel("Feature 0")
    ax.set_ylabel("Feature 1")
    ax.set_xticks(())
    ax.set_yticks(())
    ax.set_title(title)
#将图型显示出来
plt.show()

图型显示为:
在这里插入图片描述
结果分析:

由图可知,线性内核的SVC与linearSVC得到的结果非常近似,但仍然有一点点差别。其中一个原因是linearSVC对L2范数进行最小化,而线性内核的SVC是对L1范数进行最小化。不论如何,linearSVC 和线性内核的SVC生成的决定边界都是线性的,在更高维数据集中将会是相交的超平面(请读者朋友自行想象)。

而RBF内核的SVC和polynomial内核的SVC分类器的决定边界则完全不是线性的,它们更加弹性。而决定了它们决定边界形状的,就是它们的参数。在polynomial内核的SVC中,起决定性作用的参数就是degree和正则化参数C,在本次实验中使用的degree为3,也就是对原始数据集的特征进行乘3次方操作。而在RBF内核的SVC中,起决定作用的是正则化参数C和参数gamma。

三、支持向量机的gamma参数调节:

#导入红酒数据集
from sklearn.datasets import load_wine

#定义一个函数用来画图
def make_meshgrid(x,y,h = 0.02):
    x_min,x_max = x.min() - 1, x.max() + 1
    y_min,y_max = y.min() - 1, y.max() + 1
    xx,yy = np.meshgrid(np.arange(x_min,x_max,h),
                        np.arange(y_min,y_max,h))
    return xx,yy
    
#定义一个绘制等高线的函数
def plot_contours(ax,clf,xx,yy,**params):
    Z = clf.predict(np.c_[xx.ravel(),yy.ravel()])
    Z = Z.reshape(xx.shape)
    out = ax.contourf(xx,yy,Z,**params)
    return out
    
#实例化
wine = load_wine()

#选取红酒数据集的前两个特征
X = wine.data[:, :2]
y = wine.target

#导入SVM库
from sklearn import svm

C = 1.0#SVM正则化参数
models = (svm.SVC(kernel = 'rbf',gamma = 0.1, C = C),
          svm.SVC(kernel = 'rbf',gamma = 1,C = C),
          svm.SVC(kernel = 'poly',gamma = 10,C = C))
models = (clf.fit(X,y) for clf in models)

#设定图题
titles = ('gamma = 0.1',"gamma = 1","gamma =10")

#设定子图形个数和排列
fig,sub = plt.subplots(1,3,figsize = (10,3))

X0,X1 = X[:,0],X[:,1]
xx,yy = make_meshgrid(X0, X1)

#使用定义好的函数进行画图
for clf, title, ax in zip(models,titles,sub.flatten()):
    plot_contours(ax,clf,xx,yy,
                  cmap = plt.cm.plasma,alpha = 0.8)
    ax.scatter(X0,X1,c = y,cmap = plt.cm.plasma,s = 20,edgecolors = 'k')
    ax.set_xlim(xx.min(),xx.max())
    ax.set_ylim(yy.min(),yy.max())
    ax.set_xlabel("Feature 0")
    ax.set_ylabel("Feature 1")
    ax.set_xticks(())
    ax.set_yticks(())
    ax.set_title(title)
#将图片显示出来
plt.show()

结果显示为:
在这里插入图片描述
结果分析:

由图可知,自左至右gamma值从0.1增加到10, gamma值越小,则RBF内核的直径越大,这样就会有更多的点被模型圈进决定边界中,所以决定边界也就越平滑,这时的模型也就越简单;而随着参数的增加,模型则更倾向于把每一个点都放到相应的决定边界中,这时模型的复杂度也相应提高了。所以gamma值越小,模型越倾向于欠拟合,而gamma值越大,则模型越倾向于出现过拟合的问题。

而至于正则化参数C,C值越小,模型就越受限,也就是说单个数据点对模型的影响越小,模型就越简单;而C值越大,每个数据点对模型的影响就越大,模型也会更加复杂。

  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值