重生之从零开始的神经网络算法学习之路——第五篇 超极限深入Scikit-learn(支持向量机与核方法)

当年戚继光抗倭,面对复杂多变的海岸线地形,需要灵活调整战术,有时直击要害,有时迂回包抄。而今重生后的你,在掌握了降维技术后,正准备迎接机器学习中另一个强大武器——支持向量机(SVM)与核方法,学习如何应对非线性分类问题的挑战。

前情回顾

在第四篇中,你成功使用PCA对葡萄酒数据进行降维,掌握了高维数据处理的精髓。此刻,你站在新的起点上,准备探索机器学习中另一重要技术——支持向量机,特别是其处理非线性问题的核方法。

支持向量机:从线性到非线性的分类艺术

与之前学习的算法不同,SVM的核心思想是寻找一个最优超平面,使得两个类别之间的间隔最大化。这就像戚继光布阵时,总是选择最有利的地形,让军队与敌人保持最大安全距离。

为何选择SVM和月亮/环形数据集?

SVM因其在处理高维数据和小样本问题上的优异表现而闻名,而核方法使其能够处理非线性可分问题。月亮数据集和环形数据集都是典型的非线性可分数据,非常适合展示SVM和核方法的威力。

实验五:支持向量机与核方法在非线性分类中的应用

1. 环境准备

确保已安装必要的库:

pip install scikit-learn matplotlib numpy pandas scipy -i https://pypi.tuna.tsinghua.edu.cn/simple

2. 代码实现

代码可以直接拉取,远程仓库代码地址:https://gitee.com/cmx1998/Scikit-Learning.git

  • 具体文件为Scikit-learn-5.py

3. 代码解析

这段代码实现了以下功能:

  1. 数据生成与可视化:生成月亮和环形数据集,并可视化其分布
  2. 不同核函数SVM分类:使用线性核、多项式核和RBF核训练SVM模型
  3. 决策边界可视化:对每个核函数绘制决策边界,直观理解分类机制
  4. 超参数调优:对RBF核和多项式核进行超参数调优,使用网格搜索寻找最优参数
  5. 性能对比与分析:比较不同核函数在相同数据集上的性能
  • 导入所需模块
from ScikitLearnBase import ScikitLearnExperiment, setup_chinese_font
from sklearn.datasets import make_moons, make_circles
from sklearn.svm import SVC
from sklearn.model_selection import GridSearchCV, RandomizedSearchCV, train_test_split
from sklearn.metrics import accuracy_score
import numpy as np
import matplotlib.pyplot as plt
import time
from scipy.stats import loguniform, randint
  • 1、生成数据集并可视化
moons_X, moons_y = make_moons(n_samples=500, noise=0.2, random_state=42)
circles_X, circles_y = make_circles(n_samples=500, noise=0.1, factor=0.5, random_state=42)

fig, axes = plt.subplots(1, 2, figsize=(15, 6))
axes[0].scatter(moons_X[:, 0], moons_X[:, 1], c=moons_y, cmap=plt.cm.coolwarm, s=50, edgecolors='k', alpha=0.7)
axes[0].set_title('月亮数据集 (Moons)')
axes[1].scatter(circles_X[:, 0], circles_X[:, 1], c=circles_y, cmap=plt.cm.coolwarm, s=50, edgecolors='k', alpha=0.7)
axes[1].set_title('环形数据集 (Circles)')
  • 2、使用不同核函数的SVM进行分类
kernels = ['linear', 'poly', 'rbf']
datasets = {
    '月亮数据集': (moons_X, moons_y),
    '环形数据集': (circles_X, circles_y)
}

for dataset_name, (X, y) in datasets.items():
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
    # 标准化数据
    X_train = scaler.fit_transform(X_train)
    X_test = scaler.transform(X_test)
    
    for kernel in kernels:
        if kernel == 'poly':
            svm = SVC(kernel=kernel, degree=3, random_state=42)
        else:
            svm = SVC(kernel=kernel, random_state=42)
        
        svm.fit(X_train, y_train)
        y_pred = svm.predict(X_test)
        accuracy = accuracy_score(y_test, y_pred)
  • 3、绘制决策边界
def plot_decision_boundary(X, y, model, ax, title):
    h = 0.02  # 网格步长
    x_min, x_max = X[:, 0].min() - 0.5, X[:, 0].max() + 0.5
    y_min, y_max = X[:, 1].min() - 0.5, X[:, 1].max() + 0.5
    xx, yy = np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h))
    
    Z = model.predict(np.c_[xx.ravel(), yy.ravel()])
    Z = Z.reshape(xx.shape)
    
    ax.contourf(xx, yy, Z, alpha=0.4, cmap=plt.cm.coolwarm)
    ax.scatter(X[:, 0], X[:, 1], c=y, cmap=plt.cm.coolwarm, s=30, edgecolors='k', alpha=0.7)
    ax.set_title(title)
  • 4、超参数调优
