news 2026/10/29 11:16:47

SVM最大间隔、核技巧与SMO:Python实现与调参排错指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
SVM最大间隔、核技巧与SMO:Python实现与调参排错指南

简介:一份面向机器学习初学者与课程实验场景的支持向量机 Python 实现素材,聚焦用 Python 落地 SVM 的分类思想,帮助读者理解从间隔最大化、核函数选择到模型训练与测试的基本流程。压缩包共 6 个文件,以 3 个 Python 脚本、1 个 pyc 缓存、1 个 Markdown 说明和 1 个 txt 数据文本为主,整体约 9KB,体量轻便,适合直接阅读源码并开展小规模实验。已有 1944 人学习或下载,具备一定的参考与交流基础。内容围绕核心算法、测试入口、说明文档与示例数据组织,代码结构相对紧凑,可据此梳理 SVM 的训练逻辑、分类决策与验证方式,并通过运行测试观察模型表现。对需要完成课程作业、复现经典算法或准备机器学习入门实践的人而言,这份素材提供了可运行的代码骨架、基础数据与调试起点。

1. 训练完的支持向量机里,大部分样本其实不参与决策

支持向量机给人的第一印象是“又一个分类算法”,但真正让它在 Python 实现里值得逐行读源码的,是一个反直觉的事实:训练完成之后,绝大多数训练样本对决策边界毫无影响。你把那些 α=0 的样本全部删掉再重新预测,输出一模一样。边界只由少数几个恰好压在间隔边界上、或者已经越界的点决定,这些点被称为支持向量。

这意味着支持向量机的解是稀疏的、唯一的、可复现的:同一份数据、同一组超参数,训练两次得到的 w 与 b 完全一致,不会因为权重初始化不同而给出两个都“对”但形状不同的边界。这里的稳定性来自“最大化间隔”这个目标逼出来的数学结构,不是运气。沿着这条线索往下,才能看懂对偶问题、KKT 条件和核技巧为什么长成那个样子。

2. 最大间隔:从几何直觉到凸二次规划

2.1 函数间隔的尺度陷阱:w 和 b 同乘一个数,分类结果不变

线性分类器用 f(x) = wᵀx + b 的符号判类别,标签取 +1 与 -1。自然想到的“置信度”是 y_i(wᵀx_i + b),正得越多说明分得越开,这个量叫函数间隔。问题在于它没有尺度:把 w 和 b 同时乘以 3.7,所有点的符号不变,分类结果一个字都不改,但函数间隔整体放大 3.7 倍。于是“最小函数间隔等于 0.5”和“最小函数间隔等于 1.85”描述的是同一个分类器,比较大小毫无意义。

真正有几何含义的是几何间隔:把函数间隔除以 ||w||,得到样本到超平面的欧氏距离。它才是“间隔有多宽”的度量,而且对 w、b 的等比例缩放免疫。这一步看着只是补了个分母,实际上把问题从“带尺度自由度”变成了“尺度无关”,后面的所有推导都建立在它上面。

用几行代码可以把这个事实钉死:两个只差缩放系数的分类器,函数间隔差了三倍多,几何间隔分毫不差。

import numpy as np # 一组线性可分的二维点,标签取 +1 / -1 X = np.array([[2.0, 1.0], [2.5, 2.0], [1.0, 3.0], [-1.0, -2.0], [-2.0, -1.5], [-1.5, -2.5]]) y = np.array([1, 1, 1, -1, -1, -1]) w = np.array([1.0, -1.0]) b = -0.5 def func_margin(w, b): # 函数间隔:带符号,随 w、b 等比缩放而改变 return y * (X @ w + b) m1 = func_margin(w, b) m2 = func_margin(3.7 * w, 3.7 * b) # 同方向、放大 3.7 倍 # 几何间隔:除以 ||w||,缩放被抵消 g1 = m1 / np.linalg.norm(w) g2 = m2 / np.linalg.norm(3.7 * w) print(m1.min(), m2.min()) # 0.5 与 1.85 print(g1.min(), g2.min()) # 0.354 与 0.354

