Python机器学习入门 -- 支持向量机学习笔记_支持向量机 python-程序员宅基地

技术标签: 支持向量机  python  机器学习  


前言

大部分传统的机器学习算法都可以实现分类任务,但这些模型关注的是将不同类别的数据分得开就行,也就是说它们的核心思想是让整个模型分类出错的损失越小越好。刚刚好有一种机器学习模型,它不仅关注分类能不能将不同类别的数据完全分得开,还关注分类得到的决策边界的间隔能不能最大化,即离该决策边界每个类别最近的数据点的距离能不能更远,这就是我们今天的主角 - - 支持向量机。


一、支持向量机简介

示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。

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

二、支持向量机的数学原理

在这里插入图片描述
支持向量机,从名字上来看它是由支持向量(Support Vectors)形成决策边界的一种模型,这里的支持向量是一种特殊的数据点,是所在类别数据中离决策平面最近的一些数据点,支撑起整个决策平面,有点像团队中骨干,他们支撑起整个团队的发展和未来。支持向量的个数与模型的复杂度成正比

1. 距离解算

与其他分类模型类似的是,支持向量机中我们用点到决策面的距离作为优化因子,我们以三维空间中的点到决策平面的距离计算原理推广到高维空间中

在这里插入图片描述
设决策平面方程为
w T x ′ + b = 0 w^{T}x' + b = 0 wTx+b=0

取任一数据点 x x x ,设决策平面的法向量为 w w w ,我们在决策平面上随便取一点 x ′ x' x ,则 x x ′ xx' xx 两点间的向量为 x − x ′ x - x' xx,将向量 x − x ′ x - x' xx 与法向量 w w w 作点乘可以算出向量 x − x ′ x - x' xx 在法向量 w w w 上投影的长度(即点到平面距离)与法向量 w w w 模的长度的乘积,再除以法向量 w w w 模的长度得到点到平面距离,代入决策平面的方程消掉 x ′ x' x

d i s ( x , b , w ) = ∣ w T ⋅ x + b ∣ ∣ ∣ w ∣ ∣ dis(x, b, w) = \frac{|w^{T}\cdot x+b|}{||w||} dis(x,b,w)=∣∣w∣∣wTx+b

推广到高维空间中也同样适用,只是每个参数向量的维度都变高了
在这里插入图片描述
考虑到二分类模型要结合样本数据的标签,我们将正例的标签值定义为1,将负例的标签值定义为-1,对于给定的数据集 M M M 和超平面 w ⋅ x + b = 0 w\cdot x+b=0 wx+b=0 ,定义超平面关于样本点 ( x i , y i ) \left( x_i,y_i \right) (xi,yi) 的几何间隔为
d i s ( x , b , w ) = y i ( w T ⋅ x i + b ) ∣ ∣ w ∣ ∣ dis(x, b, w) = \frac{y_{i}(w^{T}\cdot x_{i}+b)}{||w||} dis(x,b,w)=∣∣w∣∣yi(wTxi+b)

在这里插入图片描述
接下来,我们按照原来的思路,对离决策平面最近的点的距离进行最大化为目标函数进行优化

2. 目标函数

我们假设离决策平面最近的点的距离为 d i s m i n dis_{min} dismin ,这个距离就是我们所谓的支持向量到超平面的距离。根据以上定义,SVM模型的求解最大分割超平面问题可以表示为的最优化问题的约束条件为
y i ( w T ⋅ x i + b ) ∣ ∣ w ∣ ∣ ≥ d i s m i n \frac{y_{i}(w^{T}\cdot x_{i}+b)}{||w||} \geq dis_{min} ∣∣w∣∣yi(wTxi+b)dismin
最优化问题的目标函数为
m a x w , b d i s m i n max_{w, b} dis_{min} maxw,bdismin
在这里插入图片描述
为了对目标函数和约束条件进行简化,将约束条件两边同时除以 d i s m i n dis_{min} dismin ,放缩整合一下约束条件可以得出
y i ( w T ⋅ x i + b ) ∣ ∣ w ∣ ∣ d i s m i n ≥ 1 \frac{y_{i}(w^{T}\cdot x_{i}+b)}{||w||dis_{min}} \geq 1 ∣∣w∣∣disminyi(wTxi+b)1
y i ( w T ⋅ x i + b ) ≥ 1 {y_{i}(w^{T}\cdot x_{i}+b)} \geq 1 yi(wTxi+b)1

