当前位置: 首页 > news >正文

30天打牢数模基础-SVM讲解

 

案例代码实现

1.导入必要的库

首先需要安装所需库(pip install numpy pandas matplotlib scikit-learn),然后导入:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.svm import SVC
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import GridSearchCV

2.模拟葡萄酒数据

根据案例中的表格,生成10个样本的特征(酒精含量、柠檬酸含量)和标签(红葡萄酒+1、白葡萄酒-1):

def generate_wine_data():"""模拟葡萄酒数据(含2个噪声点)"""# 特征:[酒精含量(%vol), 柠檬酸含量(g/L)]X = np.array([[8.5, 0.2],   # 红葡萄酒(正常)[9.0, 0.3],   # 红葡萄酒(正常)[9.5, 0.4],   # 红葡萄酒(支持向量)[10.0, 0.5],  # 红葡萄酒(正常)[13.0, 0.7],  # 红葡萄酒(噪声点,跑到白葡萄酒区域)[11.0, 0.6],  # 白葡萄酒(正常)[11.5, 0.7],  # 白葡萄酒(正常)[12.0, 0.8],  # 白葡萄酒(支持向量)[12.5, 0.9],  # 白葡萄酒(正常)[10.5, 0.5]   # 白葡萄酒(噪声点,跑到红葡萄酒区域)])# 标签:+1=红葡萄酒,-1=白葡萄酒y = np.array([+1, +1, +1, +1, +1, -1, -1, -1, -1, -1])return X, y# 生成数据
X, y = generate_wine_data()

3.数据预处理(特征标准化)

SVM对特征缩放敏感,需将特征缩放到均值为0、方差为1(避免某一特征主导间隔计算):

def preprocess_data(X):"""标准化特征(均值0,方差1)"""scaler = StandardScaler()X_scaled = scaler.fit_transform(X)return X_scaled, scaler# 标准化数据
X_scaled, scaler = preprocess_data(X)

4.定义决策边界绘制函数(可视化工具)

为了直观看到SVM的分类边界,定义一个函数绘制散点图和决策边界:

def plot_decision_boundary(model, X, y, scaler, title):"""绘制SVM决策边界和支持向量参数:model:训练好的SVM模型X:原始特征数据(未标准化)y:标签scaler:标准化器(用于还原特征尺度)title:图标题"""# 生成网格点(覆盖原始数据的范围,统一扩展0.5避免边界点被截断)x1_min, x1_max = X[:, 0].min() - 0.5, X[:, 0].max() + 0.5x2_min, x2_max = X[:, 1].min() - 0.5, X[:, 1].max() + 0.5  # 修改:统一扩展0.5,保持坐标轴比例协调xx1, xx2 = np.meshgrid(np.linspace(x1_min, x1_max, 100),np.linspace(x2_min, x2_max, 100))# 标准化网格点(用训练好的scaler)xx_scaled = scaler.transform(np.c_[xx1.ravel(), xx2.ravel()])# 预测网格点的类别Z = model.predict(xx_scaled)Z = Z.reshape(xx1.shape)# 绘制决策边界(contour:等高线图)plt.contourf(xx1, xx2, Z, alpha=0.3, cmap='coolwarm')# 绘制原始数据点(红葡萄酒=红点,白葡萄酒=蓝点)plt.scatter(X[y == +1, 0], X[y == +1, 1], c='red', label='红葡萄酒(+1)')plt.scatter(X[y == -1, 0], X[y == -1, 1], c='blue', label='白葡萄酒(-1)')# 绘制支持向量(用圆圈标记)support_vectors = scaler.inverse_transform(model.support_vectors_)plt.scatter(support_vectors[:, 0], support_vectors[:, 1], s=150, edgecolor='black', facecolor='none', label='支持向量')# 设置图标题和标签plt.title(title)plt.xlabel('酒精含量(%vol)')plt.ylabel('柠檬酸含量(g/L)')plt.legend()plt.show()

5.训练线性核SVM(硬间隔/软间隔)

线性核适用于近似线性可分数据(案例中大部分样本符合线性规律,仅含少量噪声),调整C参数控制软间隔:

def train_linear_svm(X_scaled, y, C=1.0):"""训练线性核SVM模型"""model = SVC(kernel='linear', C=C)  # kernel='linear':线性核;C:软间隔惩罚参数model.fit(X_scaled, y)return model# 训练线性核SVM(C=1.0,中等惩罚)
linear_model = train_linear_svm(X_scaled, y, C=1.0)# 绘制决策边界
plot_decision_boundary(linear_model, X, y, scaler, title='线性核SVM分类边界(C=1.0)')

6.训练RBF核SVM(处理非线性数据)

RBF核(径向基函数核)是常用的非线性核(适用于数据分布非线性的场景,如环形、螺旋形)。需调整C(惩罚)和gamma(带宽,控制局部影响):

def train_rbf_svm(X_scaled, y, param_grid=None):"""训练RBF核SVM模型(用网格搜索调参)"""if param_grid is None:# 默认参数网格(C:惩罚,gamma:带宽)param_grid = {'C': [0.1, 1, 10, 100], 'gamma': [0.01, 0.1, 1, 10]}# 网格搜索(5折分层交叉验证,保留类别比例)grid = GridSearchCV(SVC(kernel='rbf'), param_grid, cv=5, scoring='accuracy')  # 补充:明确评分标准为准确率grid.fit(X_scaled, y)print(f"RBF核最佳参数:{grid.best_params_}")print(f"RBF核最佳交叉验证准确率:{grid.best_score_:.2f}")return grid.best_estimator_# 训练RBF核SVM(网格搜索调参)
rbf_model = train_rbf_svm(X_scaled, y)# 绘制决策边界
plot_decision_boundary(rbf_model, X, y, scaler, title='RBF核SVM分类边界(最佳参数)')

