支持向量机

目录

一、引言

二、算法概述

2.1 算法简介

2.2 间隔和支持向量

三、算法实现

3.1实验步骤

 3.2 实现SVM分类器

3.3 实现结果可视化 

3.4 准备数据 训练模型 

3.5 实验结果截图

3.6 调整参数C优化分类结果 

 3.7 实验结果截图(可调整参数C)

3.8 整体代码 

四、总结分析


一、引言

支持向量机(Support Vector Machine, SVM)是一种强大的机器学习算法,广泛应用于分类、回归以及异常值检测等任务中。本次实验旨在通过实践操作,深入了解SVM算法的原理、实现方式及其在实际应用中的效果。

二、算法概述

2.1 算法简介

支持向量机(SVM)是一种基于统计学习理论的分类方法,其核心思想是通过寻找一个超平面来对样本进行分割,使得不同类别的样本位于超平面的两侧,并且使得离超平面最近的样本点到超平面的距离最大化。这个超平面被称为最大间隔超平面,而离超平面最近的样本点被称为支持向量。

SVM算法可以分为线性可分SVM、线性SVM和非线性SVM三种类型。当训练样本线性可分时,通过硬间隔最大化学习一个线性可分SVM;当训练样本近似线性可分时,通过软间隔最大化学习一个线性SVM;当训练样本线性不可分时,则通过核技巧和软间隔最大化学习一个非线性SVM。

 

2.2 间隔和支持向量

支持向量:距离超平面最近的样本点;

间隔:两个异类支持向量到超平面的距离之和。 

三、算法实现

3.1实验步骤

本次实验采用Python编程语言,使用sklearn库中的SVM模块进行算法实现。具体实现步骤如下:

  1. 数据准备:选择适当的数据集,并进行预处理,包括数据清洗、特征选择等。
  2. 导入SVM模块:使用sklearn库中的SVC类实现SVM算法。
  3. 数据划分:将数据集划分为训练集和测试集,以便进行模型训练和评估。
  4. 训练SVM分类器:使用训练集对SVM分类器进行训练,并调整模型参数以获得最佳性能。
  5. 模型评估:使用测试集对训练好的SVM分类器进行评估,计算分类准确率等指标。

 3.2 实现SVM分类器

定义一个名为LinearSVM的类,用于实现线性支持向量机算法。其中包含类的初始化方法、fit方法和predict方法。 

class LinearSVM:
    def __init__(self,learning_rate=0.0001,lambda_param=0.1,n_iters=1000):
        self.learning_rate=learning_rate#学习率
        self.lambda_param=lambda_param#正则化参数
        self.n_iters=n_iters#迭代次数
        self.w=None
        self.b=None
 
    def fit(self,X,y):#fit方法用于模型训练
        n_samples,n_features=X.shape
        y_ =np.where(y<=0,-1,1)
 
        #初始化权重和偏置为0
        self.w=np.zeros(n_features)
        self.b=0
 
        for _ in range(self.n_iters):
            for idx,x_i in enumerate(X):
                condition = y_[idx]*(np.dot(x_i,self.w)-self.b)>=1 #遍历每个样本,检查分类条件
                if condition:
                    self.w-=self.learning_rate*(2*self.lambda_param*self.w)#如果样本被正确分类且在正确的间隔外,仅通过正则项更行权重(防止过拟合)
                else:
                    self.w-=self.learning_rate*(2*self.lambda_param*self.w-np.dot(x_i,y_[idx]))#样本被错误分类或者在间隔内,则权重更新包括误差项,同时更新偏置,使样本在未来被正确分类
                    self.b-=self.learning_rate*y_[idx]
 
    def predict(self,X):
        Linear_output=np.dot(X,self.w)-self.b
        return np.sign(Linear_output)

3.3 实现结果可视化 

定义一个名为plot_hyperplane的函数,用于绘制数据集和分类超平面。首先绘制散点图,然后获取坐标轴的范围,生成网格点,计算网格点的Z值,最后绘制等高线。