输出的两组数字直接说明了问题:函数间隔的最小值从 0.5 变到 1.85,而几何间隔始终是 0.354。代码里的X @ w + b是线性打分,y * (...)补上符号信息,np.linalg.norm(w)是超平面法向量的长度。只要承认几何间隔才是目标,就必须处理掉 ||w|| 这个分母,而它恰恰是后面优化问题的核心。

2.2 为什么可以直接规定 min y_i(wᵀx_i + b) = 1

既然尺度是自由的,就可以主动用掉这个自由度为问题定标:把 w、b 整体缩放,使离超平面最近的那些样本的几何间隔恰好等于 1/||w||,也就是让最小的函数间隔等于 1。这来自可利用的自由度:通过缩放参数,总能得到这样的结果。此时所有样本都满足 y_i(wᵀx_i + b) ≥ 1,等号在最近的样本上取到。

于是“最大化几何间隔”变成了“最小化 ||w||”,因为最近点距离是 1/||w||。为了求导方便,通常写成最小化 ½||w||²,平方不改变最优解的位置,½ 只是让导数少一个常数因子。

这一步容易翻车的地方在于前提:能归一化到最小函数间隔为 1,前提是存在一个超平面把两类完全分开、且没有点落在间隔带内。如果数据有重叠,无论怎么缩放,总有点的函数间隔小于 1,硬性规定“最小值等于 1”就和“所有点 ≥ 1”矛盾,可行域直接空了。软间隔的松弛变量就是为了修补这个前提,后面会讲到。

最终得到的标准形式是一个带线性约束的二次规划:

min ½ ||w||² s.t. y_i (wᵀ x_i + b) ≥ 1, i = 1..n

变量只有 w 和 b,约束是 n 条线性不等式,目标关于 w 是严格凸的二次函数。这个形式干净得不像机器学习问题,但它恰恰是支持向量机全部性质的源头。

2.3 凸二次规划:为什么支持向量机的解不像神经网络那样看运气

对比一下感知机:感知机只要求把训练集分对,满足条件的超平面有无穷多个,最后落在哪一个完全取决于样本遍历顺序和初始值。这不是实现细节,而是问题本身没有唯一解。支持向量机在“分对”之外加了一条“间隔最大”,把无穷多个可行解压成了唯一一个。

唯一的来源是凸性。目标函数 ½||w||² 是严格凸的,约束是线性的,所以可行域是凸集,整个问题是凸二次规划:任何局部最优都是全局最优,最优解唯一(w 唯一,b 在支持向量不唯一时可能有一个范围,但决策函数不变)。这条性质带来两个工程上的好处:一是没有“随机种子玄学”,调参时结果可复现;二是 KKT 条件从“必要条件”升级为“充要条件”,只要找到满足 KKT 的点,就一定是全局最优,这给 SMO 这类迭代算法提供了停机判据。

严格凸还解释了一个细节:w 可以写成支持向量的线性组合,且这个表示是唯一的。而 b 不唯一的情况出现在多个支持向量同时决定它的时候,实践中通常对所有自由支持向量求 b 再取平均,比随便挑一个更稳。

3. 拉格朗日对偶与 KKT:非零 α 为什么只落在少数样本上

3.1 拉格朗日函数:把 n 条约束塞进一个目标里

直接解带不等式的二次规划不是不行,通用 QP 求解器就能做,但对支持向量机来说有更好的路。给每条约束配一个乘子 α_i ≥ 0,写出拉格朗日函数:

L(w, b, α) = ½||w||² - Σ α_i [ y_i (wᵀx_i + b) - 1 ]

对 w 和 b 求偏导并令其为零,得到两个关键关系:

w = Σ α_i y_i x_i Σ α_i y_i = 0

第一个式子说明 w 完全由训练样本的加权和构成,权重就是 α。代回 L 消掉 w 和 b,得到对偶问题:

max Σ α_i - ½ ΣΣ α_i α_j y_i y_j (x_iᵀ x_j) s.t. α_i ≥ 0, Σ α_i y_i = 0