7.主程序(整合所有步骤)

if __name__ == "__main__":# 1. 生成数据X, y = generate_wine_data()print("原始数据:")print(pd.DataFrame(np.c_[X, y], columns=['酒精含量', '柠檬酸含量', '标签']))# 2. 预处理数据X_scaled, scaler = preprocess_data(X)# 3. 训练线性核SVMprint("\n=== 线性核SVM ===")linear_model = train_linear_svm(X_scaled, y, C=1.0)print(f"线性核支持向量数量(红葡萄酒/白葡萄酒):{linear_model.n_support_}")  # 补充:明确两类支持向量数量# 4. 训练RBF核SVM(调参)print("\n=== RBF核SVM(网格搜索调参) ===")rbf_model = train_rbf_svm(X_scaled, y)print(f"RBF核支持向量数量(红葡萄酒/白葡萄酒):{rbf_model.n_support_}")# 5. 绘制决策边界(线性核+RBF核)plot_decision_boundary(linear_model, X, y, scaler, title='线性核SVM分类边界(C=1.0)')plot_decision_boundary(rbf_model, X, y, scaler, title='RBF核SVM分类边界(最佳参数)')

代码说明与使用指南

1.代码结构

数据生成:generate_wine_data函数模拟案例中的10个样本(含2个噪声点);

数据预处理:preprocess_data函数标准化特征(SVM必做步骤,避免特征尺度差异影响模型);

可视化工具:plot_decision_boundary函数绘制决策边界和支持向量(直观展示SVM工作原理);

模型训练:train_linear_svm(线性核)和train_rbf_svm(RBF核)函数训练模型,其中RBF核用GridSearchCV进行参数调优(5折交叉验证);

主程序:整合所有步骤,输出原始数据、模型参数及支持向量数量,并可视化决策边界。

2.关键参数解释

C(软间隔惩罚系数)

C越大:对误分类样本的惩罚越重,模型更倾向于严格分开所有样本(容易过拟合,如C=100时,噪声点会被强行分类,但间隔很小);

C越小:对误分类样本的惩罚越轻,模型允许更多误分类(容易欠拟合,如C=0.1时,间隔很大,但可能误分类正常点)。

gamma(RBF核带宽参数)

gamma越大:单个样本的影响范围越小(模型更关注局部数据,容易过拟合,如gamma=10时,决策边界会绕开噪声点,但泛化能力差);

gamma越小:单个样本的影响范围越大(模型更关注全局数据,容易欠拟合,如gamma=0.01时,决策边界很平滑,但可能无法分开非线性数据)。

3.运行结果说明

线性核SVM:输出支持向量数量(如红葡萄酒1个、白葡萄酒1个,对应案例中的3号和8号样本),决策边界为直线,间隔较宽,允许噪声点(5号、10号)违反约束(软间隔特性);

RBF核SVM:网格搜索会输出最佳参数(如C=10、gamma=1),决策边界为曲线(处理非线性数据),支持向量数量更多(RBF核更关注局部点,对噪声更敏感)。

4.小白使用建议

修改数据:可在generate_wine_data函数中添加更多样本(如20个),或调整噪声点位置(如将5号样本的酒精含量改为12.0),观察模型对数据变化的敏感性;

调整参数:尝试修改C的值(如C=0.1、C=100),看线性核的决策边界如何变化;尝试修改gamma的值(如gamma=0.01、gamma=10),看RBF核的决策边界如何变化;

更换核函数:可尝试多项式核(kernel='poly',调整degree参数,如degree=2),观察其对非线性数据的处理效果(多项式核适用于低维非线性数据)。

通过运行这份代码,小白能直观理解SVM的最大间隔支持向量软间隔核函数等核心概念,掌握SVM的基本使用方法(数据预处理、模型训练、参数调优、可视化)。

http://www.xdnf.cn/news/1159345.html

相关文章:

  • Python 单例模式几种实现方式
  • Dify 1.6 安装与踩坑记录(Docker 方式)
  • ZooKeeper学习专栏(二):深入 Watch 机制与会话管理
  • 【单片机外部中断实验修改动态数码管0-99】2022-5-22
  • 大语言模型:人像摄影的“达芬奇转世”?——从算法解析到光影重塑的智能摄影革命
  • Vuex 核心知识详解:Vue2Vue3 状态管理指南
  • 【设计模式C#】享元模式(用于解决多次创建对象而导致的性能问题)
  • TypeScript 中替代 Interface 的方案
  • 17.TaskExecutor与ResourceManager交互
  • 对粒子群算法的理解与实例详解
  • 系统思考:整体论
  • 5.2.4 指令执行过程
  • 基于FPGA的多级流水线加法器verilog实现,包含testbench测试文件
  • Muon小记
  • 【unitrix】 6.9 减一操作(sub_one.rs)
  • 数据结构与算法汇总
  • Twisted study notes[2]
  • Node.js worker_threads 性能提升
  • ARM 学习笔记(三)
  • C 语言经典编程题实战:从基础算法到趣味问题全解析
  • python学智能算法(二十六)|SVM-拉格朗日函数构造
  • Beamer-LaTeX学习(教程批注版)【6】
  • AtCoder Beginner Contest 415
  • Linux系统中全名、用户名、主机名的区别
  • Unity学习笔记(五)——3DRPG游戏(2)
  • 《拆解WebRTC:NAT穿透的探测逻辑与中继方案》
  • (苍穹外卖)暑假学习理解P2
  • 平安车管家|中国平安车管家入职测评16PF瑞文IQ测评答题攻略及真题题库
  • UDP中的单播,多播,广播(代码实现)
  • securecrt连接服务器报错 Key exchange failed 怎么办