# 定义参数分布
rbf_param_dist = {
    'C': loguniform(1e-2, 1e3),
    'gamma': loguniform(1e-3, 1e2)
}

poly_param_dist = {
    'C': loguniform(1e-1, 1e2),
    'gamma': loguniform(1e-2, 1e1),
    'degree': randint(2, 5)
}

# 使用随机搜索进行超参数调优
search = RandomizedSearchCV(
    estimator,
    param_dist,
    n_iter=30,
    cv=5,
    scoring='accuracy',
    n_jobs=-1,
    random_state=42
)
search.fit(X_train, y_train)

4. 实际运行结果

运行代码后,实际输出如下:

============================================================
实验:支持向量机与核方法在非线性分类任务中的应用
============================================================
配置信息:
- 搜索方法: 随机搜索
- 使用CPU核心数: 所有

1. 生成月亮和环形数据集并可视化
图表已保存为 'Scikit-Learning/img\原始数据集分布.png'
2. 使用不同核函数的SVM进行分类

处理 月亮数据集:
  使用 linear 核函数...
    准确率: 0.8667, 训练时间: 0.0061秒
  使用 poly 核函数...
    准确率: 0.8867, 训练时间: 0.0025秒
  使用 rbf 核函数...
    准确率: 0.9733, 训练时间: 0.0036秒

处理 环形数据集:
  使用 linear 核函数...
    准确率: 0.5267, 训练时间: 0.0050秒
  使用 poly 核函数...
    准确率: 0.6467, 训练时间: 0.0079秒
  使用 rbf 核函数...
    准确率: 0.9867, 训练时间: 0.0040秒

3. 绘制决策边界
图表已保存为 'Scikit-Learning/img\月亮数据集_决策边界.png'
图表已保存为 'Scikit-Learning/img\环形数据集_决策边界.png'

4. 超参数调优

对 月亮数据集 进行超参数调优:
  RBF核调优:
  运行 1/5: 最佳参数 {'C': np.float64(45.70563099801453), 'gamma': np.float64(0.9846738873614566)}, 交叉验证准确率: 0.9743, 测试集准确率: 0.9733, 搜索时间: 11.72秒
  运行 2/5: 最佳参数 {'C': np.float64(45.70563099801453), 'gamma': np.float64(0.9846738873614566)}, 交叉验证准确率: 0.9886, 测试集准确率: 0.9600, 搜索时间: 0.32秒
  运行 3/5: 最佳参数 {'C': np.float64(45.70563099801453), 'gamma': np.float64(0.9846738873614566)}, 交叉验证准确率: 0.9743, 测试集准确率: 0.9933, 搜索时间: 0.30秒
  运行 4/5: 最佳参数 {'C': np.float64(45.70563099801453), 'gamma': np.float64(0.9846738873614566)}, 交叉验证准确率: 0.9829, 测试集准确率: 0.9667, 搜索时间: 0.30秒
  运行 5/5: 最佳参数 {'C': np.float64(1.9069966103000422), 'gamma': np.float64(8.43101393208247)}, 交叉验证准确率: 0.9800, 测试集准确率: 0.9600, 搜索时间: 0.29秒
  平均交叉验证准确率: 0.9800
  平均搜索时间: 2.59秒
  最常见参数组合: {'C': np.float64(45.70563099801453), 'gamma': np.float64(0.9846738873614566)}
  多项式核调优:
  运行 1/2: 最佳参数 {'C': np.float64(1.4899847475658243), 'degree': 3, 'gamma': np.float64(0.9717775305059632)}, 交叉验证准确率: 0.8714, 测试集准确率: 0.8467, 搜索时间: 87.37秒
  运行 2/2: 最佳参数 {'C': np.float64(1.4899847475658243), 'degree': 3, 'gamma': np.float64(0.9717775305059632)}, 交叉验证准确率: 0.8829, 测试集准确率: 0.8533, 搜索时间: 105.91秒
  平均交叉验证准确率: 0.8772
  平均搜索时间: 96.64秒
  最常见参数组合: {'C': np.float64(1.4899847475658243), 'degree': 3, 'gamma': np.float64(0.9717775305059632)}
图表已保存为 'Scikit-Learning/img\月亮数据集_调优对比.png'