#结果可视化    
def plot_hyperplane(X,y,w,b):
        plt.scatter(X[:,0],X[:,1],marker='o',c=y,s=100,edgecolors='k',cmap='winter')
        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=(np.dot(xy,w)-b).reshape(XX.shape)
        ax.contour(XX,YY,Z,colors='k',levels=[-1,0,1],alpha=0.5,linestyles=['--','-','--'])
        plt.show()

3.4 准备数据 训练模型 

 使用sklearn.datasets中的make_blobs函数生成一个包含100个样本、2个中心点的数据集。将标签y调整为-1和1,然后创建一个LinearSVM实例,调用fit方法进行训练。再调用plot_hyperplane函数,可视化训练结果。

#数据准备和模型训练
X,y=datasets.make_blobs(n_samples=100,centers=2,random_state=6)
y=np.where(y==0,-1,1)#调整标签为-1和1
svm0=LinearSVM()
svm0.fit(X,y)
plot_hyperplane(X,y,svm0.w,svm0.b) # type: ignore

3.5 实验结果截图

3.6 调整参数C优化分类结果 

参数C控制了错误分类训练示例的惩罚。参数C越大,则告诉SVM要对所有的例子进行正确的分类。 

当C比较小时,模型对错误分类的惩罚较小,比较松弛,样本点之间的间隔就比较大,可能产生欠拟合的情况当

C比较大时,模型对错误分类的惩罚较大,两组数据之间的间隔就小,容易产生过拟合的情况

C值越大,越不容易放弃那些离群点;C值越小,越不重视那些离群点。

#调整C参数看不同的效果
class LinearSVM1:
    def __init__(self,C=1.0,learning_rate=0.0001,n_iters=1000):
        self.C=C
        self.learning_rate=learning_rate
        self.n_iters=n_iters
        self.w=None
        self.b=None
 
    def fit(self,X,y):
        n_samples,n_features=X.shape
        y_ =np.where(y<=0,-1,1)
 
        #初始化权重和偏置为0
        self.w=np.zeros(n_features)
        self.b=0
 
        for _ in range(self.n_iters):
            for idx,x_i in enumerate(X):
                condition = y_[idx]*(np.dot(x_i,self.w)-self.b)>=1 #遍历每个样本,检查分类条件
                if condition:
                    self.w-=self.learning_rate*(2*self.w)#如果样本被正确分类且在正确的间隔外,仅通过正则项更行权重(防止过拟合)
                else:
                    self.w-=self.learning_rate*((2*self.w)-self.C*np.dot(x_i,y_[idx]))#样本被错误分类或者在间隔内,则权重更新包括误差项,同时更新偏置,使样本在未来被正确分类
                    self.b-=self.learning_rate*self.C*y_[idx]
 
    def predict(self,X):
        Linear_output=np.dot(X,self.w)-self.b
        return np.sign(Linear_output)
    
    #数据准备和模型训练
X,y=datasets.make_blobs(n_samples=100,centers=2,random_state=6)
y=np.where(y==0,-1,1)#调整标签为-1和1
svm1=LinearSVM1(C=200)
svm1.fit(X,y)
plot_hyperplane(X,y,svm1.w,svm1.b) # type: ignore

 3.7 实验结果截图(可调整参数C)

当C=20时,SVM分类结果如下图所示:

参数C=20

当C=100时,SVM分类结果如下图所示:

 

参数C=100

当C=200时,SVM分类结果如下图所示:

3.8 整体代码 

import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets
 