在这里插入图片描述
根据放缩推导可知, y i ( w T ⋅ x i + b ) ≥ 1 {y_{i}(w^{T}\cdot x_{i}+b)} \geq 1 yi(wTxi+b)1恒成立,又因为最大化 d i s m i n dis_{min} dismin 等价于最大化 1 ∣ ∣ w ∣ ∣ \frac{1}{||w||} ∣∣w∣∣1 ,所以目标函数和约束条件最终可以表达为
m i n w , b ∣ ∣ w ∣ ∣ 2 2 min_{w, b} \frac{||w||^{2}}{2} minw,b2∣∣w2
y i ( w T ⋅ x i + b ) ≥ 1 {y_{i}(w^{T}\cdot x_{i}+b)} \geq 1 yi(wTxi+b)1

3. 约束下的优化求解

拉格朗日乘子法是一种寻找多元函数在有约束条件下的极值的方法,结合拉格朗日乘子法我们可以构造新的目标函数, 该目标函数是想求解在约束路径内,何种 w , b , a w,b,a w,b,a 的组合下能使 ∣ ∣ w ∣ ∣ 2 2 \frac{||w||^{2}}{2} 2∣∣w2 达到最小,其中 ϕ ( x ) \phi(x) ϕ(x) 是核变换,是一种低维数据映射到高维的变换方式
L ( w , b , a ) = ∣ ∣ w 2 ∣ ∣ 2 − ∑ i = 1 n α ( y i ( w T ⋅ ϕ ( x i ) + b ) − 1 ) L(w, b, a) = \frac{||w^{2}||}{2} - \sum_{i=1}^{n}\alpha(y_{i}(w^{T}\cdot \phi(x_{i})+b) - 1) L(wba)=2∣∣w2∣∣i=1nα(yi(wTϕ(xi)+b)1)

在这里插入图片描述
按照拉格朗日乘子法的思想,接着目标函数分别对 w , b , a w, b, a w,b,a 求偏导,并使三个偏导等于0,即可求得在约束条件下的极值恒等式,该恒等式表征了在约束条件下取极值时 w , b w,b w,b α \alpha α 的关系,极值等式化简可以得到
∂ L ∂ w = 0 ≫ w = ∑ i = 1 n α y i ϕ ( x i ) \frac{ \partial L }{ \partial w } = 0 \gg w = \sum_{i=1}^{n}\alpha y_{i} \phi(x_{i}) wL=0w=i=1nαyiϕ(xi)
∂ L ∂ b = 0 ≫ 0 = ∑ i = 1 n α y i \frac{ \partial L }{ \partial b } = 0 \gg 0 = \sum_{i=1}^{n}\alpha y_{i} bL=00=i=1nαyi

将极值恒等式代入目标函数消掉 w , b w, b w,b,即可得到关于 α \alpha α 的一元目标函数

在这里插入图片描述
我们通过这个优化方法能得到 α \boldsymbol{\alpha } α,再根据 α \boldsymbol{\alpha } α ,我们就可以求解出 w 和 b \boldsymbol{w} 和 \boldsymbol{b} wb ,进而求得我们最初的目的:找到超平面,即算出决策平面的方程。
在这里插入图片描述

4. 软间隔优化