这个变换绝不是形式游戏。原始问题有 d 个变量(d 是特征维度),对偶问题有 n 个变量(n 是样本数),而且目标里只剩下样本之间的内积 x_iᵀx_j。高维特征下原始问题变量爆炸,对偶问题规模只和样本数有关;更重要的是,内积这个结构直接为核技巧留了接口。

代价同样明显:对偶问题的规模随样本数平方增长,这是支持向量机在大数据上吃力的根本原因,不是实现写得烂。

3.2 KKT 互补松弛:α 稀疏性的真正来源

对偶问题解出来之后,α 的分布极不均匀:绝大多数 α_i 恰好等于 0,只有少数为正。这个稀疏性来自 KKT 条件里的互补松弛:

α_i [ y_i (wᵀx_i + b) - 1 ] = 0

它要求每个样本的两个因子至少有一个为零。如果某个样本没被压在间隔边界上,也就是 y_i(wᵀx_i + b) > 1,括号里不为零,那么 α_i 必须为零。反过来,α_i > 0 的样本一定满足 y_i(wᵀx_i + b) = 1,正好躺在间隔边界上。还有一类点因为违反约束太严重、被软间隔“放弃”,它们的 α 会顶到上界 C。

把 α 分成三类看,整个模型的行为就清楚了:

α 取值样本位置对 w 的贡献对 b 的作用
α = 0间隔带外,分类正确无无
0 < α < C恰好在间隔边界上有决定 b
α = C间隔带内或分错有决定 b,但受上界约束

所以“支持向量”这个名称很实在:真正支撑起决策边界的,就是 α 非零的那几个点。删掉 α=0 的样本,w = Σα_i y_i x_i 求和结果一个字不变。这也是为什么支持向量机对异常点相对不敏感,一个远离边界的离群点几乎不可能拿到非零的 α,因为它对间隔没有约束力。

3.3 对偶形式与软间隔:C 这个参数是从哪冒出来的

把 w 的表达式代回决策函数,得到支持向量机的预测形式:

f(x) = Σ α_i y_i (x_iᵀ x) + b

预测时只需要和支持向量做内积,其余样本完全不参与计算。这个形式还有个副产品:b 不必单独优化,取任意一个满足 0 < α_i < C 的支持向量,用 b = y_i - Σ α_j y_j (x_jᵀ x_i) 就能反解出来。工程实现里为了保证数值稳定,通常对所有自由支持向量求出的 b 取平均。

硬间隔要求所有点都分对且落在间隔外,现实数据很少这么配合。引入松弛变量 ξ_i ≥ 0,把约束放宽成 y_i(wᵀx_i + b) ≥ 1 - ξ_i,目标同时惩罚松弛量:

min ½||w||² + C Σ ξ_i

C 是唯一的超参数,含义很直白:它衡量“间隔宽”和“训练错误少”之间的兑换率。C 越大,越不容忍违反间隔,间隔被压窄,边界贴着数据走,容易过拟合;C 越小,越愿意放掉一些点换取宽间隔,偏差上升方差下降。

重新走一遍拉格朗日推导,会发现软间隔的对偶问题和硬间隔几乎一模一样,唯一的差别是 α 多了一个上界:

max Σ α_i - ½ ΣΣ α_i α_j y_i y_j (x_iᵀ x_j) s.t. 0 ≤ α_i ≤ C, Σ α_i y_i = 0

C 直接从约束里长出来,不是额外拍脑袋加的正则项。还有一条等价的看法:软间隔支持向量机的最优解,与最小化合页损失加 L2 正则的问题是同一个解,形式是 min ½||w||² + C Σ max(0, 1 - y_i f(x_i))。合页损失在 y_i f(x_i) = 1 处有个折角,这个折角对应“间隔边界”,也是 α 只能取到 C 这个上界的几何原因。理解这一层,调 C 的时候就不是盲试了。

4. 核技巧:不显式映射也能算高维内积

4.1 对偶问题只依赖内积,这就是可乘之机

