[机器学习]支持向量机svm

文章目录

  • 一、支持向量机
    • 1、简介
    • 2、线性可分支持向量机
      • (1)间隔最大化和支持向量
      • (2)对偶问题
    • 3、非线性支持向量机和核函数
    • 4、线性支持向量机(软间隔支持向量机)与松弛变量
      • (1)线性支持向量机
      • (2)对偶问题
  • 二、对月亮数据集进行SVM训练
    • 1、线性核
    • 2、多项式核
    • 3、高斯核
  • 三、对鸢尾花数据集进行SVM训练
    • 1、线性核
    • 2、多项式核
    • 3、高斯核
  • 参考
  • 第八次作业另一篇博客及作业文件

一、支持向量机

1、简介

支持向量机(support vector machines)是一种二分类模型,它的目的是寻找一个超平面来对样本进行分割,分割的原则是间隔最大化,最终转化为一个凸二次规划问题来求解。由简至繁的模型包括:

  • 当训练样本线性可分时,通过硬间隔最大化,学习一个线性可分支持向量机;
  • 当训练样本近似线性可分时,通过软间隔最大化,学习一个线性支持向量机;
  • 当训练样本线性不可分时,通过核技巧和软间隔最大化,学习一个非线性支持向量机;

2、线性可分支持向量机

(1)间隔最大化和支持向量

如果一个线性函数能够将样本分开,称这些数据样本是线性可分的。那么什么是线性函数呢?其实很简单,在二维空间中就是一条直线,在三维空间中就是一个平面,以此类推,如果不考虑空间维数,这样的线性函数统称为超平面。我们看一个简单的二维空间的例子,O代表正类,X代表负类,样本是线性可分的,但是很显然不只有这一条直线可以将样本分开,而是有无数条,我们所说的线性可分支持向量机就对应着能将数据正确划分并且间隔最大的直线。
[机器学习]支持向量机svm_第1张图片
下面我们开始计算间隔,其实间隔就等于两个异类支持向量的差在 w 上的投影
在这里插入图片描述
在这里插入图片描述
推出:
在这里插入图片描述
代入公式(4)中可以得到:
在这里插入图片描述
至此,我们求得了间隔,SVM的思想是使得间隔最大化,也就是:
在这里插入图片描述
相当于最小化 ||w||,为了计算方便,将公式(6)转化成如下:在这里插入图片描述
公式(7)即为支持向量机的基本型。

(2)对偶问题

公式(7)本身是一个凸二次规划问题,可以使用现有的优化计算包来计算,但我们选择更为高效的方法。对公式(7)使用拉格朗日乘子法得到其对偶问题,该问题的拉格朗日函数可以写为:
在这里插入图片描述
公式(8)分别对 w 和 b求偏导:
[机器学习]支持向量机svm_第2张图片
令其分别为0,可以得到:
[机器学习]支持向量机svm_第3张图片将公式(9)(10)代入公式(8),可得:
[机器学习]支持向量机svm_第4张图片
此时,原问题就转化为以下仅关于 $\alpha $ 的问题:
[机器学习]支持向量机svm_第5张图片
解出 $\alpha $ 之后,根据公式(9)可以求得 w , 进而求得 b,可以得到模型:
在这里插入图片描述
上述过程的KKT条件为:
[机器学习]支持向量机svm_第6张图片
这里显示出了支持向量机的重要特征:当训练完成后,大部分样本都不需要保留,最终模型只与支持向量有关。

3、非线性支持向量机和核函数

对于非线性问题,线性可分支持向量机并不能有效解决,要使用非线性模型才能很好地分类。先看一个例子,如下图,很显然使用直线并不能将两类样本分开,但是可以使用一条椭圆曲线(非线性模型)将它们分开。非线性问题往往不好求解,所以希望能用解线性分类问题的方法求解,因此可以采用非线性变换,将非线性问题变换成线性问题。
[机器学习]支持向量机svm_第7张图片
对于这样的问题,可以将训练样本从原始空间映射到一个更高维的空间,使得样本在这个空间中线性可分,如果原始空间维数是有限的,即属性是有限的,那么一定存在一个高维特征空间是样本可分,于是有最小化函数:
在这里插入图片描述
其对偶问题为:
[机器学习]支持向量机svm_第8张图片
求解后得到:

[机器学习]支持向量机svm_第9张图片
这里的函数 κ ( x i , x j ) 就是核函数,在实际应用中,通常人们会从一些常用的核函数里选择(根据样本数据的不同,选择不同的参数,实际上就得到了不同的核函数),下面给出常用的核函数:
-线性核:
在这里插入图片描述
-多项式核(d是多项式的次数,d=1是退化为线性核):
在这里插入图片描述
-高斯核(σ>0):

在这里插入图片描述
-拉普拉斯核(σ>0):
在这里插入图片描述
-sigmiod核(β > 0,θ>0):

在这里插入图片描述
此外,核函数也可以通过组合得到,在此不再赘述。

4、线性支持向量机(软间隔支持向量机)与松弛变量

(1)线性支持向量机

在前面的讨论中,我们假设训练样本在样本空间或者特征空间中是线性可分的,但在现实任务中往往很难确定合适的核函数使训练集在特征空间中线性可分,退一步说,即使瞧好找到了这样的核函数使得样本在特征空间中线性可分,也很难判断是不是由于过拟合造成。
线性不可分意味着某些样本点 ( x i , y i )不能满足间隔大于等于1的条件,样本点落在超平面与边界之间。为解决这一问题,可以对每个样本点引入一个松弛变量 ξ i ≥ 0 ,使得间隔加上松弛变量大于等于1,这样约束条件变为:
在这里插入图片描述
同时,对于每一个松弛变量 ξ i ≥ 0,支付一个代价 ξ i ≥ 0,目标函数变为:
在这里插入图片描述
有了公式(21),可以和线性可分支持向量机一样考虑线性支持向量机的学习过程,此时,线性支持向量机的学习问题变成如下凸二次规划问题的求解(原始问题):

在这里插入图片描述

(2)对偶问题

与线性可分支持向量机的对偶问题解法一致,公式(22)的拉格朗日函数为:
在这里插入图片描述
其中 α i ≥ 0 , μ i ≥ 0 是拉格朗日乘子。

令 L ( w , b , α , ξ , μ ) 对 $w,b,\xi $的偏导数为0可得如下:
[机器学习]支持向量机svm_第10张图片
将公式(24)(25)(26)代入公式(23)得对偶问题:
[机器学习]支持向量机svm_第11张图片
解出 $\alpha $ 之后,根据公式(9)可以求得 w , 进而求得 b,可以得到模型:
在这里插入图片描述
上述过程的KKT条件为:
[机器学习]支持向量机svm_第12张图片

二、对月亮数据集进行SVM训练

# 边界绘制函数
import numpy as np
from matplotlib.colors import ListedColormap
def plot_decision_boundary(model,axis):
    x0,x1=np.meshgrid(
        np.linspace(axis[0],axis[1],int((axis[1]-axis[0])*100)).reshape(-1,1),
        np.linspace(axis[2],axis[3],int((axis[3]-axis[2])*100)).reshape(-1,1))
    # meshgrid函数是从坐标向量中返回坐标矩阵
    x_new=np.c_[x0.ravel(),x1.ravel()]
    y_predict=model.predict(x_new)#获取预测值
    zz=y_predict.reshape(x0.shape)
    custom_cmap=ListedColormap(['#EF9A9A','#FFF59D','#90CAF9'])
    plt.contourf(x0,x1,zz,cmap=custom_cmap)
from sklearn import datasets   #导入数据集
data_x,data_y = datasets.make_moons(n_samples=100, shuffle=True, noise=0.1, random_state=None)#生成月亮数据集
from sklearn.preprocessing import StandardScaler
scaler=StandardScaler()# 标准化
data_x = scaler.fit_transform(data_x)#计算训练数据的均值和方差
import matplotlib.pyplot as plt  
plt.scatter(data_x[data_y==0,0],data_x[data_y==0,1])
plt.scatter(data_x[data_y==1,0],data_x[data_y==1,1])
plt.show()