现实生活中的数据往往是或本身就是非线性可分但是近似线性可分的,或是线性可分但是具有噪声的,以上两种情况都会导致在现实应用中,上面提到的硬间隔线性支持向量机变得不再实用。软间隔SVM中,我们的分类超平面既要能够尽可能地将数据类别分对,又要使得支持向量到超平面的间隔尽可能地大。
在这里插入图片描述
软间隔中 ξ i \xi _i ξi 为 “松弛变量”, 即一个 h i n g e hinge hinge 损失函数。每一个样本都有一个对应的松弛变量,它表征该样本数据不满足约束的程度,不满足约束的程度越高该数据点越可能成为噪音点离群点。
在这里插入图片描述
软间隔的目标函数中 C C C 称为正则化惩罚参数, C C C 值越大,对分类的惩罚力度越大,容错率越低, C C C 值越小,对分类的惩罚力度越小,容错率越高。后续跟线性可分求解的思路一致,同样这里先用拉格朗日乘子法得到拉格朗日函数,再求其对偶问题。

5. 核函数变换

在常见的二分类问题中,常常会出现低维数据不可分的问题,但如果只是简单地进行矩阵内积运算,又会出现新的问题 - - 维数灾难,即原始的空间为三维可以映射到20维,这也可以处理,但是如果我们低维的特征是100个维度,那需要更高的维度来映射,这时候映射成的维度是爆炸性增长的,计算量太大,无法计算了。支持向量机的优势主要体现在解决线性不可分问题,它通过引入核函数变换技巧,巧妙地解决了在高维空间中的内积运算,从而很好地解决了非线性分类问题。

在这里插入图片描述
常用的核函数有

线性核函数(Linear Kernel): K ( x , z ) = x ⋅ z K(x,z)=x⋅z K(x,z)=xz

多项式核函数(Polynomial Kernel): K ( x , z ) = ( x ⋅ z + 1 ) p K(x,z)=(x⋅z+1) p K(x,z)=(xz+1)p

高斯核函数(Gaussian Kernel): K ( x , z ) = e − ∣ x − z ∣ 2 2 σ 2 K(x,z)=e^{-\frac{|x-z|^{2}} {2 \sigma^{2}}} K(x,z)=e2σ2xz2

Sigmoid核函数(Sigmoid Kernel): K ( x , z ) = t a n h ( γ x ∙ z + r ) K(x,z)=tanh(γx∙z+r) K(x,z)=tanhγxz+r)

在这里插入图片描述
有了核函数我们就可以将低维线性不可分的数据映射到高维达到线性可分的效果,这就是非线性SVM的实现思想

三、Python实现支持向量机

1. 惩罚力度对比

Python实现支持向量机的思路,首先导包,这次我们以鸢尾花数据集做实验,我们取鸢尾花数据集中两个特征和标签,接着实例化两个线性核的SVM,正则化参数C不同,然后定义决策平面和标出支持向量的函数等待调用,最后可视化展示一下

import matplotlib.pyplot as plt
import numpy as np
from sklearn.svm import SVC
from sklearn.datasets import load_iris

iris = load_iris()
x = iris['data'][:, (1, 2)]
y = iris['target']

set_two_classes = (y==0) | (y==1)
x = x[set_two_classes]
y = y[set_two_classes]
svm_clf1 = SVC(kernel='linear', C=0.1)
svm_clf2 = SVC(kernel='linear', C=1000)
svm_clf1.fit(x, y)
svm_clf2.fit(x, y)

def plot_decision_boundary(svm_clf, xmin, xmax):
    w = svm_clf.coef_[0]
    b = svm_clf.intercept_[0]
    x0 = np.linspace(xmin, xmax, 200)
    decision_boundary = -w[0]/w[1] * x0 - b/w[1]
    margin = 1/w[1]
    gutter_up = decision_boundary + margin
    gutter_down = decision_boundary - margin
    svs = svm_clf.support_vectors_
    plt.scatter(svs[:, 0], svs[:, 1], s=200, facecolors='#FFAAAA')
    plt.plot(x0, decision_boundary, 'k-', linewidth=2)
    plt.plot(x0, gutter_up, 'k--', linewidth=2)
    plt.plot(x0, gutter_down, 'k--', linewidth=2)