回头看对偶目标:Σ α_i - ½ ΣΣ α_i α_j y_i y_j (x_iᵀ x_j)。样本坐标只以两两内积的形式出现,决策函数 f(x) = Σ α_i y_i (x_iᵀ x) + b 也一样。也就是说,算法从头到尾只关心“任意两个样本有多像”,从来不单独使用某个样本的坐标。

既然这样,就可以把内积换成一个函数 K(x, z)。如果这个 K 恰好等于某个映射 φ 之后的内积,即 K(x, z) = φ(x)ᵀφ(z),那么用 K 训练出来的模型,等价于先把数据映射到高维空间、再在那个空间里做线性支持向量机。区别在于 φ 从头到尾没被算出来过。

多项式核是个能手工验证的例子。取 K(x, z) = (xᵀz + 1)²,二维情况下展开:

(xᵀz + 1)² = x₁²z₁² + x₂²z₂² + 2x₁x₂z₁z₂ + 2x₁z₁ + 2x₂z₂ + 1 = φ(x)ᵀ φ(z)

对应的 φ(x) = [x₁², x₂², √2 x₁x₂, √2 x₁, √2 x₂, 1],六维。原始二维空间里算一次内积再加一平方,等价于在六维空间里算一次内积,中间那六个坐标一次都不用显式构造。维度越高差距越夸张,RBF 核对应的甚至是无限维空间,但计算量始终是 O(d)。

4.2 常用核函数与 Mercer 条件:什么样的 K 才合法

不是随便写个相似度函数就能当核用。合法性的判据是 Mercer 条件:对任意有限样本集,核矩阵 K_ij = K(x_i, x_j) 必须对称半正定。满足这一条,才能保证存在某个 φ 使得 K(x, z) = φ(x)ᵀφ(z),对偶问题也才是凸的、有唯一解。忽略这个条件直接造核,得到的对偶问题可能是非凸的,SMO 迭代着就发散了,这就是一个典型的黑匣子故障。

实践中常用的几个核:

核函数表达式关键参数适用场景
线性核xᵀz无特征维度高、样本量大、近似线性可分
多项式核(γ xᵀz + r)^dγ, r, d特征间存在明确的交互项
RBF 核exp(-γ‖x - z‖²)γ通用默认选择,边界光滑
Sigmoid 核tanh(γ xᵀz + r)γ, r并非总是半正定,慎用

RBF 核的 γ 值得单独说:它控制单个样本的影响半径。γ 大,样本影响范围小,边界贴着每个点绕,训练集能到 100% 但测试集可能崩;γ 小,影响范围大,边界接近超平面,容易欠拟合。γ 和 C 通常要一起调,一个管边界的弯曲程度,一个管对错误的容忍度,两个都放大就双重过拟合。

4.3 SMO:把 n 个变量拆成两两求解

有了对偶形式和核函数,剩下的问题是怎么解那个带等式约束和盒约束的二次规划。α 有 n 个,直接上通用求解器要 O(n³),还得存 n×n 的核矩阵。

序列最小最优化(SMO)的思路是坐标下降:每次只动两个 α,其余固定。为什么是两个而不是一个?因为等式约束 Σ α_i y_i = 0 必须始终满足,单独改一个 α 立刻破坏约束,最少得同时改两个来互相抵消。

固定其余变量后,两个乘子的子问题有解析解,不需要迭代。设选中的是 α₁ 和 α₂,先算误差 E_i = f(x_i) - y_i,再算二阶导:

η = K₁₁ + K₂₂ - 2K₁₂

η 是两个样本在核空间里的“距离平方”,只要它大于零,子问题就是严格凸的,可以直接写出更新量:

α₂_new = α₂ + y₂ (E₁ - E₂) / η

然后按 y₁ 与 y₂ 是否同号,把 α₂_new 剪辑到不同的区间 [L, H]:同号时 L = max(0, α₁+α₂-C),H = min(C, α₁+α₂);异号时 L = max(0, α₂-α₁),H = min(C, C+α₂-α₁)。α₁ 由等式约束反推。这个剪辑不是可选项,跳过它约束就破了,训练出来的模型预测全是同一类。

4.4 一份能跑的 numpy 实现与验收标准

把上面的推导落成代码,核心不到一百行。核矩阵先算一次缓存起来,内层循环只做索引和标量运算。