对 环形数据集 进行超参数调优:
  RBF核调优:
  运行 1/5: 最佳参数 {'C': np.float64(45.70563099801453), 'gamma': np.float64(0.9846738873614566)}, 交叉验证准确率: 0.9971, 测试集准确率: 0.9800, 搜索时间: 0.42秒
  运行 2/5: 最佳参数 {'C': np.float64(0.0407559644007287), 'gamma': np.float64(0.2991469302130217)}, 交叉验证准确率: 0.9943, 测试集准确率: 0.9733, 搜索时间: 0.32秒
  运行 3/5: 最佳参数 {'C': np.float64(673.2248920775328), 'gamma': np.float64(11.015056790269638)}, 交叉验证准确率: 0.9800, 测试集准确率: 0.9933, 搜索时间: 0.26秒
  运行 4/5: 最佳参数 {'C': np.float64(0.09962513222055108), 'gamma': np.float64(0.37253938395788866)}, 交叉验证准确率: 0.9914, 测试集准确率: 0.9733, 搜索时间: 0.25秒
  运行 5/5: 最佳参数 {'C': np.float64(10.129197956845726), 'gamma': np.float64(3.4702669886504163)}, 交叉验证准确率: 0.9971, 测试集准确率: 0.9867, 搜索时间: 0.24秒
  平均交叉验证准确率: 0.9920
  平均搜索时间: 0.30秒
  最常见参数组合: {'C': np.float64(45.70563099801453), 'gamma': np.float64(0.9846738873614566)}
  多项式核调优:
  运行 1/2: 最佳参数 {'C': np.float64(60.25271171095384), 'degree': 4, 'gamma': np.float64(5.829384542994738)}, 交叉验证准确率: 0.9886, 测试集准确率: 0.9867, 搜索时间: 0.25秒
  运行 2/2: 最佳参数 {'C': np.float64(6.838478430964044), 'degree': 2, 'gamma': np.float64(0.19762189340280073)}, 交叉验证准确率: 0.9885, 测试集准确率: 0.9867, 搜索时间: 0.93秒
  平均交叉验证准确率: 0.9886
  平均搜索时间: 0.59秒
  最常见参数组合: {'C': np.float64(60.25271171095384), 'degree': 4, 'gamma': np.float64(5.829384542994738)}
图表已保存为 'Scikit-Learning/img\环形数据集_调优对比.png'

5. 性能对比与分析

总训练时间: 0.03秒
总调优时间: 216.61秒
总运行时间: 216.64秒

性能对比表格:
========================================================================================================================
数据集             核函数          准确率        训练时间(秒)         搜索时间(秒)         平均CV得分       最佳参数
========================================================================================================================
月亮数据集           linear       0.8667     0.0061          N/A             N/A
月亮数据集           poly         0.8867     0.0025          N/A             N/A
月亮数据集           rbf          0.9733     0.0036          N/A             N/A
月亮数据集           rbf(调优)      0.9733     N/A             2.59            0.9800       {'C': np.float64(45.70563099801453), 'gamma': np.float64(0.9846738873614566)}
月亮数据集           poly(调优)     0.8867     N/A             96.64           0.8772       {'C': np.float64(1.4899847475658243), 'degree': 3, 'gamma': np.float64(0.9717775305059632)}
环形数据集           linear       0.5267     0.0050          N/A             N/A
环形数据集           poly         0.6467     0.0079          N/A             N/A
环形数据集           rbf          0.9867     0.0040          N/A             N/A
环形数据集           rbf(调优)      0.9867     N/A             0.30            0.9920       {'C': np.float64(45.70563099801453), 'gamma': np.float64(0.9846738873614566)}
环形数据集           poly(调优)     0.9867     N/A             0.59            0.9886       {'C': np.float64(60.25271171095384), 'degree': 4, 'gamma': np.float64(5.829384542994738)} 
========================================================================================================================

核函数选择与数据分布关系分析:
1. 线性核: 在非线性可分数据上表现较差,适合线性可分数据
2. 多项式核: 通过调整阶数可以适应一定程度的非线性,但可能过拟合
3. RBF核: 最适合处理复杂的非线性可分数据,通过调整gamma参数控制决策边界复杂度
4. 超参数调优: 多次运行网格搜索可以减少随机性影响,找到更稳定的参数组合
5. 月亮数据集: 由于两个半月形有部分重叠,RBF核表现最好
6. 环形数据集: 完全非线性可分,RBF核明显优于其他核函数
7. 多次运行取平均: 通过多次运行网格搜索并取平均结果,可以减少数据划分随机性的影响
8. 多项式核调优: 通过搜索degree参数,可以找到最适合数据复杂度的多项式阶数
============================================================
实验顺利完成!
============================================================

同时,程序还会生成原始数据集分布图、决策边界图和调优对比图的可视化结果。

深入理解

1. SVM算法原理

