人工智能【第10篇】支持向量机SVM:寻找最优分类超平面(长文+代码实现)

作者的话 :在前面的文章中,我们学习了决策树和随机森林。今天我们要探索的是机器学习中最优雅、最强大的算法之一------支持向量机(SVM)。SVM不仅理论基础扎实,而且在高维数据处理和小样本学习中表现出色。本文将带你深入理解SVM的原理、核技巧和实际应用!


一、SVM概述

1.1 什么是支持向量机?

**支持向量机(Support Vector Machine, SVM)**是一种二分类模型,其基本模型是定义在特征空间上的间隔最大的线性分类器。

核心思想:找到一个超平面,使得两个类别之间的间隔(Margin)最大化。

SVM的特点

  • 泛化能力强,不容易过拟合
  • 适用于高维数据
  • 仅依赖支持向量,计算效率高
  • 通过核技巧处理非线性问题

1.2 线性可分与线性不可分

类型 定义 解决方法
线性可分 存在超平面能完美分开两类样本 硬间隔SVM
近似线性可分 大部分样本可分,少量噪声 软间隔SVM
线性不可分 不存在线性超平面可分开 核技巧+软间隔

二、线性可分SVM:硬间隔最大化

2.1 超平面与间隔

在n维空间中,超平面可以表示为:w^T x + b = 0

其中 w 是法向量,b 是偏置。

间隔(Margin):两个类别支持向量到超平面的距离之和:Margin = 2 / ||w||

2.2 优化问题

SVM的目标是最大化间隔,等价于最小化 ||w||^2:

min_{w,b} (1/2)||w||^2

约束条件:y_i(w^T x_i + b) >= 1, i = 1, 2, ..., n

2.3 拉格朗日对偶问题

使用拉格朗日乘子法,将原问题转化为对偶问题。其中 alpha_i 是拉格朗日乘子,非零的 alpha_i 对应的样本就是支持向量

三、软间隔SVM:处理噪声数据

3.1 为什么需要软间隔?

现实数据往往存在噪声或异常点,硬间隔SVM对这些点过于敏感。软间隔SVM允许某些样本违反约束,引入松弛变量

3.2 软间隔优化问题

min_{w,b,xi} (1/2)||w||^2 + C * sum(xi_i)

其中 C 是惩罚参数:C越大,对误分类惩罚越重;C越小,允许更多误分类。

四、核技巧:处理非线性问题

4.1 核函数原理

对于线性不可分的数据,可以通过**核技巧(Kernel Trick)**将数据映射到高维空间。

4.2 常用核函数对比

核函数 适用场景
线性核 特征多,线性可分
多项式核 图像处理
RBF核(高斯核) 通用,非线性问题
Sigmoid核 神经网络类似

4.3 RBF核参数gamma

gamma较大时每个样本影响范围小,模型复杂容易过拟合;gamma较小时每个样本影响范围大,模型简单可能欠拟合。

五、SVM的Python实现

5.1 使用sklearn的SVM

复制代码
import numpy as np
import matplotlib.pyplot as plt
from sklearn import svm
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import accuracy_score

# 生成数据
X, y = make_classification(n_samples=500, n_features=2, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3)

# 标准化
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)

# 创建线性SVM
linear_svm = svm.SVC(kernel=linear, C=1.0)
linear_svm.fit(X_train_scaled, y_train)

# 预测
y_pred = linear_svm.predict(X_test_scaled)
print(f准确率: {accuracy_score(y_test, y_pred):.4f})
print(f支持向量数: {len(linear_svm.support_)})

5.2 不同核函数对比

复制代码
# 生成非线性数据
from sklearn.datasets import make_moons
X_moon, y_moon = make_moons(n_samples=500, noise=0.1, random_state=42)
X_train_m, X_test_m, y_train_m, y_test_m = train_test_split(
    X_moon, y_moon, test_size=0.3, random_state=42)

# 定义不同核函数
kernels = {
    Linear: svm.SVC(kernel=linear, C=1.0),
    RBF: svm.SVC(kernel=rbf, C=1.0, gamma=scale),
    Polynomial: svm.SVC(kernel=poly, C=1.0, degree=3)
}

for name, model in kernels.items():
    model.fit(X_train_m, y_train_m)
    acc = model.score(X_test_m, y_test_m)
    print(f{name}: {acc:.4f})

5.3 参数调优

复制代码
from sklearn.model_selection import GridSearchCV

param_grid = {
    C: [0.1, 1, 10, 100],
    gamma: [scale, auto, 0.001, 0.01, 0.1, 1],
    kernel: [rbf, linear]
}

grid_search = GridSearchCV(
    svm.SVC(random_state=42),
    param_grid,
    cv=5,
    scoring=accuracy
)

grid_search.fit(X_train, y_train)
print(f最优参数: {grid_search.best_params_})

六、实战案例:手写数字识别

6.1 加载数据

复制代码
from sklearn.datasets import load_digits
from sklearn.metrics import confusion_matrix
import seaborn as sns

