机器学习:支持向量机(SVM)

一、算法介绍

        

支持向量机(Support Vector Machine,SVM)是一种常用的监督学习算法,用于分类和回归任务。SVM的基本原理是构建一个最优超平面来分割不同类别的数据点。

在二分类问题中,SVM试图找到一个能够将两个类别的数据点尽可能分开的超平面。超平面是一个d-1维的线性子空间,其中d是数据的特征维度。SVM的目标是找到具有最大间隔(即离超平面最近的样本点的距离最大)的超平面。

SVM的核心思想是将数据映射到高维特征空间中,通过引入核函数可以避免直接计算高维特征空间的复杂性。常用的核函数有线性核、多项式核和高斯核等。这些核函数能够将数据从原始空间映射到一个更高维度的空间,使得原本线性不可分的数据在新的空间中变得线性可分。

SVM的训练过程可以形式化为一个凸优化问题,通过最小化目标函数来确定超平面的位置和宽度。目标函数通常由数据的误分类损失和正则化项组成,正则化项是为了防止过拟合。

一旦训练完成,SVM可以用于对新样本进行分类或回归预测。对于分类问题,新样本将被映射到特征空间中,并根据其位置与超平面的关系来判断其所属类别。对于回归问题,SVM可以通过拟合一个边界带来预测。

SVM具有一些重要的特性,包括结构化风险最小化、稀疏性和鲁棒性等。它在处理小样本、高维数据和非线性问题方面表现出色,并在许多领域中得到广泛应用,如图像分类、文本分类、生物信息学和金融预测等。

二、基于最大间隔分隔数据

2.1 线性模型

        在二维空间上,两类点被一条直线完全分开叫做线性可分。如下图,在二维坐标下,样本空间中找到直线, 将不同类别的样本分开。

上述将数据集分隔开来的直线称为分隔超平面,即w^{t}x+b=0

2.2 超平面
        由于数据点都在二维平面上,所以此时分隔超平面就只是一条直线。但是,如果所给的数据 集是三维的,那么此时用来分隔数据的就是一个平面。显而易见,更高维的情况可以依此类推。如果数据集是1000维的,那么就需要一个999维的某某对象来对数据进行分隔。当数据集是N维时,需要一个N-1维的某某对象来对数据进行分隔。N-1维的该对象被称为超平面(hyperplane),也就是分类的决策边界。 分布在超平面一侧的所有数据都属于某个类别,而分布在另一侧的所有数据则属于另一个类别。 

 

从二维扩展到多维空间中时,将 D0和 D1 完全正确地划分开的 w^{t}x+b=0 就成了一个超平面。为了使这个超平面更具鲁棒性,我们会去找最佳超平面,以最大间隔把两类样本分开的超平面,也称之为最大间隔超平面。

 如上图,有五条直线,它们都能将数据分隔开,但是其中哪一条最好呢?我们希望找到离分隔超平面最近的点,确保它们离分隔面的距离尽可能远。这里点到分隔面的距离被称为间隔(margin)。我们需要的是间隔尽可能地大,这是因为如果犯错或者在有限数据上训练分类器的话,分类器尽可能健壮。所以,应选择”正中间”的那条直线 , 容忍性好, 鲁棒性高, 泛化能力最强,选择最大化决策边界的边缘。

2.3 支持向量

如下图,支持向量(support vector)就是离分隔超平面最近的那些点。

超平面方程:w^{t}x+b=0

2.4 支持向量机
        支持向量机(Support Vector Machines, SVM)是一种二分类模型,它的基本模型是定义在特征空间上的间隔最大的线性分类器;SVM还包括核函数,这使它成为实质上的非线性分类器。SVM有很多实现,下面介绍的是序列最小优化(Sequential Minimal Optimization,SMO)算法。 在此之后,将介绍如何使用核函数(kernel)的方式将SVM扩展到更多数据集上。

三、寻找最大间隔

3.1超平面的性质

性质一:法向量和偏置项以任意相同的倍数放缩,新表达式描述的仍然是原来的超平面。假设放缩比例为,令后得到的超平面表达式为,显然,这个表达式表示的仍然是原来的超平面。

性质二:样本空间中的任意一个点,到超平面的距离表达式为

性质三:超平面将n维空间划分为3部分,分为是:①点在超平面里=0;②点在超平面的“上方” ;③点在超平面的“下方”

3.2寻找最大间隔

SVM中,分隔超平面是一个能够将正负样本恰好隔开的超平面,并且使得正样本在分隔超平面“上方”,负样本在分隔超平面”下方“。这就意味着w^{T}x+b=0,分隔超平面中的w,b需要满足以下条件:

其中为正样本点,为负样本点,而正负样本对应的标记值为,所以这两个条件可以改写成下面两个式子:

于是,对于线性可分的样本集:

        ,其中,

分类正确的超平面需要满足的条件为:

        

,我们可以得到更加紧凑的表达:

        "分类正确"