plt.figure(figsize=(12, 8))
plt.subplot(121)
plot_decision_boundary(svm_clf1, 0, 6)
plt.plot(x[:, 0][y == 0], x[:, 1][y == 0], 'bs', label="Iris-Virginica")
plt.plot(x[:, 0][y == 1], x[:, 1][y == 1], 'ys', label="Iris-Versicolor")
plt.legend(loc="best", fontsize=12)
plt.xlabel("petal length", fontsize=12)
plt.ylabel("petal width", fontsize=12)
plt.title("C=0.1")
plt.axis([1, 5, 0.5, 5.5])
plt.subplot(122)
plot_decision_boundary(svm_clf2, 0, 6)
plt.plot(x[:, 0][y == 0], x[:, 1][y == 0], 'bs', label="Iris-Virginica")
plt.plot(x[:, 0][y == 1], x[:, 1][y == 1], 'ys', label="Iris-Versicolor")
plt.legend(loc="best", fontsize=12)
plt.xlabel("petal length", fontsize=12)
plt.ylabel("petal width", fontsize=12)
plt.title("C=1000")
plt.axis([1, 5, 0.5, 5.5])
plt.show()

在这里插入图片描述

2. 高斯核函数

Python实现高斯核映射的思路,首先导包,这次我们以随便生成的数据集做实验,定义高斯核函数的数学表达式和数据集画图函数,然后将数据代入高斯核函数计算,最后可视化展示一下

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D



x1 = np.linspace(-2, 2, 30)
y1 = np.sqrt(4 - 2 * x1**2)
x2 = np.linspace(-1, 1, 30)
y2 = np.sqrt(2 - 2 * x2**2)

colors = ["blue", "green"]
types = ["bs", "g^"]

def plot_dataset(x, y, ty):
    plt.plot(x, y, ty, markersize=3)
    plt.grid(True, which='both')
    plt.xlabel(r"$x_1$", fontsize=12)
    plt.ylabel(r"$x_2$", fontsize=12, rotation=0)

# 定义高斯核函数
def gaussian_kernel(x1, y1, x2, y2, sigma=1):
    return np.exp(-((x1-y1)**2+(x2-y2)**2) / (2 * (sigma ** 2)))



# 计算高斯核函数矩阵
K1 = np.zeros((1, 30))
K2 = np.zeros((1, 30))
for i in range(1):
    for j in range(30):
       K1[i, j] = gaussian_kernel(x1[j], 0.0, y1[j], 1)
       K2[i, j] = gaussian_kernel(x2[j], 0.0, y2[j], 1)

# 画图
fig = plt.figure(figsize=(12, 8))

ax1 = fig.add_subplot(121)
plot_dataset(x1, y1, types[0])
plot_dataset(x2, y2, types[1])
ax2 = fig.add_subplot(122, projection='3d')
ax2.scatter(x1.flatten(), y1.flatten(), K1.flatten(), c=colors[0], cmap='rainbow')
ax2.scatter(x2.flatten(), y2.flatten(), K2.flatten(), c=colors[1], cmap='rainbow')
plt.show()

在这里插入图片描述
可以清晰地看见,在二维空间中线性不可分的数据映射到三维空间中就变得线性可分了

3. 非线性SVM

Python实现非线性SVM的思路,首先导包,这次我们以月亮数据集做实验,我们取月亮数据集中两个特征和标签,接着实例化两个高斯核的SVM,在正则化参数C不同, γ \gamma γ参数不同的情况下作对比,然后定义决策平面和标出支持向量的画图函数等待调用,最后枚举画图可视化展示一下

import matplotlib.pyplot as plt
import numpy as np
from sklearn.datasets import make_moons
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import PolynomialFeatures
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC

x, y = make_moons(n_samples=200, noise=0.23, random_state=36)
gamma1, gamma2 = 0.2, 6
C1, C2 = 0.1, 1000
hyperparams = (gamma1, C1), (gamma2, C1), (gamma1, C2), (gamma2, C2)
svm_clfs = []

def plot_dataset(x, y):
    plt.plot(x[:, 0][y == 0], x[:, 1][y == 0], "bs", markersize=3)
    plt.plot(x[:, 0][y == 1], x[:, 1][y == 1], "g^", markersize=3)
    plt.grid(True, which='both')
    plt.xlabel(r"$x_1$", fontsize=12)
    plt.ylabel(r"$x_2$", fontsize=12, rotation=0)