# 加载手写数字数据集
digits = load_digits()
X_digits = digits.data
y_digits = digits.target

print(f数据形状: {X_digits.shape})
print(f类别: {np.unique(y_digits)})

6.2 训练SVM

复制代码
# 划分数据集
X_train_d, X_test_d, y_train_d, y_test_d = train_test_split(
    X_digits, y_digits, test_size=0.3, random_state=42)

# 标准化
scaler_d = StandardScaler()
X_train_d_scaled = scaler_d.fit_transform(X_train_d)
X_test_d_scaled = scaler_d.transform(X_test_d)

# 训练SVM(RBF核)
svm_digits = svm.SVC(kernel=rbf, C=10, gamma=0.001)
svm_digits.fit(X_train_d_scaled, y_train_d)

# 评估
train_acc = svm_digits.score(X_train_d_scaled, y_train_d)
test_acc = svm_digits.score(X_test_d_scaled, y_test_d)
print(f训练准确率: {train_acc:.4f})
print(f测试准确率: {test_acc:.4f})

6.3 混淆矩阵

复制代码
# 绘制混淆矩阵
y_pred_d = svm_digits.predict(X_test_d_scaled)
cm = confusion_matrix(y_test_d, y_pred_d)

plt.figure(figsize=(10, 8))
sns.heatmap(cm, annot=True, fmt=d, cmap=Blues)
plt.xlabel(Predicted)
plt.ylabel(Actual)
plt.title(Confusion Matrix)
plt.show()

七、SVM回归(SVR)

复制代码
from sklearn.svm import SVR
from sklearn.datasets import make_regression

# 生成回归数据
X_reg, y_reg = make_regression(n_samples=500, n_features=1, noise=15)
X_train_r, X_test_r, y_train_r, y_test_r = train_test_split(
    X_reg, y_reg, test_size=0.3)

# 训练SVR
svr = SVR(kernel=rbf, C=100, gamma=0.1)
svr.fit(X_train_r, y_train_r)

# 预测
y_pred_r = svr.predict(X_test_r)
print(fR²: {r2_score(y_test_r, y_pred_r):.4f})

八、SVM的优缺点

8.1 优点

  • 泛化能力强:通过最大化间隔,具有良好的泛化性能
  • 维度无关性:在高维空间中仍有效
  • 样本效率高:仅依赖支持向量,节省内存
  • 核技巧:通过核函数处理非线性问题

8.2 缺点

  • 训练速度慢:大规模数据集训练时间较长
  • 对参数敏感:核函数和参数选择对性能影响大
  • 对噪声敏感:异常值会影响超平面位置
  • 仅直接支持二分类:多分类需使用OvO或OvR

九、适用场景

场景 是否适合 说明
高维数据 文本分类、基因数据
小样本 训练样本少但特征多
非线性问题 使用RBF核处理
大规模数据 训练时间过长

十、总结

核心要点

  • 线性SVM:最大化间隔,硬间隔/软间隔
  • 核技巧:通过核函数将数据映射到高维空间
  • RBF核:最常用核函数,需调优C和gamma参数
  • SVR:SVM的回归版本

参数调优建议

  • C参数:从默认值1开始,增大C减少误分类
  • gamma参数:控制RBF核的影响范围,通常从0.001开始
  • 核函数:线性数据用linear,非线性用rbf
  • 交叉验证:使用GridSearchCV搜索最优参数

下一篇预告:【第11篇】K近邻算法KNN:简单有效的分类方法


本文为系列第10篇,深入讲解了SVM的原理、核技巧和应用。有任何问题欢迎在评论区交流!

相关推荐
晨启AI1 小时前
GPT-5.5 来了!OpenAI 最新提示词指南深度解读
大数据·人工智能·ai·提示词
wayz111 小时前
Day 18 编程实战:Keras搭建MLP神经网络
人工智能·神经网络·keras
凯歌的博客1 小时前
MetaGPT和Superpowers区别, AI编程
人工智能·ai编程
NaMM CHIN1 小时前
Spring Boot + Spring AI快速体验
人工智能·spring boot·spring
一切皆是因缘际会1 小时前
可落地数字生命工程:从记忆厮杀到自我意识觉醒全链路,AGI内生智能硅基生命心智建模
人工智能·深度学习·算法·机器学习·ai·系统架构·agi
70asunflower1 小时前
从CPU市场到AI算力格局:一场关于技术路线、商业逻辑与生态锁定的深度梳理
人工智能
地球资源数据云1 小时前
中国陆地生态系统主要植物功能特征空间分布数据
大数据·数据库·人工智能·机器学习
AI创界者2 小时前
最新RedMix-Ernie-Image整合包,解压即用:文生图、图生图,n卡8G显存玩转4K
人工智能
月诸清酒2 小时前
51-260503 AI 科技日报 (ChatGPT图像功能用户量暴涨,新用户占六成)
人工智能·chatgpt