支持向量机是一种基于统计学习理论的二分类模型,其基本模型是定义在特征空间上的间隔最大的线性分类器。算法的核心思想包括:

  1. 间隔最大化:寻找一个超平面,使得两个类别之间的间隔最大化
  2. 支持向量:距离超平面最近的样本点称为支持向量,决定了超平面的位置
  3. 核技巧:通过核函数将原始特征空间映射到高维空间,解决非线性问题

2. 核方法的作用

核方法是SVM处理非线性问题的关键,常见核函数包括:

  • 线性核:$K(x_i, x_j) = x_i^T x_j$,适用于线性可分数据
  • 多项式核:$K(x_i, x_j) = (x_i^T x_j + r)^d$,通过调整d控制复杂度
  • RBF核(径向基函数):$K(x_i, x_j) = \exp(-\gamma |x_i - x_j|^2)$,通过调整γ控制决策边界形状

结果分析:从运行结果可以看出,RBF核在两种非线性数据集上都取得了最佳性能,特别是在环形数据集上达到了98.67%的准确率。

3. 超参数调优的重要性

通过超参数调优,我们发现:

  1. RBF核调优效果明显:调优后的RBF核在月亮数据集上平均交叉验证准确率达到98.00%,比调优前有所提升
  2. 多项式核调优有限:调优对多项式核的提升相对有限,可能因为多项式核本身适应能力不如RBF核
  3. 参数敏感性:RBF核对C和γ参数较为敏感,合适的参数组合能显著提升性能
  4. 计算代价:超参数调优需要较多计算资源(尤其是多项式核调优耗时96.64秒),但能带来性能提升

4. 决策边界分析

通过可视化决策边界,我们可以直观理解不同核函数的分类机制:

  • 线性核:只能产生直线决策边界,无法处理环形和月亮形数据
  • 多项式核:能产生曲线决策边界,但形状较为规则
  • RBF核:能产生非常灵活的决策边界,完美适应复杂的数据分布

这些可视化结果帮助我们理解为什么RBF核在非线性问题上表现优异。

支持向量机:灵活应对复杂问题的利器

1. 为什么选择SVM?

SVM在处理复杂问题时的优势:

  • 高维数据处理:适合特征维度高于样本数量的情况
  • 小样本学习:基于结构风险最小化原理,泛化能力强
  • 非线性问题:通过核技巧处理复杂的非线性决策边界
  • 全局最优解:凸优化问题,能找到全局最优解

2. SVM的应用场景

SVM在各个领域都有广泛应用:

  • 文本分类:高维稀疏文本特征的处理
  • 图像识别:手写数字识别、人脸检测等
  • 生物信息学:基因分类、蛋白质结构预测
  • 金融风控:信用评分、欺诈检测

3. 核函数的选择策略

选择合适的核函数是关键决策:

  • 线性核:数据大致线性可分时首选,计算效率高
  • 多项式核:数据具有明显多项式特征时使用
  • RBF核:默认选择,适合大多数非线性问题
  • 自定义核:针对特定领域问题设计专用核函数

遇到的挑战与解决

在完成这个SVM项目的过程中,你遇到了一些新挑战:

  1. 核函数选择:通过实验比较不同核函数的性能,确定了RBF核的优越性
  2. 超参数调优:使用随机搜索高效地寻找最优参数组合,发现RBF核的最佳参数组合为
  3. 决策边界可视化:掌握了如何可视化非线性决策边界,直观理解模型行为
  4. 性能评估:通过准确率和决策边界复杂度综合评估模型性能
  5. 计算效率:平衡模型复杂度和计算资源,选择适合的核函数和参数

结语

完成了SVM与核方法项目后,你不仅掌握了这一强大分类算法,还深入理解了核方法处理非线性问题的精髓。这就像戚继光学会了根据不同地形灵活运用战术,而不是固守一成不变的阵型。

值得注意的是,SVM虽然强大,但也有其局限性。核函数和参数的选择需要经验和实验,计算复杂度随数据量增长而快速增加,特别是在使用非线性核时。对于超大规模数据集,线性SVM或基于随机特征的方法可能更合适。

这个实验的价值在于让你熟悉SVM的基本原理和核方法的应用,为处理复杂的非线性分类问题打下基础。实际应用中,需要根据数据特性和计算资源谨慎选择核函数和参数。

机器学习之路如同用兵布阵,需要根据敌情地形灵活调整战术。SVM与核方法的大门已经向你敞开,前方还有更多强大的算法等待你去探索。


下集预告:Scikit库的学习可能就暂时告一段落了,可能要先马上投入到PyTorch库的学习中去

posted on 2025-09-02 17:18  cmxcxd  阅读(21)  评论(0)    收藏  举报