def plot_predictions(svm_clf):
    x0 = np.linspace(-2, 3, 200)
    x1 = np.linspace(-2, 3, 200)
    x0s, x1s = np.meshgrid(x0, x1)
    X = np.c_[x0s.ravel(), x1s.ravel()]
    y_pred = svm_clf.predict(X).reshape(x0s.shape)
    plt.contourf(x0s, x1s, y_pred, cmap=plt.cm.brg, alpha=0.3)

for gamma, C in hyperparams:
    rbf_svm_clf = Pipeline([("scaler", StandardScaler()),("svm_clf", SVC(kernel="rbf" ,C=C, gamma=gamma))])
    rbf_svm_clf.fit(x, y)
    svm_clfs.append(rbf_svm_clf)


plt.figure(figsize=(12, 8))

for i, svm_clf in enumerate(svm_clfs):
    plt.subplot(221+i)
    plot_predictions(svm_clf)
    plot_dataset(x, y)
    gamma, C = hyperparams[i]
    plt.title(r"$\gamma = {},C = {}$".format(gamma, C), fontsize=12)
plt.show()

在这里插入图片描述


总结

以上就是支持向量机学习笔记的内容,本篇笔记简单地介绍了支持向量机的数学原理和程序实现思路。支持向量机在以下几个领域有广泛应用:

模式识别:SVM能够有效地处理高维数据,因此广泛应用于模式识别领域,如人脸识别、手写字符识别、语音识别、图像识别等。

生物信息学:SVM在生物信息学领域中被用于针对蛋白质、DNA和RNA进行的序列分类、簇分类、预测等方面。

金融预测:SVM在金融领域中被用于预测股票价格、货币汇率等方面,可以通过股票市场中交易数据的分析来为资产管理、人力资源管理等备出一定的策略。

医学检测:SVM能够通过学习病人的生物标记,进行疾病诊断、预测和治疗方案制定等方面的应用。

计算机视觉:SVM在计算机视觉领域中被用于目标检测、图像分类、图像分割等方面。

文本分类:SVM在文本分类领域中被用于垃圾邮件、情感分析、自然语言处理等方面。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/m0_55202222/article/details/130462742

智能推荐

c# 调用c++ lib静态库_c#调用lib-程序员宅基地

文章浏览阅读2w次,点赞7次,收藏51次。四个步骤1.创建C++ Win32项目动态库dll 2.在Win32项目动态库中添加 外部依赖项 lib头文件和lib库3.导出C接口4.c#调用c++动态库开始你的表演...①创建一个空白的解决方案,在解决方案中添加 Visual C++ , Win32 项目空白解决方案的创建:添加Visual C++ , Win32 项目这......_c#调用lib

deepin/ubuntu安装苹方字体-程序员宅基地

文章浏览阅读4.6k次。苹方字体是苹果系统上的黑体,挺好看的。注重颜值的网站都会使用,例如知乎:font-family: -apple-system, BlinkMacSystemFont, Helvetica Neue, PingFang SC, Microsoft YaHei, Source Han Sans SC, Noto Sans CJK SC, W..._ubuntu pingfang

html表单常见操作汇总_html表单的处理程序有那些-程序员宅基地

文章浏览阅读159次。表单表单概述表单标签表单域按钮控件demo表单标签表单标签基本语法结构<form action="处理数据程序的url地址“ method=”get|post“ name="表单名称”></form><!--action,当提交表单时,向何处发送表单中的数据,地址可以是相对地址也可以是绝对地址--><!--method将表单中的数据传送给服务器处理,get方式直接显示在url地址中,数据可以被缓存,且长度有限制;而post方式数据隐藏传输,_html表单的处理程序有那些

PHP设置谷歌验证器(Google Authenticator)实现操作二步验证_php otp 验证器-程序员宅基地

