SVM支持向量机:从线性可分到核函数实战

发布时间:2026/8/4 16:15:17
SVM支持向量机:从线性可分到核函数实战 1. 从“最大间隔”说起SVM的直觉与核心思想如果你在机器学习领域摸爬滚打了一段时间一定会遇到一个名字听起来很“硬核”的算法——支持向量机。我第一次接触它的时候也被那些“超平面”、“核函数”、“对偶问题”搞得一头雾水感觉它像是数学家们的玩具离实际应用很远。但后来当我真正用它解决了一个棘手的二分类问题并且效果出奇地好时我才意识到SVM背后那种追求“最稳妥”分类边界的思想其实非常符合工程上的直觉。今天我们就抛开那些复杂的公式推导从一个从业者的角度聊聊SVM到底是怎么一回事以及我们该如何在“线性可分”和“线性不可分”这两种最典型的场景下把它用起来。简单来说SVM的核心目标就是找一个“最好”的边界把两类数据点分开。什么叫“最好”想象一下你在两张不同颜色的点之间画一条分界线。一条紧贴着某些点的线虽然能把它们分开但稍微有点风吹草动比如数据有点噪声新的点就可能被分错。SVM认为最好的线是离两边最近的数据点都最远的那条线。这个“最远”的距离就是所谓的“间隔”。SVM就是要找到那个能让这个“间隔”最大的分界超平面在二维里就是一条线。那些决定了这个最大间隔的、离分界面最近的数据点就被称为“支持向量”——你看名字就是这么来的它们是支撑起整个分类边界的关键点。这个追求最大间隔的思想赋予了SVM很强的泛化能力也就是对未知数据的分类能力这恰恰是我们工程应用中最看重的。那么这个“最大间隔”具体怎么找这就引出了SVM的数学模型。对于一个线性可分的二分类问题我们假设数据点可以用一个线性方程超平面完美分开。SVM的优化目标数学上就转化为了一个在约束条件下所有样本点都被正确分类最大化“间隔”的问题。有趣的是通过一番巧妙的数学变换主要是拉格朗日乘子法这个原始问题会被转换成一个所谓的“对偶问题”。这个对偶形式非常漂亮它让优化目标只依赖于数据点之间的内积并且自然地引出了“支持向量”的概念——只有那些拉格朗日乘子不为零的样本点才是支持向量。这意味着最终的分类决策函数也仅仅依赖于这些支持向量和它们与待预测点之间的内积。这种特性为后续处理线性不可分问题埋下了至关重要的伏笔。2. 理想情况硬间隔SVM与线性可分问题我们先从最理想、也是最容易理解的情况开始线性可分。这意味着存在至少一个超平面能像一把快刀一样干净利落地把所有正类样本和负类样本分开没有任何一个点被分错。在这种情况下SVM可以采用“硬间隔”的策略。2.1 硬间隔SVM的数学表述与求解假设我们的训练数据集是 { (x_i, y_i) }其中 x_i 是特征向量y_i 是类别标签取值为 1 或 -1。我们要寻找一个超平面w^T * x b 0。对于这个超平面我们希望所有样本都满足 y_i (w^T * x_i b) 1。这个“1”就是硬间隔的体现它要求所有点不仅被正确分类y_i 与 (w^T * x_i b) 同号而且离超平面至少有一个“函数间隔”为1的距离。我们的优化目标是最大化几何间隔这等价于最小化 ||w||^2向量w的模长的平方。于是硬间隔SVM的原始优化问题就写成了 最小化 (1/2) * ||w||^2 约束条件 y_i (w^T * x_i b) 1, 对于所有 i这是一个典型的凸二次规划问题。在实际求解中我们几乎从不直接解这个原始问题而是利用拉格朗日乘子法将其转化为对偶问题。引入拉格朗日乘子 α_i (α_i 0)构造拉格朗日函数 L(w, b, α) (1/2)||w||^2 - Σ α_i [ y_i (w^T * x_i b) - 1 ]。通过对 w 和 b 求偏导并令其为零我们可以得到两个关键关系w Σ α_i y_i x_i 以及 Σ α_i y_i 0。将这两个关系代回拉格朗日函数就消去了 w 和 b得到了只关于 α 的对偶问题最大化 Σ α_i - (1/2) Σ Σ α_i α_j y_i y_j (x_i^T * x_j) 约束条件 Σ α_i y_i 0, 且 α_i 0解这个对偶问题我们得到一组最优的 α*。根据KKT条件对于绝大多数样本α_i* 会等于0只有那些恰好满足 y_i (w^T * x_i b) 1 的样本其 α_i* 才大于0。这些 α_i* 0 的样本就是前面提到的“支持向量”。最终的决策函数用来预测新样本 x为f(x) sign( Σ α_i* y_i (x_i^T * x) b* )。其中 b* 可以通过任意一个支持向量计算得出b* y_j - Σ α_i* y_i (x_i^T * x_j)其中 j 对应任意一个支持向量。注意这里有一个非常重要的实操细节。在求解对偶问题时我们使用了所有样本点两两之间的内积 (x_i^T * x_j)。这个内积计算是后续一切扩展的基石。在代码实现中我们通常会预先计算一个“核矩阵”或“Gram矩阵”其第 i 行第 j 列的元素就是 K_ij x_i^T * x_j以提升计算效率。2.2 线性可分场景的仿真与可视化理论说得再多不如动手画一画看得明白。我们用Python和经典的sklearn库来仿真一个线性可分的例子。我们会在二维平面上生成两类服从不同高斯分布的数据点然后用线性核的SVM去拟合并可视化出决策边界和支持向量。import numpy as np import matplotlib.pyplot as plt from sklearn.svm import SVC from sklearn.datasets import make_blobs # 1. 生成线性可分的仿真数据 X, y make_blobs(n_samples100, centers2, cluster_std1.0, center_box((-5, 5), (-5, 5)), random_state42) # 为了确保是严格的二分类将标签映射为1和-1 y np.where(y0, -1, 1) # 2. 训练硬间隔SVM线性核C参数设为一个很大的值以近似硬间隔 # 注意sklearn中的SVC默认使用软间隔但将C设得极大如1e10可以逼近硬间隔的效果 svm_hard SVC(kernellinear, C1e10) svm_hard.fit(X, y) # 3. 获取模型参数 w svm_hard.coef_[0] # 权重向量w b svm_hard.intercept_[0] # 偏置项b support_vectors svm_hard.support_vectors_ # 支持向量 # 4. 可视化 plt.figure(figsize(10, 8)) # 绘制数据点 plt.scatter(X[y-1, 0], X[y-1, 1], cblue, markero, labelClass -1, edgecolorsk) plt.scatter(X[y1, 0], X[y1, 1], cred, marker^, labelClass 1, edgecolorsk) # 绘制支持向量 plt.scatter(support_vectors[:, 0], support_vectors[:, 1], s150, facecolorsnone, edgecolorsyellow, linewidths2, labelSupport Vectors) # 绘制决策边界w·x b 0 xx np.linspace(X[:, 0].min()-1, X[:, 0].max()1, 30) yy - (w[0] * xx b) / w[1] plt.plot(xx, yy, k-, linewidth2, labelDecision Boundary) # 绘制间隔边界w·x b ±1 yy_upper - (w[0] * xx b - 1) / w[1] yy_lower - (w[0] * xx b 1) / w[1] plt.plot(xx, yy_upper, k--, linewidth1, alpha0.7) plt.plot(xx, yy_lower, k--, linewidth1, alpha0.7) plt.xlabel(Feature 1) plt.ylabel(Feature 2) plt.title(Hard-Margin SVM on Linearly Separable Data) plt.legend() plt.grid(True, alpha0.3) plt.axis(equal) plt.show() # 打印关键信息 print(f权重向量 w: {w}) print(f偏置项 b: {b:.4f}) print(f支持向量数量: {len(support_vectors)}) print(f支持向量的索引在原始数据中: {svm_hard.support_})运行这段代码你会看到一张清晰的图两类颜色不同的点被一条实线决策边界分开两条虚线分别穿过离决策边界最近的正类和负类样本点这些点就是支持向量它们被高亮显示。你会发现决策边界的位置完全由这些少量的支持向量决定其他远离边界的点无论怎么移动只要不跨过虚线都不会影响最终的边界。这就是SVM的“稀疏性”也是其计算和存储效率的一个优势。实操心得在sklearn的SVC中即使我们设置kernellinear它内部也是通过解决对偶问题来求解的。参数C在这里被设置为一个极大的值1e10这相当于告诉模型“我几乎不允许分类错误”从而逼近硬间隔SVM。在实际的线性可分数据上只要数据真的是完全可分的这样设置通常能得到理想结果。但务必注意如果数据中存在哪怕一个噪声点导致严格不可分这个设置就会导致优化问题无解模型会无法收敛或产生极端结果。3. 现实妥协软间隔SVM与线性不可分问题现实世界的数据往往是“脏”的存在噪声、异常值或者两类数据本身就是你中有我、我中有你无法用一条直线超平面完美分开。这就是“线性不可分”问题。如果此时还坚持使用硬间隔SVM优化问题将变得无解。为此Vapnik等人引入了“软间隔”的概念这是SVM实用化道路上最关键的一步。3.1 引入松弛变量与惩罚因子C软间隔的核心思想是允许一些样本点“犯错”即不满足 y_i (w^T * x_i b) 1 的约束。为了度量这种“错误”的程度我们为每个样本 i 引入一个“松弛变量” ξ_i (ξ_i 0)。约束条件就放松为y_i (w^T * x_i b) 1 - ξ_i。显然如果 ξ_i 0说明该点被完美分类且位于间隔之外或边界上如果 0 ξ_i 1说明该点被正确分类但进入了间隔内部如果 ξ_i 1则说明该点被错误分类了。允许犯错不是无代价的。我们需要在目标函数中对这些松弛变量进行惩罚。于是新的优化目标变成了 最小化 (1/2) * ||w||^2 C * Σ ξ_i 约束条件 y_i (w^T * x_i b) 1 - ξ_i, 且 ξ_i 0, 对于所有 i这里的 C 0 是一个超参数称为“惩罚因子”或“正则化参数”。它控制着我们对分类错误的容忍程度C值很大意味着对误分类的惩罚很重模型会倾向于选择更小的间隔甚至逼近硬间隔以减少误分类点但可能导致模型过拟合对噪声敏感。C值很小意味着对误分类的惩罚很轻模型会倾向于选择更大的间隔容忍更多的样本点进入间隔内部或被误分类这提高了模型的泛化能力但可能欠拟合。因此参数C的调优是使用软间隔SVM时最重要的环节之一它直接体现了“最大化间隔”和“最小化分类错误”之间的权衡。3.2 软间隔SVM的对偶问题与支持向量同样地我们可以推导软间隔SVM的对偶问题。过程与硬间隔类似但引入松弛变量后拉格朗日乘子α_i的约束条件发生了变化。最终的对偶问题形式与硬间隔惊人地相似最大化 Σ α_i - (1/2) Σ Σ α_i α_j y_i y_j (x_i^T * x_j) 约束条件 Σ α_i y_i 0, 且 0 α_i C唯一的区别就是 α_i 多了一个上界 C。这个上界限制非常直观它意味着任何一个样本点对最终决策边界的影响力是有限的最大不超过C。这防止了某些异常点噪声拥有过大的权重而过度扭曲决策边界。解出对偶问题的 α* 后支持向量的定义也变得更加丰富边界支持向量对应 0 α_i C 的样本。这些点恰好落在间隔边界上即 ξ_i 0满足 y_i (w^T * x_i b) 1。非边界支持向量对应 α_i C 的样本。这些点位于间隔内部0 ξ_i 1或被误分类ξ_i 1。它们因为违反了硬间隔约束而受到了最大惩罚C。所有 α_i 0 的样本都是支持向量它们共同决定了决策边界。决策函数的形式与硬间隔完全相同f(x) sign( Σ α_i* y_i (x_i^T * x) b* )。计算 b* 时通常使用所有边界支持向量0 α_i C计算后取平均以获得更稳定的数值结果。3.3 线性不可分场景的仿真与C参数的影响我们通过一个更复杂的、线性不可分的数据集来演示软间隔SVM并观察不同C值的影响。这里我们使用make_moons数据集它生成两个交错在一起的半月形数据是典型的线性不可分案例。from sklearn.datasets import make_moons from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score # 1. 生成线性不可分的仿真数据半月形 X, y make_moons(n_samples200, noise0.15, random_state42) y np.where(y0, -1, 1) # 映射标签为1/-1 X_train, X_test, y_train, y_test train_test_split(X, y, test_size0.3, random_state42) # 2. 测试不同的C值 C_values [0.01, 0.1, 1, 10, 100, 1000] models {} train_accs [] test_accs [] plt.figure(figsize(15, 10)) for idx, C in enumerate(C_values): # 训练软间隔SVM svm_soft SVC(kernellinear, CC) svm_soft.fit(X_train, y_train) models[C] svm_soft # 计算准确率 y_train_pred svm_soft.predict(X_train) y_test_pred svm_soft.predict(X_test) train_acc accuracy_score(y_train, y_train_pred) test_acc accuracy_score(y_test, y_test_pred) train_accs.append(train_acc) test_accs.append(test_acc) # 绘制决策边界 plt.subplot(2, 3, idx1) # 创建网格以绘制决策区域 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 svm_soft.predict(np.c_[xx.ravel(), yy.ravel()]) Z Z.reshape(xx.shape) # 绘制决策区域和边界 plt.contourf(xx, yy, Z, alpha0.3, cmapplt.cm.coolwarm) plt.scatter(X_train[y_train-1, 0], X_train[y_train-1, 1], cblue, markero, edgecolorsk, alpha0.7, labelClass -1 (Train)) plt.scatter(X_train[y_train1, 0], X_train[y_train1, 1], cred, marker^, edgecolorsk, alpha0.7, labelClass 1 (Train)) # 高亮支持向量 plt.scatter(svm_soft.support_vectors_[:, 0], svm_soft.support_vectors_[:, 1], s80, facecolorsnone, edgecolorsyellow, linewidths2, labelSupport Vectors) plt.xlim(xx.min(), xx.max()) plt.ylim(yy.min(), yy.max()) plt.title(fLinear SVM (C{C})\nTrain Acc: {train_acc:.3f}, Test Acc: {test_acc:.3f}) plt.xlabel(Feature 1) plt.ylabel(Feature 2) if idx 0: plt.legend(locupper right, fontsizesmall) plt.tight_layout() plt.show() # 3. 绘制准确率随C值变化的曲线 plt.figure(figsize(10, 6)) plt.plot(C_values, train_accs, bo-, linewidth2, markersize8, labelTraining Accuracy) plt.plot(C_values, test_accs, rs-, linewidth2, markersize8, labelTest Accuracy) plt.xscale(log) # C值范围大使用对数坐标 plt.xlabel(Regularization Parameter C (log scale)) plt.ylabel(Accuracy) plt.title(Effect of C on Linear SVM Performance (Linearly Inseparable Data)) plt.grid(True, whichboth, linestyle--, alpha0.5) plt.legend() plt.show()运行这段代码你会看到六张子图展示了C值从很小0.01到很大1000时线性SVM在半月形数据上的决策边界变化。同时还有一张准确率随C值变化的曲线图。观察与解读C很小如0.01模型对误分类惩罚很轻决策边界非常“简单”几乎是一条直线间隔很大。它容忍了很多样本进入间隔内部甚至被误分类导致训练集和测试集准确率都不高欠拟合。支持向量数量可能很多因为很多点都成了“非边界支持向量”α_i C。C适中如1, 10模型在“间隔最大化”和“错误最小化”之间取得了较好的平衡。决策边界开始尝试弯曲以适应数据的分布趋势训练和测试准确率都达到较高水平。支持向量数量适中。C很大如1000模型极力避免任何错误决策边界变得非常复杂试图穿过所有可能的缝隙去完美分开训练数据间隔被压缩得很小。这导致训练准确率可能接近100%但测试准确率反而下降因为模型学习到了数据中的噪声过拟合。支持向量数量可能减少但每个支持向量的权重α_i可能很大。踩坑实录在实际项目中线性不可分是常态。直接使用线性核SVM并盲目调大C值是新手常犯的错误。他们看到训练准确率上去了就很开心殊不知模型已经过拟合。正确的做法是始终在验证集或通过交叉验证来评估不同C值下的模型性能选择在验证集上表现最好的C。对于明显线性不可分的数据如上面的半月形线性SVM的准确率存在天花板此时我们应该考虑更强大的武器——核方法。4. 升维打击核函数与非线性SVM当数据在原始特征空间里线性不可分时一个天才的想法是将数据映射到一个更高维甚至是无限维的特征空间在这个新空间里数据也许就变得线性可分了。SVM的精妙之处在于它不需要我们显式地进行这个复杂的映射只需要计算原始空间中数据点映射后的内积即可而这个内积计算可以通过一个“核函数”来高效完成。4.1 核技巧隐式高维映射的魔法回顾一下线性SVM的对偶问题和决策函数对偶问题目标函数 Σ α_i - (1/2) Σ Σ α_i α_j y_i y_jx_i, x_j决策函数 f(x) sign( Σ α_i* y_ix_i, x b* )它们都只依赖于数据点之间的内积x_i, x_j。假设我们有一个映射函数 φ: R^n - R^m (m n 甚至 m - ∞)将原始特征 x 映射到高维特征 φ(x)。那么在高维空间中的SVM其内积就变成了φ(x_i), φ(x_j)。核函数 K(x_i, x_j) 就是一个函数它直接计算这个高维空间的内积而无需知道映射φ的具体形式K(x_i, x_j) φ(x_i), φ(x_j)。这样我们只需要将原来所有内积x_i, x_j替换为核函数值 K(x_i, x_j)就可以在高维特征空间中隐式地运行SVM。这就是著名的“核技巧”。4.2 常用核函数及其选择常用的核函数有以下几种选择合适的核函数是应用非线性SVM成功的关键。线性核Linear Kernel K(x_i, x_j) x_i^T * x_j。这就是我们前面讨论的情况没有进行非线性映射。适用于特征数量多、样本数量相对少或者问题本身近似线性的情况。它的优点是速度快可解释性强可以分析权重向量w。多项式核Polynomial Kernel K(x_i, x_j) (γ * x_i^T * x_j r)^d。其中d是多项式的次数γ、r是参数。它能捕捉特征间d阶的交叉组合信息。当d1且r0时退化为线性核。多项式核的缺点是当d较大时计算可能不稳定且需要调优的参数较多d, γ, r。径向基函数核/高斯核RBF Kernel / Gaussian Kernel K(x_i, x_j) exp(-γ * ||x_i - x_j||^2)。这是最常用、最强大的核函数之一。它对应于将数据映射到无限维的特征空间。参数γgamma控制了单个样本的影响范围γ越大高斯分布越“瘦高”模型越复杂容易过拟合γ越小分布越“扁平”模型越平滑容易欠拟合。RBF核通常是非线性问题的首选。Sigmoid核 K(x_i, x_j) tanh(γ * x_i^T * x_j r)。形式上类似于神经网络中的激活函数。但在实际应用中它并不总是满足Mercer定理即保证对应的核矩阵是半正定的因此可能在某些优化问题上遇到困难现在用得相对较少。核函数选择经验谈没有先验知识时默认从RBF核开始尝试。它在大多数情况下都能取得不错的效果。如果特征维度非常高比如文本分类中的词袋模型线性核往往就足够了而且训练速度远快于RBF核。可以先试试线性核如果效果不佳再换RBF。多项式核在某些特定领域如图像处理可能有其优势但调参更复杂不如RBF核通用。选择核函数后关键的超参数就变成了C惩罚因子和核函数自身的参数如RBF的γ。这两个参数需要联合调优。4.3 非线性SVM仿真RBF核的威力让我们回到那个线性不可分的半月形数据集这次我们祭出RBF核SVM看看它如何通过非线性映射“掰弯”决策边界完美解决这个问题。from sklearn.svm import SVC from sklearn.model_selection import GridSearchCV # 继续使用之前的半月形数据 X, y (训练集X_train, y_train测试集X_test, y_test) # 1. 定义参数网格进行网格搜索寻找最优的C和gamma param_grid { C: [0.1, 1, 10, 100], gamma: [0.01, 0.1, 1, 10, scale, auto] # scale和auto是sklearn的默认策略 } # 使用RBF核的SVM svm_rbf SVC(kernelrbf, random_state42) # 使用5折交叉验证进行网格搜索 grid_search GridSearchCV(svm_rbf, param_grid, cv5, scoringaccuracy, n_jobs-1, verbose1) grid_search.fit(X_train, y_train) # 输出最佳参数和最佳得分 print(fBest parameters found: {grid_search.best_params_}) print(fBest cross-validation accuracy: {grid_search.best_score_:.4f}) # 用最佳模型在测试集上评估 best_svm grid_search.best_estimator_ y_test_pred best_svm.predict(X_test) test_accuracy accuracy_score(y_test, y_test_pred) print(fTest set accuracy with best model: {test_accuracy:.4f}) # 2. 可视化最佳RBF SVM的决策边界 plt.figure(figsize(12, 5)) # 子图1决策区域与支持向量 plt.subplot(1, 2, 1) 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 best_svm.predict(np.c_[xx.ravel(), yy.ravel()]) Z Z.reshape(xx.shape) plt.contourf(xx, yy, Z, alpha0.3, cmapplt.cm.coolwarm) plt.scatter(X_train[y_train-1, 0], X_train[y_train-1, 1], cblue, markero, edgecolorsk, alpha0.7, labelClass -1 (Train)) plt.scatter(X_train[y_train1, 0], X_train[y_train1, 1], cred, marker^, edgecolorsk, alpha0.7, labelClass 1 (Train)) plt.scatter(best_svm.support_vectors_[:, 0], best_svm.support_vectors_[:, 1], s100, facecolorsnone, edgecolorsyellow, linewidths2, labelSupport Vectors) plt.xlim(xx.min(), xx.max()) plt.ylim(yy.min(), yy.max()) plt.title(fRBF SVM Decision Boundary\nBest Params: C{grid_search.best_params_[\C\]}, gamma{grid_search.best_params_[\gamma\]}\nTest Acc: {test_accuracy:.3f}) plt.xlabel(Feature 1) plt.ylabel(Feature 2) plt.legend(locupper right) # 子图2不同C和gamma组合的热力图交叉验证平均分 plt.subplot(1, 2, 2) # 提取网格搜索结果 results grid_search.cv_results_ C_values param_grid[C] gamma_values param_grid[gamma] scores_mean results[mean_test_score].reshape(len(C_values), len(gamma_values)) # 绘制热力图 im plt.imshow(scores_mean, interpolationnearest, cmapplt.cm.viridis) plt.colorbar(im, labelCV Accuracy) plt.xticks(np.arange(len(gamma_values)), labelsgamma_values) plt.yticks(np.arange(len(C_values)), labelsC_values) plt.xlabel(gamma) plt.ylabel(C) plt.title(Grid Search CV Accuracy Heatmap) # 在热力图上标注分数 for i in range(len(C_values)): for j in range(len(gamma_values)): text plt.text(j, i, f{scores_mean[i, j]:.3f}, hacenter, vacenter, colorw if scores_mean[i, j] 0.7 else k, fontsize9) plt.tight_layout() plt.show() # 3. 对比线性核与RBF核在测试集上的表现 svm_linear_best SVC(kernellinear, C1).fit(X_train, y_train) # 简单取C1的线性SVM linear_test_acc accuracy_score(y_test, svm_linear_best.predict(X_test)) print(f\nComparison on Moons dataset:) print(f - Linear SVM (C1) Test Accuracy: {linear_test_acc:.4f}) print(f - RBF SVM (Tuned) Test Accuracy: {test_accuracy:.4f})这段代码做了几件关键事情自动调参使用GridSearchCV对RBF核SVM的超参数C和gamma进行网格搜索通过5折交叉验证找到最优组合。这是实际项目中必不可少的步骤。可视化决策边界展示了最优RBF SVM如何画出一条复杂的、非线性的边界完美地将两个半月形分开。支持向量通常位于两类数据的“交界”地带。参数热力图直观展示了不同C和gamma组合下的交叉验证平均准确率帮助你理解这两个参数如何共同影响模型性能。通常热力图中会有一个性能较好的区域。对比实验最后对比了调优后的RBF SVM和线性SVM在测试集上的表现。在半月形数据上RBF核的性能优势是压倒性的。核心技巧RBF核有两个关键参数C和gamma。它们之间存在交互作用需要联合调优。一个实用的调参策略是使用粗粒度网格搜索如C和gamma都取对数间隔的值[0.001, 0.01, 0.1, 1, 10, 100]先锁定性能较好的区域然后在细粒度网格如该区域附近更密集的值上进行精细搜索。sklearn的GridSearchCV或RandomizedSearchCV可以自动化这个过程。记住gamma定义了单个样本的影响半径gamma太大模型会过拟合每个样本点都是一个“小山丘”gamma太小模型会欠拟合所有样本的影响范围都很大决策边界趋于平滑甚至线性。