class LinearSVM:
    def __init__(self,learning_rate=0.0001,lambda_param=0.1,n_iters=1000):
        self.learning_rate=learning_rate#学习率
        self.lambda_param=lambda_param#正则化参数
        self.n_iters=n_iters#迭代次数
        self.w=None
        self.b=None
 
    def fit(self,X,y):#fit方法用于模型训练
        n_samples,n_features=X.shape
        y_ =np.where(y<=0,-1,1)
 
        #初始化权重和偏置为0
        self.w=np.zeros(n_features)
        self.b=0
 
        for _ in range(self.n_iters):
            for idx,x_i in enumerate(X):
                condition = y_[idx]*(np.dot(x_i,self.w)-self.b)>=1 #遍历每个样本,检查分类条件
                if condition:
                    self.w-=self.learning_rate*(2*self.lambda_param*self.w)#如果样本被正确分类且在正确的间隔外,仅通过正则项更行权重(防止过拟合)
                else:
                    self.w-=self.learning_rate*(2*self.lambda_param*self.w-np.dot(x_i,y_[idx]))#样本被错误分类或者在间隔内,则权重更新包括误差项,同时更新偏置,使样本在未来被正确分类
                    self.b-=self.learning_rate*y_[idx]
 
    def predict(self,X):
        Linear_output=np.dot(X,self.w)-self.b
        return np.sign(Linear_output)
 
#结果可视化    
def plot_hyperplane(X,y,w,b):
        plt.scatter(X[:,0],X[:,1],marker='o',c=y,s=100,edgecolors='k',cmap='winter')
        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=(np.dot(xy,w)-b).reshape(XX.shape)
        ax.contour(XX,YY,Z,colors='k',levels=[-1,0,1],alpha=0.5,linestyles=['--','-','--'])
        plt.show()
    
#数据准备和模型训练
X,y=datasets.make_blobs(n_samples=100,centers=2,random_state=6)
y=np.where(y==0,-1,1)#调整标签为-1和1
svm0=LinearSVM()
svm0.fit(X,y)
plot_hyperplane(X,y,svm0.w,svm0.b) # type: ignore
 
 
#调整C参数看不同的效果
class LinearSVM1:
    def __init__(self,C=1.0,learning_rate=0.0001,n_iters=1000):
        self.C=C
        self.learning_rate=learning_rate
        self.n_iters=n_iters
        self.w=None
        self.b=None
 
    def fit(self,X,y):
        n_samples,n_features=X.shape
        y_ =np.where(y<=0,-1,1)
 
        #初始化权重和偏置为0
        self.w=np.zeros(n_features)
        self.b=0
 
        for _ in range(self.n_iters):
            for idx,x_i in enumerate(X):
                condition = y_[idx]*(np.dot(x_i,self.w)-self.b)>=1 #遍历每个样本,检查分类条件
                if condition:
                    self.w-=self.learning_rate*(2*self.w)#如果样本被正确分类且在正确的间隔外,仅通过正则项更行权重(防止过拟合)
                else:
                    self.w-=self.learning_rate*((2*self.w)-self.C*np.dot(x_i,y_[idx]))#样本被错误分类或者在间隔内,则权重更新包括误差项,同时更新偏置,使样本在未来被正确分类
                    self.b-=self.learning_rate*self.C*y_[idx]
 
    def predict(self,X):
        Linear_output=np.dot(X,self.w)-self.b
        return np.sign(Linear_output)
    
    #数据准备和模型训练
X,y=datasets.make_blobs(n_samples=100,centers=2,random_state=6)
y=np.where(y==0,-1,1)#调整标签为-1和1
svm1=LinearSVM1(C=200)
svm1.fit(X,y)
plot_hyperplane(X,y,svm1.w,svm1.b) # type: ignore

四、总结分析

通过本次实验,我们深入了解了SVM算法的原理和实现方式,并成功地将其应用于手写数字识别任务中。实验结果表明,SVM算法在处理高维数据时具有较好的性能,并且能够通过核函数技巧处理非线性分类问题。此外,SVM算法还具有较好的泛化能力,能够有效地避免过拟合现象。

然而,SVM算法也存在一些缺点。首先,SVM算法的计算复杂度较高,特别是在处理大规模数据集时,其训练速度可能会受到较大影响。其次,SVM算法对参数的选择较为敏感,不同的参数设置可能会导致模型性能的较大差异。因此,在实际应用中,我们需要根据具体任务和数据特点来选择合适的SVM算法和参数设置。

综上所述,SVM算法是一种强大而有效的机器学习算法,在分类任务中具有较好的性能和泛化能力。在未来的研究中,我们可以进一步探索SVM算法的优化和改进方法,以提高其在处理大规模数据集和复杂任务时的性能和效率。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值