文章浏览阅读1.2k次。使用说明:开启Google的登陆二步验证(即Google Authenticator服务)后用户登陆时需要输入额外由手机客户端生成的一次性密码。实现Google Authenticator功能需要服务器端和客户端的支持。服务器端负责密钥的生成、验证一次性密码是否正确。客户端记录密钥后生成一次性密码。下载谷歌验证类库文件放到项目合适位置(我这边放在项目Vender下面)https://github.com/PHPGangsta/GoogleAuthenticatorPHP代码示例://引入谷_php otp 验证器

【Python】matplotlib.plot画图横坐标混乱及间隔处理_matplotlib更改横轴间距-程序员宅基地

文章浏览阅读4.3k次,点赞5次,收藏11次。matplotlib.plot画图横坐标混乱及间隔处理_matplotlib更改横轴间距

docker — 容器存储_docker 保存容器-程序员宅基地

文章浏览阅读2.2k次。①Storage driver 处理各镜像层及容器层的处理细节,实现了多层数据的堆叠,为用户 提供了多层数据合并后的统一视图②所有 Storage driver 都使用可堆叠图像层和写时复制(CoW)策略③docker info 命令可查看当系统上的 storage driver主要用于测试目的,不建议用于生成环境。_docker 保存容器

随便推点

网络拓扑结构_网络拓扑csdn-程序员宅基地

文章浏览阅读834次,点赞27次,收藏13次。网络拓扑结构是指计算机网络中各组件(如计算机、服务器、打印机、路由器、交换机等设备)及其连接线路在物理布局或逻辑构型上的排列形式。这种布局不仅描述了设备间的实际物理连接方式,也决定了数据在网络中流动的路径和方式。不同的网络拓扑结构影响着网络的性能、可靠性、可扩展性及管理维护的难易程度。_网络拓扑csdn

JS重写Date函数,兼容IOS系统_date.prototype 将所有 ios-程序员宅基地

文章浏览阅读1.8k次,点赞5次,收藏8次。IOS系统Date的坑要创建一个指定时间的new Date对象时,通常的做法是:new Date("2020-09-21 11:11:00")这行代码在 PC 端和安卓端都是正常的,而在 iOS 端则会提示 Invalid Date 无效日期。在IOS年月日中间的横岗许换成斜杠,也就是new Date("2020/09/21 11:11:00")通常为了兼容IOS的这个坑,需要做一些额外的特殊处理,笔者在开发的时候经常会忘了兼容IOS系统。所以就想试着重写Date函数,一劳永逸,避免每次ne_date.prototype 将所有 ios

如何将EXCEL表导入plsql数据库中-程序员宅基地

文章浏览阅读5.3k次。方法一:用PLSQL Developer工具。 1 在PLSQL Developer的sql window里输入select * from test for update; 2 按F8执行 3 打开锁, 再按一下加号. 鼠标点到第一列的列头,使全列成选中状态,然后粘贴,最后commit提交即可。(前提..._excel导入pl/sql

Git常用命令速查手册-程序员宅基地

文章浏览阅读83次。Git常用命令速查手册1、初始化仓库git init2、将文件添加到仓库git add 文件名 # 将工作区的某个文件添加到暂存区 git add -u # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,不处理untracked的文件git add -A # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,包括untracked的文件...

分享119个ASP.NET源码总有一个是你想要的_千博二手车源码v2023 build 1120-程序员宅基地

文章浏览阅读202次。分享119个ASP.NET源码总有一个是你想要的_千博二手车源码v2023 build 1120

【C++缺省函数】 空类默认产生的6个类成员函数_空类默认产生哪些类成员函数-程序员宅基地

文章浏览阅读1.8k次。版权声明:转载请注明出处 http://blog.csdn.net/irean_lau。目录(?)[+]1、缺省构造函数。2、缺省拷贝构造函数。3、 缺省析构函数。4、缺省赋值运算符。5、缺省取址运算符。6、 缺省取址运算符 const。[cpp] view plain copy_空类默认产生哪些类成员函数

推荐文章

热门文章

相关标签