import numpy as np class SimpleSVM: def __init__(self, C=1.0, tol=1e-3, max_passes=5, kernel="linear", gamma=0.5): self.C = C # 盒约束上界,控制间隔宽度与容错的兑换率 self.tol = tol # KKT 违反量的容忍阈值,越小越严格也越慢 self.max_passes = max_passes # 连续多少轮没有 α 变化就停 self.kernel = kernel self.gamma = gamma # RBF 核的影响半径参数 def _K(self, A, B): if self.kernel == "linear": return A @ B.T if self.kernel == "rbf": d = (A[:, None, :] - B[None, :, :]) ** 2 return np.exp(-self.gamma * d.sum(axis=2)) raise ValueError("unsupported kernel") def fit(self, X, y): n = len(y) K = self._K(X, X) alpha, b = np.zeros(n), 0.0 passes = 0 while passes < self.max_passes: changed = 0 for i in range(n): E_i = (alpha * y) @ K[:, i] + b - y[i] # 只在违反 KKT 的样本上才尝试更新 if not ((y[i] * E_i < -self.tol and alpha[i] < self.C) or (y[i] * E_i > self.tol and alpha[i] > 0)): continue j = (i + 1 + np.random.randint(n - 1)) % n # 保证 j != i E_j = (alpha * y) @ K[:, j] + b - y[j] ai_old, aj_old = alpha[i], alpha[j] # 盒约束 + 等式约束决定的可行区间 if y[i] != y[j]: L, H = max(0, aj_old - ai_old), min(self.C, self.C + aj_old - ai_old) else: L, H = max(0, ai_old + aj_old - self.C), min(self.C, ai_old + aj_old) if L >= H: continue eta = K[i, i] + K[j, j] - 2 * K[i, j] if eta <= 0: continue # 退化情形直接跳过 aj = min(H, max(L, aj_old + y[j] * (E_i - E_j) / eta)) if abs(aj - aj_old) < 1e-5: continue ai = ai_old + y[i] * y[j] * (aj_old - aj) # b 的两个候选值,优先取落在 (0, C) 区间的那个 b1 = b - E_i - y[i] * (ai - ai_old) * K[i, i] - y[j] * (aj - aj_old) * K[i, j] b2 = b - E_j - y[i] * (ai - ai_old) * K[i, j] - y[j] * (aj - aj_old) * K[j, j] if 0 < ai < self.C: b = b1 elif 0 < aj < self.C: b = b2 else: b = (b1 + b2) / 2 alpha[i], alpha[j] = ai, aj changed += 1 passes = passes + 1 if changed == 0 else 0 self.alpha, self.b, self.X, self.y = alpha, b, X, y self.sv = np.where(alpha > 1e-8)[0] # 只保留支持向量用于预测 return self def decision_function(self, X): K = self._K(X, self.X[self.sv]) return K @ (self.alpha[self.sv] * self.y[self.sv]) + self.b

几个参数和实现细节值得单独交代。max_passes是停机条件,Platt 原始论文的写法是“连续若干轮没有任何 α 被更新”,工程上这个值给 5 到 10 足够,太小会在还没收敛时就退出,表现出对偶目标一直降不下去。eta用 K[i,i] + K[j,j] - 2K[i,j] 而不是直接对核函数求导,等于把核空间的距离平方算出来,只要它不是非正数,子问题就是凸的,更新量有解析解。sv过滤掉 α 接近零的样本,预测时只和支持向量做内积,这是稀疏性带来的实际加速,不是装饰。

5. 常见问题排查:支持向量机训练不收敛、准确率像掷硬币

5.1 现象:训练集准确率接近 100%,测试集却接近随机

现象:换一批数据跑,训练集上完美分开,测试集准确率在 50% 附近波动,多次重跑差异很大。

原因:C 或 RBF 核的 γ 给得太大,模型把每个训练点都当成必须绕开的障碍,边界画得极其曲折。核矩阵在这种参数下条件数很差,SMO 的更新量被噪声主导,结果对随机选择的乘子对非常敏感。

