优秀的编程知识分享平台

网站首页 > 技术文章 正文

用Python进行机器学习(7)支持向量机SVM算法

nanyue 2025-05-14 15:22:22 技术文章 16 ℃

提到机器学习,一定要提到SVM算法,也就是Support Vector Machine,中文通常翻译为支持向量机,它广泛应用在分类和回归任务中。它的核心思想是找到一个最优的超平面,使得不同类别之间的间隔最大

如果是第一次听,会感觉有点抽象,那么不妨来看下面一个示例图:

在上面这个图中,我们要把红色的方框和绿色的圆圈分开,假设不同的机器学习模型给出了不同的三条线,分别是红色的线、绿色的线和蓝色的线,那么哪种分割的方式最好呢?正常情况来说应该是红色的线分割的最好,为什么呢?因为红色的线离两边要分割的样本点比较远,这样就可以最大限度的保证分割的效果能够确定这条分割线的对应的样本点也叫做支持向量,这就是这个分类方式支持向量机的名字的由来

借助sklearn这个库,要使用svm比较简单,通常来说对于样本数据有两种情况,一种是线性可分,那这种的效果就有点类似于逻辑回归的那种处理情况,一种是线性不可分,此时就可以使用RBF这个核函数,也就是径向基核函数,这个核函数也叫高斯核,一般来说是用的最多的,当然也可以选择其他的,比如多项式相关的poly核函数。

我们这里直接来看代码实现吧,代码如下:

import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_blobs, make_circles
from sklearn.svm import SVC

# 生成线性可分数据
X_linear, y_linear = make_blobs(
    n_samples=100, # 样本数量
    centers=2, # 类别数量
    random_state=42, # 随机种子
    cluster_std=1.0 # 簇的标准差
)

# 生成线性不可分数据
X_nonlinear, y_nonlinear = make_circles(
    n_samples=100, # 样本数量
    noise=0.1, # 噪声比例
    factor=0.5, # 内圈和外圈的比例
    random_state=42
)

# 创建线性 SVM 模型并训练
svm_linear = SVC(kernel='linear')
svm_linear.fit(X_linear, y_linear)

# 创建非线性 SVM 模型(使用 RBF 核)并训练
svm_nonlinear = SVC(kernel='rbf', gamma='scale')
svm_nonlinear.fit(X_nonlinear, y_nonlinear)

def plot_svm_decision_boundary(svm_clf, X, y, ax):
    """
    绘制 SVM 的决策边界和支持向量
    :param svm_clf: SVM 模型
    :param X: 特征数据
    :param y: 标签数据
    :param ax: 绘图坐标轴
    """
    ax.scatter(X[:, 0], X[:, 1], c=y, s=30, cmap=plt.cm.Paired)

    # 创建网格来计算决策边界
    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 = svm_clf.decision_function(xy).reshape(XX.shape)

    # 绘制决策边界和间隔
    ax.contour(XX, YY, Z, colors='k', levels=[-1, 0, 1], alpha=0.5, linestyles=['--', '-', '--'])
    # 绘制支持向量
    ax.scatter(svm_clf.support_vectors_[:, 0], svm_clf.support_vectors_[:, 1], s=100,
               linewidth=1, facecolors='none', edgecolors='k')

    ax.set_xlim(xlim)
    ax.set_ylim(ylim)

# 创建画布
fig, axes = plt.subplots(1, 2, figsize=(12, 5))

# 绘制线性 SVM 结果
plot_svm_decision_boundary(svm_linear, X_linear, y_linear, axes[0])
axes[0].set_title("Linear SVM")

# 绘制非线性 SVM 结果
plot_svm_decision_boundary(svm_nonlinear, X_nonlinear, y_nonlinear, axes[1])
axes[1].set_title("RBF SVM")

plt.show()

上面我们分别使用线性可分和线性不可分的核函数来进行分类,虽然代码看上去有点长,但是大部分都是绘图的代码,主要的逻辑只需要新建一个SVC类的实例,然后调用其fit方法就可以了,我们来看一下分别对应的分类效果吧,首先是线性可分的这个:

然后是线性不可分的这个:

线性可分的比较好理解,对于线性不可分的这个,我们这里是一个圆形,也就是这个圆的外边和里面是两类,而带有边缘的点就是支持向量,SVM算法会保证这些支持向量的间隔尽可能的大,而那些没有边缘的点就不是支持向量。可以看到,SVM算法在处理这种非线性可分的数据时还是很强的。

Tags:

最近发表
标签列表