[机器学习]支持向量机svm_第13张图片

1、线性核

from sklearn.svm import LinearSVC
liner_svc=LinearSVC(C=1e9,max_iter=100000)#线性svm分类器,iter是迭达次数
liner_svc.fit(data_x,data_y)
#画图并显示参数和截距
plot_decision_boundary(liner_svc,axis=[-3,3,-3,3])
plt.scatter(data_x[data_y==0,0],data_x[data_y==0,1],color='red')
plt.scatter(data_x[data_y==1,0],data_x[data_y==1,1],color='blue')
plt.show()
print('参数权重')
print(liner_svc.coef_)
print('模型截距')
print(l

[机器学习]支持向量机svm_第14张图片

2、多项式核

from sklearn.preprocessing import PolynomialFeatures #导入多项式回归
from sklearn.pipeline import Pipeline #导入python里的管道
def PolynomialSVC(degree,c=10):#多项式svm
    '''
    :param d:阶数
    :param C:正则化常数
    :return:一个Pipeline实例
    '''
    return Pipeline([
            # 将源数据 映射到 3阶多项式
            ("poly_features", PolynomialFeatures(degree=degree)),
            # 标准化
            ("scaler", StandardScaler()),
            # SVC线性分类器
            ("svm_clf", LinearSVC(C=10, loss="hinge", random_state=42,max_iter=10000))
        ])

poly_svc=PolynomialSVC(degree=3)
poly_svc.fit(data_x,data_y)
# 画图
plot_decision_boundary(poly_svc,axis=[-3,3,-3,3])#绘制边界
plt.scatter(data_x[data_y==0,0],data_x[data_y==0,1],color='red')#画点
plt.scatter(data_x[data_y==1,0],data_x[data_y==1,1],color='blue')
plt.show()
print('参数权重')
print(poly_svc.named_steps['svm_clf'].coef_)
print('模型截距')
print(poly_svc.named_steps['svm_clf'].intercept_)

[机器学习]支持向量机svm_第15张图片

3、高斯核

from sklearn.svm import SVC #导入svm
def RBFKernelSVC(gamma=1.0):
    return Pipeline([
        ('std_scaler',StandardScaler()),
        ('svc',SVC(kernel='rbf',gamma=gamma))
    ])
svc=RBFKernelSVC(gamma=4)#gamma参数很重要,gamma参数越大,支持向量越小
svc.fit(data_x,data_y)
plot_decision_boundary(svc,axis=[-3,3,-3,3])
plt.scatter(data_x[data_y==0,0],data_x[data_y==0,1],color='red')#画点
plt.scatter(data_x[data_y==1,0],data_x[data_y==1,1],color='blue')
plt.show()

[机器学习]支持向量机svm_第16张图片

三、对鸢尾花数据集进行SVM训练

import numpy as np
from sklearn import datasets   #导入数据集
import matplotlib.pyplot as plt  
from sklearn.preprocessing import StandardScaler
from matplotlib.colors import ListedColormap
# 边界绘制函数
def plot_decision_boundary(model,axis):
    x0,x1=np.meshgrid(
        np.linspace(axis[0],axis[1],int((axis[1]-axis[0])*100)).reshape(-1,1),
        np.linspace(axis[2],axis[3],int((axis[3]-axis[2])*100)).reshape(-1,1))
    # meshgrid函数是从坐标向量中返回坐标矩阵
    x_new=np.c_[x0.ravel(),x1.ravel()]
    y_predict=model.predict(x_new)#获取预测值
    zz=y_predict.reshape(x0.shape)
    custom_cmap=ListedColormap(['#EF9A9A','#FFF59D','#90CAF9'])
    plt.contourf(x0,x1,zz,cmap=custom_cmap)

iris = datasets.load_iris()
data_x = iris.data[:, :2] 
data_y = iris.target
plt.rcParams["font.sans-serif"] = ['SimHei']    # 用来正常显示中文标签,SimHei是字体名称,字体必须在系统中存在,字体的查看方式和安装第三部分
plt.rcParams['axes.unicode_minus'] = False     # 用来正常显示负号
plt.scatter(data_x[data_y==0, 0],data_x[data_y==0, 1])    # 选取y所有为0的+X的第一列
plt.scatter(data_x[data_y==1, 0],data_x[data_y==1, 1])    # 选取y所有为1的+X的第一列
plt.scatter(data_x[data_y==2, 0],data_x[data_y==2, 1])    # 选取y所有为2的+X的第一列
plt.xlabel('sepal length')    # 设置横坐标标注xlabel为sepal width
plt.ylabel('sepal width')    # 设置纵坐标标注ylabel为sepal length
plt.title('sepal散点图')    # 设置散点图的标题为sepal散点图
plt.show()

[机器学习]支持向量机svm_第17张图片

1、线性核

from sklearn.svm import LinearSVC
svc_line = LinearSVC(C =1e9,max_iter=100000) #线性SVM分类器
svc_line.fit(data_x,data_y)#训练svm
plot_decision_boundary(svc_line,axis=[4,8,1.8,4.5])
plt.scatter(data_x[data_y==0,0],data_x[data_y==0,1])
plt.scatter(data_x[data_y==1,0],data_x[data_y==1,1])
plt.scatter(data_x[data_y==2,0],data_x[data_y==2,1])
plt.show()

[机器学习]支持向量机svm_第18张图片

2、多项式核

from sklearn.preprocessing import PolynomialFeatures #导入多项式回归
from sklearn.pipeline import Pipeline #导入python里的管道
def PolynomialSVC(degree,c=5):#多项式svm
    """
    :param d:阶数
    :param C:正则化常数
    :return:一个Pipeline实例
    """
    return Pipeline([
            # 将源数据 映射到 3阶多项式
            ("poly_features", PolynomialFeatures(degree=degree)),
            # 标准化
            ("scaler", StandardScaler()),
            # SVC线性分类器
            ("svm_clf", LinearSVC(C=c, loss="hinge", random_state=42,max_iter=100000))
        ])

poly_svc=PolynomialSVC(degree=3)
poly_svc.fit(data_x,data_y)
plot_decision_boundary(poly_svc,axis=[4,8,1.8,4.5])
plt.scatter(data_x[data_y==0,0],data_x[data_y==0,1])
plt.scatter(data_x[data_y==1,0],data_x[data_y==1,1])
plt.scatter(data_x[data_y==2,0],data_x[data_y==2,1])
plt.show()

[机器学习]支持向量机svm_第19张图片

3、高斯核

from sklearn.svm import SVC #导入svm
def RBFKernelSVC(gamma=1.0):
    return Pipeline([
        ('std_scaler',StandardScaler()),
        ('svc',SVC(kernel='rbf',gamma=gamma))
    ])
svc=RBFKernelSVC(gamma=42)#gamma参数很重要,gamma参数越大,支持向量越小
svc.fit(data_x,data_y)
plot_decision_boundary(svc,axis=[4,8,1.8,4.5])
plt.scatter(data_x[data_y==0,0],data_x[data_y==0,1])
plt.scatter(data_x[data_y==1,0],data_x[data_y==1,1])
plt.scatter(data_x[data_y==2,0],data_x[data_y==2,1])
plt.show()

[机器学习]支持向量机svm_第20张图片

参考

  • 《机器学习》分析鸢尾花数据集
  • 鸢尾花数据集、月亮数据集二分类可视化分析
  • 支持向量机(SVM)入门理解与推导

第八次作业另一篇博客及作业文件

[机器学习]初识人脸识别

你可能感兴趣的:(人工智能与机器学习,支持向量机,机器学习,算法)