解决:先把 C 和 γ 放到对数网格上做交叉验证,从 C ∈ {0.1, 1, 10, 100}、γ ∈ {0.001, 0.01, 0.1, 1} 开始,别用默认值。同时确认训练前做了标准化:RBF 核算的是欧氏距离,某个特征量纲是千级、另一个是零点几,距离完全被大尺度特征支配,γ 调什么值都没用。

5.2 现象:几万条样本训练直接卡死、内存飙到几十 G

现象:几千条能跑,样本量上万之后内存爆掉,或者跑一晚上还没结束。

原因:核方法要构造 n×n 的核矩阵,n=50000 时就是 20 亿个浮点数,单精度也要 8 GB,再叠加 SMO 的迭代开销,复杂度实际上接近 O(n²) 到 O(n³)。这是对偶问题的固有代价,不是代码写得差。

解决:先问一句“真的需要核吗”。特征维度已经很高(文本 TF-IDF、one-hot 编码)时,线性核往往效果相当,改用线性支持向量机的对偶坐标下降实现,复杂度对样本数近似线性。必须用非线性核的话,考虑 Nyström 近似或者对训练集做分层抽样,再或者换梯度下降类的线性模型加特征交叉。

5.3 现象:预测结果全是同一类

现象:模型不报错,但decision_function对所有输入输出同一个符号,混淆矩阵只有一行。

原因:多半是对偶的等式约束 Σ α_i y_i = 0 在某次更新后被破坏。最常见的是剪辑区间算错,或者 b 的更新用了不在 (0, C) 区间内的支持向量,导致 b 偏到很离谱的位置。另一个可能是数据类别极度不平衡,且 C 给得很小,模型直接选择“全判多数类”这个退化解。

解决:训练完打印 α 的分布,看有多少落在 0、多少落在 (0, C)、多少等于 C。如果非零 α 只来自一个类别,基本可以确认约束被破坏。修好剪辑逻辑后,再用class_weight之类的机制给少数类加权,或者把 C 调大让模型不敢忽略少数类。

5.4 现象:手写的 SMO 一直跑不停,对偶目标还在缓慢下降

现象:迭代了几十万次,α 还在微调,max_passes永远到不了,日志里对偶目标每轮只降一点点。

原因:通常是tol设得过小(比如 1e-8),KKT 违反量永远卡在阈值边缘;或者选点策略太朴素,每次只顺序扫 i、随机选 j,收敛速度被拖慢;也可能是数据没有标准化,核矩阵数值范围跨了好几个数量级,浮点误差让更新量算不准。

解决:tol给 1e-3 到 1e-4 就够了,再小只是浪费算力。选点策略上,外循环优先挑违反 KKT 最严重的样本,内循环挑让 |E_i - E_j| 最大的那个,收敛速度会明显提升。标准化这一步别省,它对 SMO 的数值稳定性影响比想象中大。

5.5 现象:predict_proba 的概率值永远挤在 0.5 附近

现象:决策函数的分数区分度很好,但转成概率之后,所有样本都落在 0.45 到 0.55 之间,看起来毫无信息量。

原因:支持向量机本身不输出概率,只是输出到超平面的带符号距离。概率需要额外拟合一层映射(Platt 缩放),用交叉验证的分数去拟合一个 sigmoid,样本量小或者分数分布集中时,这层映射会严重压缩。另外预测时默认假设各类先验相等,类别不平衡时概率会系统性偏移。

解决:需要概率就接受它是个近似,别拿它做精细的阈值决策。更稳的做法是直接用decision_function的分数排序,用 ROC 曲线选阈值。如果一定要概率,确保做概率标定时用了足够的分层交叉验证,并检查类别先验是否需要手动指定。

6. 间隔、核与 C 的三角权衡:支持向量机什么时候还值得选

支持向量机的设计核心,用一句话概括:它用“间隔”而不是“参数数量”来控制模型复杂度。神经网络靠层数和宽度约束假设空间,树模型靠深度和叶子数,支持向量机则直接把“边界到最近样本的距离”写进目标函数,让模型自己去找最稳的那条线。这个视角解释了它为什么在小样本、高维、需要可复现结果的场景里依然能打:样本少的时候,参数数量那套复杂度度量失效,而间隔是可估计的。