在SVM中,被称为样本点到超平面的函数间隔。

因此,我们可以得出结论,对于给定的线性可分的样本集合,必然存在分隔超平面可以将正负样本分开,该分类正确的超平面需要满足的条件为:样本点到超平面的函数间隔大于零。

所以,为了方便后续的计算,简化方程为:

令 X_+和 X_- 位于决策边界上,标签分别为正、负的两个样本,考虑 X_+到分类线的距离为:

因此,分类间隔为:

最大化间隔也就是寻找参数wb , 使得width最大,即:

 四、拉格朗日乘子法

拉格朗日乘子法(Lagrange Multiplier Method)是一种用于求解约束最优化问题的数学方法。通过引入拉格朗日乘子,将约束条件融入目标函数中,从而将原始问题转化为一个无约束的优化问题。

假设我们要求解如下形式的最优化问题:

最小化(或最大化)目标函数 f(x), 满足约束条件 g(x) = 0。

其中,x 是待求解的变量。

为了使用拉格朗日乘子法求解这个问题,我们引入一个拉格朗日乘子 λ,构建拉格朗日函数:

L(x, λ) = f(x) + λg(x)。

然后,我们可以将原始问题转化为一个无约束的优化问题,即求解拉格朗日函数 L(x, λ) 的极值问题:

最小化(或最大化)L(x, λ)。

为了找到 L(x, λ) 的极值点,我们需要对 x 和 λ 分别求导,并令导数等于零:

∂L(x, λ)/∂x = 0, ∂L(x, λ)/∂λ = 0。

通过求解这个方程组,我们可以得到关于 x 和 λ 的解。其中,x 就是原始问题的最优解,而 λ 则对应着约束条件的乘子。

五、核函数

核函数(Kernel Function)是机器学习中一种重要的工具,它用于将数据从原始空间映射到一个高维特征空间,从而使得非线性可分的数据在新的特征空间中变得线性可分。

在支持向量机(SVM)等算法中,核函数的主要作用是通过计算两个样本在特征空间中的相似度,来替代显式地进行特征映射。这样可以避免了高维特征空间的计算和存储开销,同时仍然能够利用高维特征空间带来的线性可分性。

核函数的特点是只需计算原始空间中的样本之间的内积,而无需显式地计算样本在高维特征空间中的位置。常见的核函数包括线性核函数、多项式核函数、高斯径向基函数(RBF核函数)等。

以高斯径向基函数为例,其定义如下:

K(x, y) = exp(-||x-y||^2 / (2σ^2))

其中,x 和 y 是两个样本点,||x-y|| 表示欧氏距离,σ 是高斯核函数的宽度参数。高斯径向基函数可以将样本映射到无穷维的特征空间中,使得原本分布较近的样本之间的相似度更高。

六、基于SVM实现鸢尾花分类预测

import pandas as pd
import matplotlib.pyplot as plt
import matplotlib as mpl
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.svm import SVC
from sklearn.model_selection import GridSearchCV
from sklearn.metrics import accuracy_score
 
 
# 导入数据,分离特征与输出
iris = load_iris()
iris_df = pd.DataFrame(iris.data, columns=iris.feature_names)
target = pd.Series(iris.target)
print('特征和目标的大小', iris_df.shape, target.shape)
 
# 画布属性设置
mpl.rcParams['font.family'] = ['sans-serif']
mpl.rcParams['font.sans-serif'] = ['SimHei']
mpl.rcParams['axes.unicode_minus'] = False
 
# 散点图
plt.figure(figsize=(10, 5))
plt.subplot(1, 2, 1)
scatter = plt.scatter(iris_df.iloc[:, 0], iris_df.iloc[:, 1], c=target, cmap='viridis')
plt.xlabel('Sepal length')
plt.ylabel('Sepal width')
plt.title('鸢尾花特征分析散点图')
a, b = scatter.legend_elements()
print('散点对象及其标签', a, b)
b = ['setosa', 'versicolor', 'virginica']  # 原标签0,1,2分别对应以下三种
plt.legend(a, b)
 
plt.subplot(1, 2, 2)
scatter = plt.scatter(iris_df.iloc[:, 2], iris_df.iloc[:, 3], c=target, cmap='viridis')
plt.xlabel('Petal length')
plt.ylabel('Petal width')
plt.title('鸢尾花特征分析散点图')
a, b = scatter.legend_elements()
print('散点对象及其标签', a, b)
b = ['setosa', 'versicolor', 'virginica']  # 原标签0,1,2分别对应以下三种
plt.legend(a, b)
plt.show()
 
# 划分训练和测试数据
X_train, X_test, y_train, y_test = train_test_split(iris_df, target, test_size=0.2, random_state=5)
 
# 线型SVM模型训练
linear_svm = SVC(kernel='linear', C=1, random_state=0)
linear_svm.fit(X_train, y_train)
 
