SVM案例练习:从线性核到RBF核的参数调优实战
发布时间:2026/9/14 3:01:32来源:尧图网络
简介这是一套SVM支持向量机从原理到实战的MATLAB案例练习包面向机器学习初学者和需完成分类、回归任务的开发者覆盖最大间隔超平面、核函数映射、SVR回归、参数C与γ调优等核心知识点。资源共76个文件包含8个m脚本、5个mat数据集、7个html结果展示页面、55张png输出图压缩包仅908KB结构紧凑下载后即可按案例编号运行。目前已有2604人学习下载。预览案例涉及葡萄酒种类识别、上证开盘指数回归预测、PSO/网格搜索/遗传算法优化分类器性能以及信息粒化时序回归预测等每部分都配有源码、数据与可视化结果便于对照学习支持向量机在分类、回归、参数调优上的完整流程与排错思路。1. SVM案例练习为什么总卡在参数与数据准备上很多人学支持向量机SVM都是从最大间隔示意图开始的两类样本之间画一条线并尽量远离两侧的点。可真到自己做SVM案例练习时同样的代码换个数据集准确率就明显往下掉原因往往不在公式推导而在三个没做好的地方特征没有缩放、核函数选错、C和gamma没有联调。SVM的优势场景是样本量几千到几万、特征维度中等的表格型数据决策边界由少数支持向量决定泛化能力通常不错代价是对数据尺度和超参数非常敏感。这篇练习按一条完整链路推进线性软间隔分类、RBF核非线性分类、特征缩放与样本不均衡处理最后落到验证与排错适合想把svm算法真正跑出可用效果的工程师。2. 最小可跑的SVM案例线性核与软间隔的调参逻辑2.1 用scikit-learn跑通SVM分类的最小代码SVM案例练习第一步先别碰核函数。用线性核把可分的二分类问题跑通确认数据格式、训练链路和评估方式都正确再去叠加复杂度。常见做法是用make_blobs生成两组高斯点云并故意把cluster_std调大一点让两类样本存在部分重叠这样C参数的作用才能在后面体现出来。import numpy as np from sklearn.datasets import make_blobs from sklearn.svm import SVC from sklearn.model_selection import train_test_split # 生成两个有重叠的二维高斯点云模拟真实分类场景 X, y make_blobs(n_samples150, centers2, cluster_std1.8, random_state42) X_train, X_test, y_train, y_test train_test_split( X, y, test_size0.3, random_state42) # 线性核SVMC1.0是默认惩罚系数 clf SVC(kernellinear, C1.0) clf.fit(X_train, y_train) print(train acc:, clf.score(X_train, y_train)) print(test acc:, clf.score(X_test, y_test)) print(n support vectors:, clf.support_vectors_.shape[0])这段代码包含SVM案例练习里最核心的四步构造数据、切分训练测试集、实例化SVC并fit、在测试集上评估。kernellinear表示线性核数学上等价于在原特征空间寻找最大间隔超平面C是软间隔的惩罚系数默认1.0它控制模型对错分样本的容忍度。cluster_std1.8让两类点云边界交叠如果完全不重叠任何一组参数都能拿到高分练习就失去了区分度。提示SVC内部用One-vs-One策略处理多分类二分类场景无需额外设置。2.2 画决策边界看支持向量别只盯准确率模型训练完成后案例练习不能停在准确率上。SVM和别的分类器最大的区别在于决策边界只由少数样本决定这些样本就是支持向量。通过support_vectors_属性可以拿到这些点的坐标配合decision_function返回的带符号距离就能把决策边界和间隔边界画在同一张图上。import matplotlib.pyplot as plt def plot_svm_boundary(clf, X, y): # 构造覆盖样本取值范围的网格点 x_min, x_max X[:, 0].min() - 1, X[:, 0].max() 1 y_min, y_max X[:, 1].min() - 1, X[:, 1].max() 1 xx, yy np.meshgrid(np.linspace(x_min, x_max, 400), np.linspace(y_min, y_max, 400)) # decision_function返回样本到决策边界的带符号距离 Z clf.decision_function(np.c_[xx.ravel(), yy.ravel()]) Z Z.reshape(xx.shape) # levels[-1,0,1]分别对应间隔边界和决策边界 plt.contour(xx, yy, Z, levels[-1, 0, 1], colorsk) plt.scatter(X[:, 0], X[:, 1], cy, edgecolorsk) plt.scatter(clf.support_vectors_[:, 0], clf.support_vectors_[:, 1], s100, facecolorsnone, edgecolorsr) plt.show() plot_svm_boundary(clf, X_train, y_train)decision_function输出的是样本到超平面的带符号距离正则、负则各属一类绝对值越大置信度越高。levels[-1, 0, 1]画出的三条线就是间隔边界加决策边界红圈标出的支持向量恰好落在这两条间隔边界上。观察两个关键数字支持向量数量以及它们占训练集的比例。支持向量占比越高说明数据越难分模型越依赖局部样本过拟合风险也在累积。2.3 C参数是SVM案例练习里第一个要调的旋钮C用来权衡间隔最大化和训练误差最小化。C小软间隔宽模型保守训练准确率可能略低但泛化更好C大模型会尽力把每个训练样本分对间隔变窄容易过拟合。调C的常规做法是对数网格扫描再叠加交叉验证避免只凭单次切分的结果做判断。from sklearn.model_selection import cross_val_score for C in [0.01, 0.1, 1.0, 10.0, 100.0]: clf SVC(kernellinear, CC) scores cross_val_score(clf, X, y, cv5, scoringaccuracy) print(fC{C:6.2f} acc{scores.mean():.4f} fstd{scores.std():.4f})cross_val_score把数据切成5折每折轮流做验证集返回5次准确率的均值与标准差。标准差大说明模型对数据切分方式敏感结果不可信。线性核场景下数据量不大时C的影响相对温和但换到RBF核之后C和gamma会互相拉扯情况复杂很多。先记录下表里的现象后一章会用到同样的判断逻辑。C取值间隔宽度对错分的态度典型表现0.01宽容忍较多错分边界平滑训练分数偏低1.0中等少量错分可接受分数与泛化较平衡100.0窄强求训练集全对边界贴样本容易过拟合3. 非线性SVM案例核函数选型、gamma与网格搜索3.1 用make_moons构造一个线性不可分的练习数据集真实项目里几乎没有能直接用一条直线切开的分类问题。SVM处理非线性分类的核心是核技巧不显式做特征映射而是用核函数直接计算样本在高维空间的内积隐式地把原始数据映射到更易分离的空间。练习中最常用的非线性数据集是make_moons生成的月牙形点云。from sklearn.datasets import make_moons # noise越大两个月牙越混叠分类难度越高 X, y make_moons(n_samples300, noise0.15, random_state10) X_train, X_test, y_train, y_test train_test_split( X, y, test_size0.3, random_state10) clf SVC(kernelrbf, C1.0, gamma0.5) clf.fit(X_train, y_train) print(rbf test acc:, clf.score(X_test, y_test))noise0.15是一个适合做练习的基准值太小则线性核也能应付太大则任何模型都很难收敛出好看的边界。kernelrbf使用径向基核这是实际项目中最常用的SVM核它只有一个gamma参数却能拟合绝大多数非线性边界。相比多项式核RBF核参数更少、数值行为更可控这也是它成为默认选项的原因。选核时可以参考下表但大多数表格型数据的非线性案例都从RBF起步。核函数kernel参数适用场景需要联调的参数线性核linear高维稀疏特征、样本量大C多项式核poly已知特征间有多项式关系degree, coef0, CRBF核rbf非线性、无先验结构C, gammasigmoid核sigmoid类似神经网络的激活行为C, gamma, coef03.2 gamma控制单个样本的影响半径边界形状全靠它RBF核的定义是K(x, x) exp(-gamma * ||x - x||^2)。gamma越大核函数衰减越快每个训练样本只影响离它很近的区域决策边界会变得曲折且剧烈gamma越小影响半径越大边界越平滑小到一定程度就退化成接近线性。换句话说调通SVM案例练习的难点不在C而在同时理解C和gamma的分工。for gamma in [0.1, 1.0, 10.0]: clf SVC(kernelrbf, C1.0, gammagamma) clf.fit(X_train, y_train) # 边界可视化复用2.2节的plot_svm_boundary print(fgamma{gamma:5} test_acc{clf.score(X_test, y_test):.3f} fn_sv{len(clf.support_vectors_)})上面这个小循环会输出三个分数和对应的支持向量数量。你会看到gamma从0.1涨到10时测试准确率先升后降而支持向量数量一路增加。支持向量占比超过训练样本一半时基本可以断定边界被拉得过于曲折。常见的误用是直接信任gammascale默认值即1 / (n_features * X.var())特征方差大时这个值会小到让模型欠拟合。比较稳妥的做法是把手动指定的gamma放进网格搜索不让默认值替你决定。3.3 用GridSearchCV一次完成C与gamma的联调C和gamma是耦合的增大C会放大错分样本的惩罚增大gamma会让边界更复杂两者同时过大过拟合风险翻倍。逐个单独调参很容易停在局部最优。更符合SVM案例练习习惯的做法是把两个参数放进同一张网格用交叉验证统一评估。from sklearn.model_selection import GridSearchCV from sklearn.metrics import f1_score param_grid { C: [0.1, 1, 10, 100], gamma: [0.01, 0.1, 1.0, 10.0] } grid GridSearchCV(SVC(kernelrbf), param_grid, cv5, scoringf1, n_jobs-1) grid.fit(X_train, y_train) print(best params:, grid.best_params_) print(best cv f1:, grid.best_score_) print(test f1:, f1_score(y_test, grid.predict(X_test)))scoringf1在这里比accuracy更合适。SVM案例练习如果正负样本略有不均衡准确率会把少数类上的失败掩盖掉F1能把两类错误同时计入。16组参数、每组5折交叉验证共80次SVM训练对小数据集几秒就跑完。n_jobs-1启用全部CPU核心并行。注意看一个细节如果best_params_恰好落在网格边缘比如C100说明搜索区间没有覆盖到最优值要把网格往边界方向扩展再搜一轮直到最优解落在网格内部。提示GridSearchCV内部会用全部训练数据对最优参数重新拟合之后直接用grid.predict即可不要手动再fit一次否则可能和交叉验证时的数据切分不一致。4. SVM案例练习前的数据准备特征缩放与样本不均衡4.1 特征量纲不一致会让SVM的间隔计算失真SVM优化的目标是几何间隔而间隔计算依赖特征空间里的距离。当特征量纲不一致比如一个特征取值0到1另一个特征取值0到10000后者会直接主导距离计算决策边界被高量纲特征牵制。这是SVM与树模型的本质区别树模型按阈值切分不怕量纲SVM必须做特征缩放否则前面的参数练习全部失真。from sklearn.preprocessing import StandardScaler from sklearn.pipeline import Pipeline pipe Pipeline([ (scaler, StandardScaler()), (svm, SVC(kernelrbf, C1.0, gamma0.5)) ]) pipe.fit(X_train, y_train) print(pipeline test acc:, pipe.score(X_test, y_test))StandardScaler对每个特征减去均值再除以标准差把分布拉到均值0、方差1附近。这里的关键不是缩放本身而是把它放进Pipeline交叉验证时缩放器只在训练折上拟合再用训练折的均值和标准差去变换验证折。如果先对全量数据做StandardScaler.fit(X)再切分验证集的统计信息已经泄露进训练流程测试分数会偏乐观一到线上就露馅。这也是SVM案例练习里最容易被忽视、又最容易犯的流程错误。4.2 样本不均衡时优先用class_weight而不是换核异常检测、流失预测这类真实业务里正负样本比例失调是常态。SVM面对不均衡数据时最大间隔会倾向多数类因为多数类的样本更容易成为支持向量少数类的边界被压缩。此时两个直接手段其一是class_weightbalanced让样本权重与类别频率成反比其二是对少数类单独加大惩罚。前者的好处是不用手工猜权重。from sklearn.utils.class_weight import compute_class_weight # 先看balanced策略实际分配了哪些权重 print(compute_class_weight(balanced, classesnp.unique(y), yy)) # 再把权重策略应用到SVM上 clf SVC(kernelrbf, C1.0, gamma0.5, class_weightbalanced) clf.fit(X_train, y_train) print(balanced f1:, f1_score(y_test, clf.predict(X_test)))compute_class_weight输出的数组里少数类权重明显高于多数类。手动构造权重字典也可以但你得在验证集上反复试错试几轮就相当于在用验证集调参容易过拟合验证集。class_weightbalanced把这件事变成一行配置。如果加上balanced之后少数类分数仍然不行合理的下一步是换用对不均衡更鲁棒的模型或做数据增强而不是继续堆SVM的C和gamma。记住参数调整解决的是边界形状问题不解决样本分布问题。5. SVM案例练习收尾支持向量占比与训练异常的排查5.1 训练分数和验证分数的缺口是过拟合的直接证据SVM案例练习的最后一步是确认模型到底处于欠拟合、正常还是过拟合状态。最简单的办法是固定C扫描gamma同时记录训练集和验证集分数两条曲线的间距就是过拟合的度量。from sklearn.model_selection import validation_curve param_range [0.001, 0.01, 0.1, 1.0, 10.0] train_scores, valid_scores validation_curve( SVC(kernelrbf, C1.0), X, y, param_namegamma, param_rangeparam_range, cv5, scoringaccuracy) for i, g in enumerate(param_range): print(fgamma{g:7.3f} train{train_scores[i].mean():.3f} fvalid{valid_scores[i].mean():.3f})当gamma增大到某个节点训练分数逼近1.0而验证分数开始回落这就是过拟合的拐点。网格搜索选出的最优参数通常位于拐点左侧附近。如果训练和验证分数都很低则属于欠拟合先考虑增大gamma或检查特征缩放是否生效。5.2 四类训练异常的排查方向现象可能原因优先排查动作训练验证分数双低欠拟合gamma过小或特征未缩放增大gamma检查StandardScaler训练近满分、验证明显低过拟合C与gamma同时偏大缩小C或gamma观察支持向量占比支持向量占比超50%噪声过大或数据重叠严重增大C降低惩罚清洗异常样本样本量大、训练极慢SVC复杂度接近样本数的平方换LinearSVC或SGDClassifier支持向量占比是一个常被忽略但非常好用的指标。占比低说明决策边界被少量样本定义模型简洁占比接近全部样本时边界已经被噪声牵制即使验证分数不低泛化也未必可靠。另一个进阶技巧是当业务需要概率输出时给SVC设probabilityTrue会额外做一轮Platt缩放训练时间变长且得到的不一定是严格校准的概率排序用途可以接受绝对值用途要谨慎。每次实验把best_params、支持向量占比、训练验证分数差这三项记成一行实验日志比盲目扫网格更接近一线做SVM案例练习的节奏。本文还有配套的精品资源点击获取
网站建设高端定制企业官网