代价也来自同一个地方。对偶问题的规模是样本数的平方,核矩阵必须能放进内存,这是硬性上限;核技巧把非线性转到相似度上,换来的是模型不再提供特征重要性,解释性弱于线性模型和树模型;概率输出要靠后处理拟合,天然不如直接建模概率的方法自然。这三条决定了它的适用边界:样本量中等偏小、特征维度高、边界非线性但光滑、需要稳定可复现的结果,这几个条件同时成立时它仍然是最好的选择之一。

一个我自己常用的验证习惯:训练完先看支持向量占总样本的比例。比例在 10% 到 30% 之间,说明间隔和容错处在合理区间;逼近 100%,多半是 C 太小或者 γ 太大,模型在硬扛噪声;只有个位数,检查一下是不是数据几乎线性可分,那线性核可能就够了,没必要上核函数。再看对偶目标随迭代的下降曲线,如果几百轮之后还在明显下降,说明停机阈值太松或者选点策略有问题,不是数据的问题。

那张“C 大就过拟合、γ 大就绕圈”的对照表,我最初是当口诀背的,直到有一次在一份标准化漏做一半的数据上把 C 从 1 调到 1000,测试集指标纹丝不动,才发现参数根本不是主要矛盾。从那以后我每次拿到新数据,第一件事都是先标准化、再画一遍特征量纲分布、最后才动 C 和 γ。希望帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/29 11:15:20

C# WinForms 自绘仪表控件:圆表、直表、旋钮、开关与指示灯实战

简介&#xff1a;这份资源面向 C# 桌面开发与工控组态界面设计的学习者&#xff0c;聚焦模拟真实设备的仪表控件实践。围绕圆表、直表&#xff08;测量标尺&#xff09;、旋钮、开关与指示灯等常见控件&#xff0c;给出可运行的示例工程与配套 ActiveX 组件&#xff0c;解决了自…

作者头像 李华
网站建设 2026/10/29 11:15:17

Java Web数据库系统应用开发:Spring Boot+MyBatis实例

简介&#xff1a;《Java Web数据库系统应用开发与实例》配套包面向希望系统掌握Java Web与数据库开发的学习者&#xff0c;内容覆盖Servlet、JSP、JDBC、MVC设计模式、Tomcat部署以及SQL增删改查等核心知识&#xff0c;适合高校课程设计、毕业设计入门和自学者补齐项目经验。压…

作者头像 李华
网站建设 2026/10/29 11:14:19

DeepSeek提示词到智能体:V3/R1分流、RTGO与CAP实践

简介&#xff1a;围绕DeepSeek在职场中的落地应用&#xff0c;这份PDF文档从提示语设计延伸到多场景实践与智能体协作&#xff0c;面向具备一定技术基础的研发人员、工程师、设计师、产品经理及关注人机协同的管理者&#xff0c;帮助读者理解大模型能力边界&#xff0c;并把提示…

作者头像 李华
网站建设 2026/10/29 11:13:07

2G 内存跑全栈监控,为什么你的容器总在半夜被“暗杀”?

背景 你的服务器上跑着 MariaDB、两个 Flask 实例、Kuma 和 Adminer,一共 5 个容器。 某天早上醒来,打开监控大屏,发现一片红,微信收到一堆“服务不可用”的告警。你赶紧 SSH 登录服务器,敲下 docker ps -a,发现有几个容器的状态变成了 Exited (137)。 你查了容器的日志…

作者头像 李华
网站建设 2026/10/29 11:12:27

软件测试-UI自动化-面试题2

请简述 Web 自动化测试执行过程中&#xff0c;为了提高测试效率/成功率采取了哪些措施&#xff1f;主要从以下几个方面提高 Web 自动化测试的效率和成功率&#xff1a;优化等待机制&#xff1a; 使用显式等待&#xff0c;等待元素加载完成后再操作&#xff0c;减少因页面加载不…

作者头像 李华