# 基于RBF非线性SVM模型训练
rbf_svm = SVC(kernel='rbf', C=1, gamma=0.1, random_state=0)
rbf_svm.fit(X_train, y_train)
 
# 模型评估
linear_y_pred = linear_svm.predict(X_test)
linear_accuracy = accuracy_score(y_test, linear_y_pred)
 
rbf_y_pred = rbf_svm.predict(X_test)
rbf_accuracy = accuracy_score(y_test, rbf_y_pred)
 
print()
print('线性SVM模型模型评估:')
print('参数C:', linear_svm.C)
print('分类准确度accuracy: ', linear_accuracy)
print()
print('RBF非线性SVM模型评估:')
print('参数C:{:d},gamma:{:.1f}'.format(rbf_svm.C, rbf_svm.gamma))
print('分类准确度accuracy: ', rbf_accuracy)
 
# print('真实分类:', list(y_test))
# print('预测分类', list(linear_y_pred))
 
 
# 线型模型分类结果展示
plt.figure(figsize=(8, 8))
plt.subplot(2, 2, 1)
plt.scatter(X_test.iloc[:, 0], X_test.iloc[:, 1], c=y_test, cmap='viridis')
plt.xlabel('Sepal length')
plt.ylabel('Sepal width')
plt.title('真实散点图')
plt.subplot(2, 2, 2)
plt.scatter(X_test.iloc[:, 0], X_test.iloc[:, 1], c=linear_y_pred, cmap='viridis')
plt.xlabel('Sepal length')
plt.ylabel('Sepal width')
plt.title('预测散点图')
plt.subplot(2, 2, 3)
plt.scatter(X_test.iloc[:, 2], X_test.iloc[:, 3], c=y_test, cmap='viridis')
plt.xlabel('Petal length')
plt.ylabel('Petal width')
plt.title('真实散点图')
plt.subplot(2, 2, 4)
plt.scatter(X_test.iloc[:, 2], X_test.iloc[:, 3], c=linear_y_pred, cmap='viridis')
plt.xlabel('Petal length')
plt.ylabel('Petal width')
plt.title('预测散点图')
plt.suptitle('线性模型分类结果对照图')
plt.show()
 
# rbf非线型模型分类结果展示
plt.figure(figsize=(8, 8))
plt.subplot(2, 2, 1)
plt.scatter(X_test.iloc[:, 0], X_test.iloc[:, 1], c=y_test, cmap='viridis')
plt.xlabel('Sepal length')
plt.ylabel('Sepal width')
plt.title('真实散点图')
plt.subplot(2, 2, 2)
plt.scatter(X_test.iloc[:, 0], X_test.iloc[:, 1], c=rbf_y_pred, cmap='viridis')
plt.xlabel('Sepal length')
plt.ylabel('Sepal width')
plt.title('预测散点图')
plt.subplot(2, 2, 3)
plt.scatter(X_test.iloc[:, 2], X_test.iloc[:, 3], c=y_test, cmap='viridis')
plt.xlabel('Petal length')
plt.ylabel('Petal width')
plt.title('真实散点图')
plt.subplot(2, 2, 4)
plt.scatter(X_test.iloc[:, 2], X_test.iloc[:, 3], c=rbf_y_pred, cmap='viridis')
plt.xlabel('Petal length')
plt.ylabel('Petal width')
plt.title('预测散点图')
plt.suptitle('rbf非线性模型分类结果对照图')
plt.show()
 
# 参数调优
print()
print('模型调优')
linear_params = {'C': [0.1, 0.5, 1, 5, 10]}
linear_gridsearch = GridSearchCV(SVC(kernel='linear'), linear_params, scoring='accuracy', cv=5)
linear_gridsearch.fit(X_train, y_train)
print('线性SVM参数调优结果:', linear_gridsearch.best_params_)
linear_svm.C = linear_gridsearch.best_params_['C']
 
rbf_params = {'C': [0.1, 0.5, 1, 5, 10], 'gamma': [0.001, 0.01, 0.1, 1, 10]}
rbf_gridsearch = GridSearchCV(SVC(kernel='rbf'), rbf_params, cv=5)
rbf_gridsearch.fit(X_train, y_train)
print('RBF非线性SVM参数调优结果:', rbf_gridsearch.best_params_)
rbf_svm.C = rbf_gridsearch.best_params_['C']
rbf_svm.gamma = rbf_gridsearch.best_params_['gamma']
 
# 模型评估
linear_y_pred = linear_svm.predict(X_test)
linear_accuracy = accuracy_score(y_test, linear_y_pred)
 
rbf_y_pred = rbf_svm.predict(X_test)
rbf_accuracy = accuracy_score(y_test, rbf_y_pred)
 
print()
print('参数调优后的模型性能:')
print('C:', linear_svm.C)
print('线性SVM模型准分类确度: ', linear_accuracy)
print('C,gamma:', rbf_svm.C, rbf_svm.gamma)
print('RBF非线性SVM模型准分类确度:  ', rbf_accuracy)
 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值